Attempt to improve areaportal support. now networked (so visible clientside), but will probably break anyway, if doors open before players join. should also block some rtlights, although perhaps not completely.

disable the use of quakespy stuff, using a dynamic port and no stuffcmds from random ip addresses and no mutex.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4676 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2014-06-02 16:50:40 +00:00
parent c841b4fbd1
commit c415ead7d8
20 changed files with 192 additions and 130 deletions

View file

@ -94,12 +94,14 @@ cvar_t cl_loopbackprotocol = CVARD("cl_loopbackprotocol", "qw", "Which protocol
cvar_t cl_threadedphysics = CVAR("cl_threadedphysics", "0");
#ifdef QUAKESPYAPI
cvar_t localid = SCVAR("localid", "");
static qboolean allowremotecmd = true;
#endif
cvar_t r_drawflame = CVARD("r_drawflame", "1", "Set to -1 to disable ALL static entities. Set to 0 to disable only wall torches and standing flame. Set to 1 for everything drawn as normal.");
qboolean forcesaveprompt;
static qboolean allowremotecmd = true;
extern int total_loading_size, current_loading_size, loading_stage;
@ -2760,7 +2762,9 @@ client_connect: //fixme: make function
cls.state = ca_connected;
if (cls.netchan.remote_address.type != NA_LOOPBACK)
Con_TPrintf ("Connected.\n");
#ifdef QUAKESPYAPI
allowremotecmd = false; // localid required now for remote cmds
#endif
total_loading_size = 100;
current_loading_size = 0;
@ -2770,6 +2774,7 @@ client_connect: //fixme: make function
return;
}
#ifdef QUAKESPYAPI
// remote command from gui front end
if (c == A2C_CLIENT_COMMAND) //man I hate this.
{
@ -2815,6 +2820,7 @@ client_connect: //fixme: make function
allowremotecmd = false;
return;
}
#endif
// print command from somewhere
if (c == 'p')
{
@ -2910,7 +2916,9 @@ void CLNQ_ConnectionlessPacket(void)
current_loading_size = 0;
SCR_SetLoadingStage(LS_CLIENT);
#ifdef QUAKESPYAPI
allowremotecmd = false; // localid required now for remote cmds
#endif
//send a dummy packet.
//this makes our local nat think we initialised the conversation.
@ -3476,7 +3484,9 @@ void CL_Init (void)
Cvar_Register (&cl_predict_players_frac, cl_predictiongroup);
Cvar_Register (&cl_solid_players, cl_predictiongroup);
#ifdef QUAKESPYAPI
Cvar_Register (&localid, cl_controlgroup);
#endif
Cvar_Register (&cl_muzzleflash, cl_controlgroup);
@ -4724,9 +4734,10 @@ void CL_ExecInitialConfigs(char *resetcommand)
Cbuf_AddText ("exec autoexec.cfg\n", RESTRICT_LOCAL);
}
Cbuf_AddText ("exec fte.cfg\n", RESTRICT_LOCAL);
#ifdef QUAKESPYAPI
if (COM_FCheckExists ("frontend.cfg"))
Cbuf_AddText ("exec frontend.cfg\n", RESTRICT_LOCAL);
#endif
Cbuf_AddText ("cl_warncmd 1\n", RESTRICT_LOCAL); //and then it's allowed to start moaning.
com_parseutf8.ival = com_parseutf8.value;

View file

@ -5375,6 +5375,43 @@ void CL_DumpPacket(void)
}
}
void CL_ParsePortalState(void)
{
qboolean open = false;
int mode = MSG_ReadByte();
int a1, a2;
switch(mode)
{
case 0x80:
if (mode&2)
a1 = MSG_ReadShort();
else
a1 = MSG_ReadByte();
CMQ2_SetAreaPortalState(a1, !!(mode&1));
break;
case 0xc0:
if (mode&2)
{
a1 = MSG_ReadShort();
a2 = MSG_ReadShort();
}
else
{
a1 = MSG_ReadByte();
a2 = MSG_ReadByte();
}
CMQ3_SetAreaPortalState(a1, a2, !!(mode&1));
break;
default:
//to be phased out.
mode |= MSG_ReadByte()<<8;
CMQ2_SetAreaPortalState(mode & 0x7fff, !!(mode&0x8000));
break;
}
}
#define SHOWNET(x) if(cl_shownet.value>=2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
#define SHOWNET2(x, y) if(cl_shownet.value>=2)Con_Printf ("%3i:%3i:%s\n", msg_readcount-1, y, x);
/*
@ -5855,15 +5892,9 @@ void CLQW_ParseServerMessage (void)
// case svc_ftesetclientpersist:
// CL_ParseClientPersist();
// break;
#ifdef Q2BSPS
case svc_setportalstate:
i = MSG_ReadByte();
j = MSG_ReadByte();
i *= j & 127;
j &= ~128;
CMQ2_SetAreaPortalState(i, j!=0);
CL_ParsePortalState();
break;
#endif
case svcfte_showpic:
SCR_ShowPic_Create();

View file

@ -640,7 +640,8 @@ static void CL_ClearExplosion(explosion_t *exp, vec3_t org)
VectorClear(exp->velocity);
VectorClear(exp->angles);
VectorClear(exp->avel);
P_DelinkTrailstate(&(exp->trailstate));
if (pe)
P_DelinkTrailstate(&(exp->trailstate));
exp->traileffect = P_INVALID;
VectorCopy(org, exp->origin);
VectorCopy(org, exp->oldorigin);

View file

@ -577,6 +577,7 @@ struct q3refdef_s {
void D3D9_Set2D (void);
void VQ3_RenderView(const q3refdef_t *ref)
{
int i;
extern cvar_t r_torch;
VectorCopy(ref->vieworg, r_refdef.vieworg);
r_refdef.viewangles[0] = -(atan2(ref->viewaxis[0][2], sqrt(ref->viewaxis[0][1]*ref->viewaxis[0][1]+ref->viewaxis[0][0]*ref->viewaxis[0][0])) * 180 / M_PI);
@ -610,7 +611,9 @@ void VQ3_RenderView(const q3refdef_t *ref)
VectorCopy(ref->viewaxis[2], dl->axis[2]);
}
memcpy(cl.q2frame.areabits, ref->areamask, sizeof(cl.q2frame.areabits));
r_refdef.areabitsknown = true;
for (i = 0; i < sizeof(cl.q2frame.areabits)/sizeof(int); i++)
((int*)r_refdef.areabits)[i] = ((int*)ref->areamask)[i] ^ ~0;
R_RenderView();
r_refdef.playerview = NULL;
#ifdef GLQUAKE

View file

@ -1836,6 +1836,9 @@ void CLQ2_CalcViewValues (void)
q2player_state_t *ps, *ops;
extern cvar_t gl_cshiftenabled;
r_refdef.areabitsknown = true;
memcpy(r_refdef.areabits, cl.q2frame.areabits, sizeof(r_refdef.areabits));
r_refdef.useperspective = true;
// find the previous frame to interpolate from

View file

@ -3468,9 +3468,7 @@ static void QCBUILTIN PF_cs_OpenPortal (pubprogfuncs_t *prinst, struct globalvar
#ifdef Q3BSPS
if (cl.worldmodel->fromgame == fg_quake3)
{
int i;
int state = G_FLOAT(OFS_PARM1)!=0;
client_t *client;
edict_t *portal = G_EDICT(prinst, OFS_PARM0);
int area1 = portal->pvsinfo.areanum, area2 = portal->pvsinfo.areanum2;
if (area1 == area2 || !area1 || !area2)

View file

@ -30,7 +30,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern cvar_t r_ambient;
static vec3_t modelorg; /*set before recursively entering the visible surface finder*/
static qbyte areabits[MAX_Q2MAP_AREAS/8];
model_t *currentmodel;
@ -1634,11 +1633,12 @@ static void Surf_RecursiveQ2WorldNode (mnode_t *node)
pleaf = (mleaf_t *)node;
// check for door connected areas
// if (areabits)
{
if (! (areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) )
return; // not visible
}
if (! (r_refdef.areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) )
return; // not visible
c = pleaf->cluster;
if (c >= 0)
frustumvis[c>>3] |= 1<<(c&7);
mark = pleaf->firstmarksurface;
c = pleaf->nummarksurfaces;
@ -1698,7 +1698,7 @@ static void Surf_RecursiveQ2WorldNode (mnode_t *node)
if ( (surf->flags & SURF_PLANEBACK) != sidebit )
continue; // wrong side
surf->visframe = r_framecount+1;//-1;
surf->visframe = 0;//r_framecount+1;//-1;
Surf_RenderDynamicLightmaps (surf);
@ -1830,9 +1830,13 @@ start:
{
pleaf = (mleaf_t *)node;
if (! (areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) )
if (! (r_refdef.areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) )
return; // not visible
c = pleaf->cluster;
if (c >= 0)
frustumvis[c>>3] |= 1<<(c&7);
mark = pleaf->firstmarksurface;
for (c = pleaf->nummarksurfaces; c; c--)
{
@ -2286,19 +2290,15 @@ void Surf_DrawWorld (void)
#ifdef Q2BSPS
if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3)
{
int leafnum;
int clientarea;
#ifdef Q2CLIENT
if (cls.protocol == CP_QUAKE2) //we can get server sent info
{
memcpy(areabits, cl.q2frame.areabits, sizeof(areabits));
}
else
#endif
{ //generate the info each frame.
leafnum = CM_PointLeafnum (cl.worldmodel, r_refdef.vieworg);
clientarea = CM_LeafArea (cl.worldmodel, leafnum);
CM_WriteAreaBits(cl.worldmodel, areabits, clientarea);
frustumvis = frustumvis_;
memset(frustumvis, 0, (cl.worldmodel->numclusters + 7)>>3);
if (!r_refdef.areabitsknown)
{ //generate the info each frame, as the gamecode didn't tell us what to use.
int leafnum = CM_PointLeafnum (cl.worldmodel, r_refdef.vieworg);
int clientarea = CM_LeafArea (cl.worldmodel, leafnum);
CM_WriteAreaBits(cl.worldmodel, r_refdef.areabits, clientarea);
r_refdef.areabitsknown = true;
}
#ifdef Q3BSPS
if (cl.worldmodel->fromgame == fg_quake3)
@ -2314,6 +2314,8 @@ void Surf_DrawWorld (void)
VectorCopy (r_refdef.vieworg, modelorg);
Surf_RecursiveQ2WorldNode (cl.worldmodel->nodes);
}
surfvis = frustumvis;
}
else
#endif
@ -2351,7 +2353,7 @@ void Surf_DrawWorld (void)
VectorCopy (r_origin, modelorg);
frustumvis = frustumvis_;
memset(frustumvis, 0, (cl.worldmodel->numleafs + 7)>>3);
memset(frustumvis, 0, (cl.worldmodel->numclusters + 7)>>3);
if (r_refdef.useperspective)
Surf_RecursiveWorldNode (cl.worldmodel->nodes, 0x1f);

View file

@ -236,6 +236,8 @@ typedef struct
int rt_ripplemap; /*read by 2d. used by 3d (internal ripplemap buffer used if not set)*/
qbyte *forcedvis;
qboolean areabitsknown;
qbyte areabits[MAX_MAP_AREA_BYTES];
struct
{

View file

@ -1337,6 +1337,7 @@ void Sys_Init (void)
Cvar_Register(&sys_disableTaskSwitch, "System vars");
Cmd_AddCommandD("sys_register_file_associations", Sys_Register_File_Associations_f, "Register FTE as the system handler for .bsp .mvd .qwd .dem files. Also register the qw:// URL protocol. This command will probably trigger a UAC prompt in Windows Vista and up. Deny it for current-user-only asociations (will also prevent listing in windows' 'default programs' ui due to microsoft bugs/limitations).");
#ifdef QUAKESPYAPI
#ifndef CLIENTONLY
if (!isDedicated && !COM_CheckParm("-nomutex"))
#else
@ -1362,6 +1363,7 @@ void Sys_Init (void)
"qwcl"); // Semaphore name
}
#endif
#endif
#if 0
if (!QueryPerformanceFrequency (&PerformanceFreq))

View file

@ -1209,6 +1209,8 @@ void V_ClearRefdef(playerview_t *pv)
r_refdef.drawsbar = !cl.intermission;
r_refdef.flags = 0;
r_refdef.areabitsknown = false;
// memset(r_refdef.postprocshader, 0, sizeof(r_refdef.postprocshader));
// memset(r_refdef.postprocsize, 0, sizeof(r_refdef.postprocsize));
// r_refdef.postproccube = 0;

View file

@ -264,12 +264,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#if defined(_WIN32) && !defined(MULTITHREAD) //always thread on win32 non-minimal builds
#define MULTITHREAD
#endif
//these things were moved to plugins.
#endif
#endif
//#define QUAKESPYAPI //define this if you want the engine to be usable via gamespy/quakespy, which has been dead for a long time now.
#ifdef FTE_TARGET_WEB
//try to trim the fat
#undef VOICECHAT //too lazy to compile speex

View file

@ -6091,7 +6091,6 @@ AREAPORTALS
static void FloodArea_r (q2carea_t *area, int floodnum)
{
int i;
q2dareaportal_t *p;
if (area->floodvalid == floodvalid)
{
@ -6102,11 +6101,22 @@ static void FloodArea_r (q2carea_t *area, int floodnum)
area->floodnum = floodnum;
area->floodvalid = floodvalid;
p = &map_areaportals[area->firstareaportal];
for (i=0 ; i<area->numareaportals ; i++, p++)
if (mapisq3)
{
if (portalopen[p->portalnum])
FloodArea_r (&map_q2areas[p->otherarea], floodnum);
for (i=1 ; i<numareas ; i++)
{
if (map_q3areas[area - map_q2areas].numareaportals[i]>0)
FloodArea_r (&map_q2areas[i], floodnum);
}
}
else
{
q2dareaportal_t *p = &map_areaportals[area->firstareaportal];
for (i=0 ; i<area->numareaportals ; i++, p++)
{
if (portalopen[p->portalnum])
FloodArea_r (&map_q2areas[p->otherarea], floodnum);
}
}
}
@ -6119,22 +6129,10 @@ FloodAreaConnections
*/
static void FloodAreaConnections (void)
{
int i, j;
int i;
q2carea_t *area;
int floodnum;
if (mapisq3)
{
// area 0 is not used
for (i=1 ; i<numareas ; i++)
{
for ( j = 1; j < numareas; j++ ) {
map_q3areas[i].numareaportals[j] = ( j == i );
}
}
return;
}
// all current floods are now invalid
floodvalid++;
floodnum = 0;
@ -6151,7 +6149,7 @@ static void FloodAreaConnections (void)
}
void VARGS CMQ2_SetAreaPortalState (int portalnum, qboolean open)
void VARGS CMQ2_SetAreaPortalState (unsigned int portalnum, qboolean open)
{
if (mapisq3)
return;
@ -6166,7 +6164,7 @@ void VARGS CMQ2_SetAreaPortalState (int portalnum, qboolean open)
return;
}
void CMQ3_SetAreaPortalState (int area1, int area2, qboolean open)
void CMQ3_SetAreaPortalState (unsigned int area1, unsigned int area2, qboolean open)
{
if (!mapisq3)
return;
@ -6185,9 +6183,11 @@ void CMQ3_SetAreaPortalState (int area1, int area2, qboolean open)
map_q3areas[area1].numareaportals[area2]--;
map_q3areas[area2].numareaportals[area1]--;
}
FloodAreaConnections();
}
qboolean VARGS CM_AreasConnected (model_t *mod, int area1, int area2)
qboolean VARGS CM_AreasConnected (model_t *mod, unsigned int area1, unsigned int area2)
{
if (map_noareas.value)
return true;
@ -6195,21 +6195,8 @@ qboolean VARGS CM_AreasConnected (model_t *mod, int area1, int area2)
if (area1 > numareas || area2 > numareas)
Host_Error ("area > numareas");
if (mapisq3)
{
int i;
for (i=1 ; i<numareas ; i++)
{
if ( map_q3areas[i].numareaportals[area1] &&
map_q3areas[i].numareaportals[area2] )
return true;
}
}
else
{
if (map_q2areas[area1].floodnum == map_q2areas[area2].floodnum)
return true;
}
if (map_q2areas[area1].floodnum == map_q2areas[area2].floodnum)
return true;
return false;
}
@ -6240,41 +6227,17 @@ int CM_WriteAreaBits (model_t *mod, qbyte *buffer, int area)
{
memset (buffer, 0, bytes);
if (mapisq3)
floodnum = map_q2areas[area].floodnum;
for (i=1 ; i<numareas ; i++)
{
for (i=0 ; i<numareas ; i++)
{
if (!area || CM_AreasConnected (mod, i, area ) || i == area)
buffer[i>>3] |= 1<<(i&7);
}
}
else
{
floodnum = map_q2areas[area].floodnum;
for (i=0 ; i<numareas ; i++)
{
if (map_q2areas[i].floodnum == floodnum || !area)
buffer[i>>3] |= 1<<(i&7);
}
if (map_q2areas[i].floodnum == floodnum || !area)
buffer[i>>3] |= 1<<(i&7);
}
}
return bytes;
}
#ifndef CLIENTONLY
void CM_InitPortalState(void)
{
int i;
//if we're not running q2, force all q2 portals open.
if (svs.gametype != GT_QUAKE2 && !mapisq3)
{
for (i = 0; i < numareas; i++)
map_q2areas[i].floodnum = 0;
}
}
#endif
/*
===================
CM_WritePortalState

View file

@ -2537,7 +2537,7 @@ qboolean NET_PortToAdr (int adrfamily, const char *s, netadr_t *a)
port = strtoul(s, &e, 10);
if (*e) //if *e then its not just a single number in there, so treat it as a proper address.
return NET_StringToAdr(s, 0, a);
else if (port)
else if (e != s) //if we actually read something (even a 0)
{
memset(a, 0, sizeof(*a));
a->port = htons((unsigned short)port);
@ -2662,7 +2662,7 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i
//
// determine my name & address if we don't already know it
//
if (net_local_cl_ipadr.type == NA_INVALID)
if (!isserver && net_local_cl_ipadr.type == NA_INVALID)
NET_GetLocalAddress (newsocket, &net_local_cl_ipadr);
newcon = Z_Malloc(sizeof(*newcon));
@ -5362,10 +5362,10 @@ void NET_GetLocalAddress (int socket, netadr_t *out)
if (!notvalid)
{
Con_TPrintf("IP address %s\n", NET_AdrToString (adrbuf, sizeof(adrbuf), out) );
// Con_TPrintf("Client IP address %s\n", NET_AdrToString (adrbuf, sizeof(adrbuf), out) );
return;
}
Con_Printf("Couldn't detect local ip\n");
// Con_Printf("Couldn't detect local ip\n");
#endif
out->type = NA_INVALID;
@ -5492,7 +5492,12 @@ void NET_InitClient(void)
{
const char *port;
int p;
#ifdef QUAKESPYAPI
port = STRINGIFY(PORT_QWCLIENT);
#else
port = "0";
#endif
p = COM_CheckParm ("-clport");
if (p && p < com_argc)
@ -5520,7 +5525,7 @@ void NET_InitClient(void)
net_message.maxsize = sizeof(net_message_buffer);
net_message.data = net_message_buffer;
Con_TPrintf("Client port Initialized\n");
// Con_TPrintf("Client port Initialized\n");
}
#endif

View file

@ -266,7 +266,7 @@ public class FTEDroidActivity extends Activity
public void run()
{
theview.setVisibility(theview.GONE);
AlertDialog ad = new AlertDialog.Builder(act);
AlertDialog ad = new AlertDialog.Builder(act).create();
ad.setTitle("FTE ERROR");
ad.setMessage(errormsg);
ad.setCancelable(false);

View file

@ -1002,7 +1002,7 @@ void CM_Init(void);
qboolean CM_SetAreaPortalState (struct model_s *mod, int portalnum, qboolean open);
qboolean CM_HeadnodeVisible (struct model_s *mod, int nodenum, qbyte *visbits);
qboolean VARGS CM_AreasConnected (struct model_s *mod, int area1, int area2);
qboolean VARGS CM_AreasConnected (struct model_s *mod, unsigned int area1, unsigned int area2);
int CM_NumClusters (struct model_s *mod);
int CM_ClusterSize (struct model_s *mod);
int CM_LeafContents (struct model_s *mod, int leafnum);
@ -1019,8 +1019,8 @@ int CM_HeadnodeForBox (struct model_s *mod, vec3_t mins, vec3_t maxs);
struct trace_s CM_TransformedBoxTrace (struct model_s *mod, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, int brushmask, vec3_t origin, vec3_t angles);
struct model_s *CM_TempBoxModel(vec3_t mins, vec3_t maxs);
void VARGS CMQ2_SetAreaPortalState (int portalnum, qboolean open);
void CMQ3_SetAreaPortalState (int area1, int area2, qboolean open);
void VARGS CMQ2_SetAreaPortalState (unsigned int portalnum, qboolean open);
void CMQ3_SetAreaPortalState (unsigned int area1, unsigned int area2, qboolean open);
#endif

View file

@ -296,14 +296,30 @@ cl_expsprite 0
//r_effect "progs/s_explod.spr" hidden 1
//////////////////////////////////////////
//for when a spawn dies.
//also used by TF for emp explosions.
//r_part te_tarexplosion
//{
//}
//////////////////////////////////////////
//r_part te_lavasplash
//{
//}
//cthon falling into lava.
//often also used for TF gas grenades.
r_part te_lavasplash
{
texture "particles/fteparticlefont.tga"
tcoords 129 1 191 63 256
count 654
scale 15
alpha 0.7
die 4
randomvel 64
rgb 255 128 128
gravity 50
blend add
spawnorg 192 64
up 48
}
//////////////////////////////////////////
//FIXME: what if we don't have glsl support?

View file

@ -6224,9 +6224,9 @@ static void QCBUILTIN PF_log(pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
}
#ifdef Q2BSPS
static void QCBUILTIN PF_OpenPortal (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
#ifdef Q2BSPS
if (sv.world.worldmodel->fromgame == fg_quake2)
{
int i, portal;
@ -6240,16 +6240,29 @@ static void QCBUILTIN PF_OpenPortal (pubprogfuncs_t *prinst, struct globalvars_s
{
if (client->state >= cs_connected)
{
ClientReliableWrite_Begin(client, svc_setportalstate, 3);
if (state)
ClientReliableWrite_Short(client, portal | (state<<15));
ClientReliableWrite_Begin(client, svc_setportalstate, 4);
if (portal >= 0x80)
{ //new pathway, to be enabled at some point
if (portal > 0xff)
{
ClientReliableWrite_Byte(client, 0x80 | 2 | state);
ClientReliableWrite_Short(client, portal);
}
else
{
ClientReliableWrite_Byte(client, 0x80 | 0 | state);
ClientReliableWrite_Byte(client, portal);
}
}
else
ClientReliableWrite_Short(client, portal);
ClientReliableWrite_Short(client, portal | (state<<15));
}
}
CMQ2_SetAreaPortalState(portal, state);
}
else if (sv.world.worldmodel->fromgame == fg_quake3)
#endif
#ifdef Q3BSPS
if (sv.world.worldmodel->fromgame == fg_quake3)
{
int i;
int state = G_FLOAT(OFS_PARM1)!=0;
@ -6258,21 +6271,29 @@ static void QCBUILTIN PF_OpenPortal (pubprogfuncs_t *prinst, struct globalvars_s
int area1 = portal->pvsinfo.areanum, area2 = portal->pvsinfo.areanum2;
if (area1 == area2 || !area1 || !area2)
return;
/*for (client = svs.clients, i = 0; i < sv.allocated_client_slots; i++, client++)
for (client = svs.clients, i = 0; i < sv.allocated_client_slots; i++, client++)
{
if (client->state >= cs_connected)
{
ClientReliableWrite_Begin(client, svc_setportalstate, 3);
if (state)
ClientReliableWrite_Short(client, portal | (state<<15));
ClientReliableWrite_Begin(client, svc_setportalstate, 6);
if (area1 > 0xff || area2 > 0xff)
{
ClientReliableWrite_Byte(client, 0xc0 | 2 | state);
ClientReliableWrite_Short(client, area1);
ClientReliableWrite_Short(client, area2);
}
else
ClientReliableWrite_Short(client, portal);
{
ClientReliableWrite_Byte(client, 0x80 | 0 | state);
ClientReliableWrite_Byte(client, area1);
ClientReliableWrite_Byte(client, area2);
}
}
}*/
}
CMQ3_SetAreaPortalState(portal->pvsinfo.areanum, portal->pvsinfo.areanum2, state);
}
}
#endif
}
//EXTENSION: DP_QC_COPYENTITY

View file

@ -209,8 +209,8 @@ typedef struct
int (VARGS *pointcontents) (vec3_t point);
qboolean (VARGS *inPVS) (vec3_t p1, vec3_t p2);
qboolean (VARGS *inPHS) (vec3_t p1, vec3_t p2);
void (VARGS *SetAreaPortalState) (int portalnum, qboolean open);
qboolean (VARGS *AreasConnected) (int area1, int area2);
void (VARGS *SetAreaPortalState) (unsigned int portalnum, qboolean open);
qboolean (VARGS *AreasConnected) (unsigned int area1, unsigned int area2);
// an entity will never be sent to a client or used for collision
// if it is not passed to linkentity. If the size, position, or

View file

@ -452,7 +452,7 @@ static qboolean VARGS PFQ2_inPHS (vec3_t p1, vec3_t p2)
return true;
}
qboolean VARGS PFQ2_AreasConnected(int area1, int area2)
qboolean VARGS PFQ2_AreasConnected(unsigned int area1, unsigned int area2)
{
//FIXME: requires q2/q3 bsp
return CM_AreasConnected(sv.world.worldmodel, area1, area2);

View file

@ -283,7 +283,7 @@ static void Q3G_LinkEntity(q3sharedEntity_t *ent)
{
clusters[i] = CM_LeafCluster(sv.world.worldmodel, leafs[i]);
area = CM_LeafArea(sv.world.worldmodel, leafs[i]);
if(area >= 0)
if(area > 0) //FIXME: this should be >=
{
// doors may legally straggle two areas,
// but nothing should ever need more than that
@ -752,6 +752,8 @@ static int SVQ3_BotGetSnapshotEntity(int client, int entnum)
static void SVQ3_Adjust_Area_Portal_State(q3sharedEntity_t *ge, qboolean open)
{
q3serverEntity_t *se = SENTITY_FOR_GENTITY(ge);
if (se->areanum == -1 || se->areanum2 == -1) //not linked properly.
return;
CMQ3_SetAreaPortalState(se->areanum, se->areanum2, open);
}