18 Jan 2008
This commit is contained in:
parent
a5ca5ac292
commit
b3fa6d6dbd
|
@ -12,7 +12,6 @@ fopen
|
|||
|
||||
// замеченные баги
|
||||
1. viewer ничего не пишет в лог (сцуко)
|
||||
2. Модели не рисуются для неотвизеных карт (даже самых мелких)
|
||||
|
||||
// из неоконченного
|
||||
0. Приделать бы всем утилитам разные иконки
|
||||
|
@ -35,7 +34,8 @@ physic.dll
|
|||
12.Подключить его к серверу и клиенту OK
|
||||
13.Билдер коллижн мешей для бсп-моделей OK
|
||||
14.Переписать трасинг OK
|
||||
15.Доделать трасинг
|
||||
15.Доделать трасинг OK
|
||||
16.Переписать pmove
|
||||
}
|
||||
|
||||
Создание sdk_main
|
||||
|
|
|
@ -106,7 +106,7 @@ void CL_ClipMoveToEntities ( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end,
|
|||
}
|
||||
if( tr->allsolid ) return;
|
||||
|
||||
trace = pe->TransformedBoxTrace( start, end, mins, maxs, MASK_PLAYERSOLID, ent->origin, angles );
|
||||
trace = pe->TransformedBoxTrace( start, end, mins, maxs, cmodel, MASK_PLAYERSOLID, ent->origin, angles );
|
||||
|
||||
if( trace.allsolid || trace.startsolid || trace.fraction < tr->fraction )
|
||||
{
|
||||
|
@ -133,7 +133,7 @@ trace_t CL_PMTrace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
|
|||
trace_t t;
|
||||
|
||||
// check against world
|
||||
t = pe->BoxTrace( start, end, mins, maxs, MASK_PLAYERSOLID );
|
||||
t = pe->BoxTrace( start, end, mins, maxs, NULL, MASK_PLAYERSOLID );
|
||||
if (t.fraction < 1.0) t.ent = (edict_t *)1;
|
||||
|
||||
// check all other solid models
|
||||
|
@ -142,15 +142,15 @@ trace_t CL_PMTrace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
|
|||
return t;
|
||||
}
|
||||
|
||||
int CL_PMpointcontents (vec3_t point)
|
||||
int CL_PMpointcontents( vec3_t point )
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
entity_state_t *ent;
|
||||
int num;
|
||||
int num;
|
||||
cmodel_t *cmodel;
|
||||
int contents;
|
||||
int contents;
|
||||
|
||||
contents = pe->PointContents( point );
|
||||
contents = pe->PointContents( point, NULL );
|
||||
|
||||
for( i = 0; i < cl.frame.num_entities; i++ )
|
||||
{
|
||||
|
@ -163,7 +163,7 @@ int CL_PMpointcontents (vec3_t point)
|
|||
cmodel = cl.model_clip[ent->modelindex];
|
||||
if (!cmodel) continue;
|
||||
|
||||
contents |= pe->TransformedPointContents( point, ent->origin, ent->angles );
|
||||
contents |= pe->TransformedPointContents( point, cmodel, ent->origin, ent->angles );
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
|
|
@ -30,19 +30,26 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t origin; // full float precision
|
||||
vec3_t velocity; // full float precision
|
||||
vec3_t origin;
|
||||
vec3_t velocity;
|
||||
vec3_t previous_origin;
|
||||
vec3_t previous_velocity;
|
||||
int previous_waterlevel;
|
||||
|
||||
vec3_t forward, right, up;
|
||||
float frametime;
|
||||
int msec;
|
||||
|
||||
bool walking;
|
||||
bool onladder;
|
||||
trace_t groundtrace;
|
||||
float impact_speed;
|
||||
|
||||
csurface_t *groundsurface;
|
||||
cplane_t groundplane;
|
||||
int groundcontents;
|
||||
|
||||
vec3_t previous_origin;
|
||||
bool ladder;
|
||||
|
||||
} pml_t;
|
||||
|
||||
pmove_t *pm;
|
||||
|
@ -81,14 +88,15 @@ void PM_ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
|
|||
float change;
|
||||
int i;
|
||||
|
||||
backoff = DotProduct (in, normal) * overbounce;
|
||||
backoff = DotProduct (in, normal);
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
if( backoff < 0 ) backoff *= overbounce;
|
||||
else backoff /= overbounce;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
change = normal[i]*backoff;
|
||||
out[i] = in[i] - change;
|
||||
if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
|
||||
out[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,48 +294,47 @@ Handles both ground friction and water friction
|
|||
==================
|
||||
*/
|
||||
|
||||
void PM_Friction (void)
|
||||
void PM_Friction( void )
|
||||
{
|
||||
vec3_t vec;
|
||||
float *vel;
|
||||
float speed, newspeed, control;
|
||||
float friction;
|
||||
float drop;
|
||||
|
||||
vel = pml.velocity;
|
||||
|
||||
speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1] + vel[2]*vel[2]);
|
||||
if (speed < 1)
|
||||
|
||||
VectorCopy( vel, vec );
|
||||
if( pml.walking ) vec[2] = 0; // ignore slope movement
|
||||
|
||||
speed = VectorLength( vec );
|
||||
Msg("speed %g\n", speed );
|
||||
if( speed < 1 )
|
||||
{
|
||||
vel[0] = 0;
|
||||
vel[1] = 0;
|
||||
vel[0] = vel[1] = 0; // allow sinking underwater
|
||||
// FIXME: still have z friction underwater?
|
||||
return;
|
||||
}
|
||||
|
||||
drop = 0;
|
||||
|
||||
// apply ground friction
|
||||
if ((pm->groundentity && pml.groundsurface && !(pml.groundsurface->flags & SURF_SLICK) ) || (pml.ladder) )
|
||||
if( pm->waterlevel <= 1 )
|
||||
{
|
||||
friction = pm_friction;
|
||||
control = speed < pm_stopspeed ? pm_stopspeed : speed;
|
||||
drop += control*friction*pml.frametime;
|
||||
if( pml.walking && !(pml.groundtrace.flags & SURF_SLICK) || (pml.onladder))
|
||||
{
|
||||
control = speed < pm_stopspeed ? pm_stopspeed : speed;
|
||||
drop += control * pm_friction * pml.frametime;
|
||||
}
|
||||
}
|
||||
|
||||
// apply water friction
|
||||
if (pm->waterlevel && !pml.ladder)
|
||||
drop += speed*pm_waterfriction*pm->waterlevel*pml.frametime;
|
||||
if( pm->waterlevel && !pml.onladder ) drop += speed * pm_waterfriction * pm->waterlevel * pml.frametime;
|
||||
|
||||
// scale the velocity
|
||||
newspeed = speed - drop;
|
||||
if (newspeed < 0)
|
||||
{
|
||||
newspeed = 0;
|
||||
}
|
||||
if (newspeed < 0) newspeed = 0;
|
||||
newspeed /= speed;
|
||||
|
||||
vel[0] = vel[0] * newspeed;
|
||||
vel[1] = vel[1] * newspeed;
|
||||
vel[2] = vel[2] * newspeed;
|
||||
VectorScale( vel, newspeed, vel );
|
||||
}
|
||||
|
||||
|
||||
|
@ -340,19 +347,17 @@ Handles user intended acceleration
|
|||
*/
|
||||
void PM_Accelerate (vec3_t wishdir, float wishspeed, float accel)
|
||||
{
|
||||
int i;
|
||||
float addspeed, accelspeed, currentspeed;
|
||||
int i;
|
||||
float addspeed, accelspeed, currentspeed;
|
||||
|
||||
currentspeed = DotProduct (pml.velocity, wishdir);
|
||||
addspeed = wishspeed - currentspeed;
|
||||
if (addspeed <= 0)
|
||||
return;
|
||||
accelspeed = accel*pml.frametime*wishspeed;
|
||||
if (accelspeed > addspeed)
|
||||
accelspeed = addspeed;
|
||||
if( addspeed <= 0 ) return;
|
||||
accelspeed = accel * pml.frametime * wishspeed;
|
||||
if( accelspeed > addspeed ) accelspeed = addspeed;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
pml.velocity[i] += accelspeed*wishdir[i];
|
||||
for( i = 0; i < 3; i++ )
|
||||
pml.velocity[i] += accelspeed * wishdir[i];
|
||||
}
|
||||
|
||||
void PM_AirAccelerate (vec3_t wishdir, float wishspeed, float accel)
|
||||
|
@ -384,8 +389,8 @@ void PM_AddCurrents (vec3_t wishvel)
|
|||
vec3_t v;
|
||||
float s;
|
||||
|
||||
// account for ladders
|
||||
if (pml.ladder && fabs(pml.velocity[2]) <= 200)
|
||||
// account for onladders
|
||||
if (pml.onladder && fabs(pml.velocity[2]) <= 200)
|
||||
{
|
||||
if ((pm->viewangles[PITCH] <= -15) && (pm->cmd.forwardmove > 0))
|
||||
wishvel[2] = 200;
|
||||
|
@ -397,7 +402,7 @@ void PM_AddCurrents (vec3_t wishvel)
|
|||
wishvel[2] = -200;
|
||||
else wishvel[2] = 0;
|
||||
|
||||
// limit horizontal speed when on a ladder
|
||||
// limit horizontal speed when on a onladder
|
||||
if (wishvel[0] < -25)
|
||||
wishvel[0] = -25;
|
||||
else if (wishvel[0] > 25)
|
||||
|
@ -539,7 +544,7 @@ void PM_AirMove (void)
|
|||
wishspeed = maxspeed;
|
||||
}
|
||||
|
||||
if ( pml.ladder )
|
||||
if ( pml.onladder )
|
||||
{
|
||||
PM_Accelerate (wishdir, wishspeed, pm_accelerate);
|
||||
if (!wishvel[2])
|
||||
|
@ -612,6 +617,7 @@ void PM_CatagorizePosition (void)
|
|||
else
|
||||
{
|
||||
trace = pm->trace (pml.origin, pm->mins, pm->maxs, point);
|
||||
groundtrace = trace;
|
||||
pml.groundplane = trace.plane;
|
||||
pml.groundsurface = trace.surface;
|
||||
pml.groundcontents = trace.contents;
|
||||
|
@ -747,9 +753,9 @@ void PM_CheckSpecialMovement (void)
|
|||
|
||||
if (pm->s.pm_time) return;
|
||||
|
||||
pml.ladder = false;
|
||||
pml.onladder = false;
|
||||
|
||||
// check for ladder
|
||||
// check for onladder
|
||||
flatforward[0] = pml.forward[0];
|
||||
flatforward[1] = pml.forward[1];
|
||||
flatforward[2] = 0;
|
||||
|
@ -758,7 +764,7 @@ void PM_CheckSpecialMovement (void)
|
|||
VectorMA (pml.origin, 1, flatforward, spot);
|
||||
trace = pm->trace (pml.origin, pm->mins, pm->maxs, spot);
|
||||
if ((trace.fraction < 1) && (trace.contents & CONTENTS_LADDER))
|
||||
pml.ladder = true;
|
||||
pml.onladder = true;
|
||||
|
||||
// check for water jump
|
||||
if (pm->waterlevel != 2) return;
|
||||
|
@ -964,6 +970,7 @@ bool PM_GoodPosition (void)
|
|||
|
||||
for (i = 0; i < 3; i++) origin[i] = end[i] = pm->s.origin[i] * CL_COORD_FRAC;
|
||||
trace = pm->trace (origin, pm->mins, pm->maxs, end);
|
||||
pml.groundtrace = trace;
|
||||
|
||||
return !trace.allsolid;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define FL_WORLDBRUSH (1<<3) // Not moveable/removeable brush entity
|
||||
#define FL_DORMANT (1<<4) // Entity is dormant, no updates to client
|
||||
#define FL_FRAMETHINK (1<<5) // entity will be thinking every frame
|
||||
#define FL_GRAPHED (1<<6) // worldgraph has this ent listed as something that blocks a connection
|
||||
#define FL_GRAPHED (1<<6) // worldgraph has this ent listed as something that blocks a conection
|
||||
#define FL_FLOAT (1<<7) // this entity can be floating. FIXME: remove this ?
|
||||
#define FL_TRACKTRAIN (1<<8) // old stuff...
|
||||
|
||||
|
@ -299,7 +299,8 @@ void SV_ExecuteClientMessage (client_state_t *cl);
|
|||
//
|
||||
// sv_ccmds.c
|
||||
//
|
||||
void SV_Status_f (void);
|
||||
void SV_Status_f( void );
|
||||
void SV_SectorList_f( void );
|
||||
|
||||
//
|
||||
// sv_ents.c
|
||||
|
@ -375,7 +376,7 @@ void SV_LinkEdict (edict_t *ent);
|
|||
// sets ent->leafnums[] for pvs determination even if the entity
|
||||
// is not solid
|
||||
|
||||
int SV_AreaEdicts (vec3_t mins, vec3_t maxs, edict_t **list, int maxcount, int areatype);
|
||||
int SV_AreaEdicts( const vec3_t mins, const vec3_t maxs, edict_t **list, int maxcount );
|
||||
// fills in a table of edict pointers with edicts that have bounding boxes
|
||||
// that intersect the given area. It is possible for a non-axial bmodel
|
||||
// to be returned that doesn't actually intersect the area on an exact
|
||||
|
@ -388,13 +389,13 @@ int SV_AreaEdicts (vec3_t mins, vec3_t maxs, edict_t **list, int maxcount, int a
|
|||
//
|
||||
// functions that interact with everything apropriate
|
||||
//
|
||||
int SV_PointContents (vec3_t p);
|
||||
int SV_PointContents( const vec3_t p, edict_t *passedict );
|
||||
// returns the CONTENTS_* value from the world at the given point.
|
||||
// Quake 2 extends this to also check entities, to allow moving liquids
|
||||
|
||||
|
||||
trace_t SV_ClipMoveToEntity(edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int contentsmask );
|
||||
trace_t SV_Trace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passedict, int contentmask);
|
||||
trace_t SV_Trace( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, edict_t *passedict, int contentmask );
|
||||
trace_t SV_TraceToss (edict_t *tossent, edict_t *ignore);
|
||||
// mins and maxs are relative
|
||||
|
||||
|
|
|
@ -515,6 +515,7 @@ void SV_InitOperatorCommands( void )
|
|||
Cmd_AddCommand("movie", SV_Movie_f, "playing video file" );
|
||||
Cmd_AddCommand("changelevel", SV_ChangeLevel_f, "changing level" );
|
||||
Cmd_AddCommand("restart", SV_Restart_f, "restarting current level" );
|
||||
Cmd_AddCommand("sectorlist", SV_SectorList_f, "display pvs sectors" );
|
||||
|
||||
if( dedicated->value )
|
||||
{
|
||||
|
@ -540,6 +541,7 @@ void SV_KillOperatorCommands( void )
|
|||
Cmd_RemoveCommand("movie");
|
||||
Cmd_RemoveCommand("changelevel");
|
||||
Cmd_RemoveCommand("restart");
|
||||
Cmd_RemoveCommand("sectorlist");
|
||||
|
||||
if( dedicated->value )
|
||||
{
|
||||
|
|
|
@ -30,6 +30,14 @@ typedef struct link_s
|
|||
int entnum; // get edict by number
|
||||
} link_t;
|
||||
|
||||
typedef struct worldsector_s
|
||||
{
|
||||
int axis; // -1 = leaf node
|
||||
float dist;
|
||||
struct worldsector_s *children[2];
|
||||
sv_edict_t *entities;
|
||||
} worldsector_t;
|
||||
|
||||
struct gclient_s
|
||||
{
|
||||
player_state_t ps; // communicated by server to clients
|
||||
|
@ -51,13 +59,16 @@ struct sv_edict_s
|
|||
float freetime; // sv.time when the object was freed
|
||||
|
||||
// sv_private_edict_t
|
||||
worldsector_t *worldsector; // member of current wolrdsector
|
||||
struct sv_edict_s *nextedict; // next edict in world sector
|
||||
link_t area; // linked to a division node or leaf
|
||||
int clipmask; // trace info
|
||||
int headnode; // unused if num_clusters != -1
|
||||
int lastcluster; // unused if num_clusters != -1
|
||||
int linkcount;
|
||||
int num_clusters; // if -1, use headnode instead
|
||||
int clusternums[MAX_ENT_CLUSTERS];
|
||||
int areanum, areanum2;
|
||||
|
||||
int serialnumber; // unical entity #id
|
||||
int solid; // see entity_state_t for details
|
||||
int event; // apply sv.events too
|
||||
|
|
|
@ -92,8 +92,7 @@ void SV_EmitPacketEntities (client_frame_t *from, client_frame_t *to, sizebuf_t
|
|||
newnum = newent->number;
|
||||
}
|
||||
|
||||
if (oldindex >= from_num_entities)
|
||||
oldnum = 9999;
|
||||
if (oldindex >= from_num_entities) oldnum = 9999;
|
||||
else
|
||||
{
|
||||
oldent = &svs.client_entities[(from->first_entity+oldindex)%svs.num_client_entities];
|
||||
|
@ -409,6 +408,7 @@ void SV_BuildClientFrame (client_state_t *client)
|
|||
int clientarea, clientcluster;
|
||||
int leafnum;
|
||||
int c_fullsend;
|
||||
byte *clientpvs;
|
||||
byte *clientphs;
|
||||
byte *bitvector;
|
||||
|
||||
|
@ -434,8 +434,8 @@ void SV_BuildClientFrame (client_state_t *client)
|
|||
// grab the current player_state_t
|
||||
frame->ps = clent->priv.sv->client->ps;
|
||||
|
||||
SV_FatPVS (org);
|
||||
clientphs = pe->ClusterPHS (clientcluster);
|
||||
clientpvs = pe->ClusterPVS( clientcluster );
|
||||
clientphs = pe->ClusterPHS( clientcluster );
|
||||
|
||||
// build up the list of visible entities
|
||||
frame->num_entities = 0;
|
||||
|
@ -474,14 +474,11 @@ void SV_BuildClientFrame (client_state_t *client)
|
|||
{
|
||||
// FIXME: if an ent has a model and a sound, but isn't
|
||||
// in the PVS, only the PHS, clear the model
|
||||
if (ent->progs.sv->noise3)
|
||||
{
|
||||
bitvector = fatpvs; //clientphs;
|
||||
}
|
||||
else bitvector = fatpvs;
|
||||
if (ent->progs.sv->noise3) bitvector = clientphs;
|
||||
else bitvector = clientpvs;
|
||||
|
||||
// check individual leafs
|
||||
/*if( !ent->priv.sv->num_clusters )
|
||||
if( !ent->priv.sv->num_clusters )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -495,38 +492,18 @@ void SV_BuildClientFrame (client_state_t *client)
|
|||
// check overflow clusters that coudln't be stored
|
||||
if( i == ent->priv.sv->num_clusters )
|
||||
{
|
||||
if( svEnt->lastCluster )
|
||||
if( ent->priv.sv->lastcluster )
|
||||
{
|
||||
for( ; l <= svEnt->lastCluster; l++ )
|
||||
for( ; l <= ent->priv.sv->lastcluster; l++ )
|
||||
{
|
||||
if( bitvector[l>>3] & (1<<(l&7)))
|
||||
break;
|
||||
}
|
||||
if ( l == svEnt->lastCluster )
|
||||
if( l == ent->priv.sv->lastcluster )
|
||||
continue; // not visible
|
||||
}
|
||||
else continue;
|
||||
}*/
|
||||
|
||||
if (ent->priv.sv->num_clusters == -1)
|
||||
{
|
||||
// too many leafs for individual check, go by headnode
|
||||
//if(!pe->HeadnodeVisible (ent->priv.sv->headnode, bitvector))
|
||||
// continue;
|
||||
c_fullsend++;
|
||||
}
|
||||
else
|
||||
{ // check individual leafs
|
||||
for (i=0 ; i < ent->priv.sv->num_clusters ; i++)
|
||||
{
|
||||
l = ent->priv.sv->clusternums[i];
|
||||
if (bitvector[l >> 3] & (1 << (l&7) ))
|
||||
break;
|
||||
}
|
||||
if (i == ent->priv.sv->num_clusters)
|
||||
continue; // not visible
|
||||
}
|
||||
|
||||
if (!ent->progs.sv->modelindex)
|
||||
{
|
||||
// don't send sounds if they will be attenuated away
|
||||
|
|
|
@ -194,7 +194,7 @@ void SV_SpawnServer (char *server, char *savename, sv_state_t serverstate )
|
|||
|
||||
if (serverstate != ss_game)
|
||||
{
|
||||
sv.models[1] = pe->BeginRegistration("", false, &checksum); // no real map
|
||||
sv.models[1] = pe->BeginRegistration( "", false, &checksum); // no real map
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -85,7 +85,7 @@ bool SV_CheckBottom (edict_t *ent)
|
|||
{
|
||||
start[0] = x ? maxs[0] : mins[0];
|
||||
start[1] = y ? maxs[1] : mins[1];
|
||||
if (SV_PointContents(start) != CONTENTS_SOLID)
|
||||
if (SV_PointContents(start, ent ) != CONTENTS_SOLID)
|
||||
goto realcheck;
|
||||
}
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ void SV_Impact (edict_t *e1, trace_t *trace)
|
|||
prog->globals.sv->trace_plane_dist = trace->plane.dist;
|
||||
if (trace->ent) prog->globals.sv->trace_ent = PRVM_EDICT_TO_PROG(trace->ent);
|
||||
else prog->globals.sv->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
|
||||
PRVM_ExecuteProgram (e1->progs.sv->touch, "QC function pev->touch is missing");
|
||||
PRVM_ExecuteProgram (e1->progs.sv->touch, "QC function pev->touch is missing\n");
|
||||
}
|
||||
if (!e1->priv.sv->free && !e2->priv.sv->free && e2->progs.sv->touch && e2->progs.sv->solid != SOLID_NOT)
|
||||
{
|
||||
|
@ -239,7 +239,7 @@ void SV_Impact (edict_t *e1, trace_t *trace)
|
|||
VectorSet (prog->globals.sv->trace_plane_normal, 0, 0, 1);
|
||||
prog->globals.sv->trace_plane_dist = 0;
|
||||
prog->globals.sv->trace_ent = PRVM_EDICT_TO_PROG(e1);
|
||||
PRVM_ExecuteProgram (e2->progs.sv->touch, "QC function pev->touch is missing");
|
||||
PRVM_ExecuteProgram (e2->progs.sv->touch, "QC function pev->touch is missing\n");
|
||||
}
|
||||
|
||||
PRVM_POP_GLOBALS;
|
||||
|
@ -381,17 +381,17 @@ bool SV_CheckWater (edict_t *ent)
|
|||
|
||||
ent->progs.sv->waterlevel = 0;
|
||||
ent->progs.sv->watertype = CONTENTS_NONE;
|
||||
cont = SV_PointContents(point);
|
||||
cont = SV_PointContents( point, ent );
|
||||
if (cont & (MASK_WATER))
|
||||
{
|
||||
ent->progs.sv->watertype = cont;
|
||||
ent->progs.sv->waterlevel = 1;
|
||||
point[2] = ent->progs.sv->origin[2] + (ent->progs.sv->mins[2] + ent->progs.sv->maxs[2])*0.5;
|
||||
if (SV_PointContents(point) & (MASK_WATER))
|
||||
if (SV_PointContents(point, ent ) & (MASK_WATER))
|
||||
{
|
||||
ent->progs.sv->waterlevel = 2;
|
||||
point[2] = ent->progs.sv->origin[2] + ent->progs.sv->view_ofs[2];
|
||||
if (SV_PointContents(point) & (MASK_WATER))
|
||||
if (SV_PointContents(point, ent ) & (MASK_WATER))
|
||||
ent->progs.sv->waterlevel = 3;
|
||||
}
|
||||
}
|
||||
|
@ -640,7 +640,7 @@ bool SV_MoveStep (edict_t *ent, vec3_t move, bool relink)
|
|||
if (trace.fraction == 1)
|
||||
{
|
||||
VectorCopy(trace.endpos, traceendpos);
|
||||
if (((int)ent->progs.sv->aiflags & AI_SWIM) && !(SV_PointContents(traceendpos) & MASK_WATER))
|
||||
if (((int)ent->progs.sv->aiflags & AI_SWIM) && !(SV_PointContents(traceendpos, ent ) & MASK_WATER))
|
||||
return false; // swim monster left water
|
||||
|
||||
VectorCopy (traceendpos, ent->progs.sv->origin);
|
||||
|
@ -1022,7 +1022,7 @@ SV_CheckWaterTransition
|
|||
*/
|
||||
void SV_CheckWaterTransition (edict_t *ent)
|
||||
{
|
||||
int cont = SV_PointContents(ent->progs.sv->origin);
|
||||
int cont = SV_PointContents(ent->progs.sv->origin, ent );
|
||||
|
||||
if (!ent->progs.sv->watertype)
|
||||
{
|
||||
|
|
|
@ -173,7 +173,7 @@ void SV_TouchTriggers (edict_t *ent)
|
|||
if ((ent->priv.sv->client || ((int)ent->progs.sv->flags & FL_MONSTER)) && (ent->progs.sv->health <= 0))
|
||||
return;
|
||||
|
||||
num = SV_AreaEdicts(ent->progs.sv->absmin, ent->progs.sv->absmax, touch, MAX_EDICTS, AREA_TRIGGERS);
|
||||
num = SV_AreaEdicts(ent->progs.sv->absmin, ent->progs.sv->absmax, touch, MAX_EDICTS );
|
||||
|
||||
PRVM_PUSH_GLOBALS;
|
||||
|
||||
|
|
|
@ -83,14 +83,14 @@ void SV_SetMinMaxSize (edict_t *e, float *min, float *max, bool rotate)
|
|||
PRVM_ERROR("SV_SetMinMaxSize: backwards mins/maxs");
|
||||
|
||||
// set derived values
|
||||
if( rotate && e->progs.sv->solid == SOLID_BBOX)
|
||||
if( rotate && e->progs.sv->solid == SOLID_BBOX )
|
||||
{
|
||||
SV_CalcBBox( e, min, max );
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy (min, e->progs.sv->mins);
|
||||
VectorCopy (max, e->progs.sv->maxs);
|
||||
VectorCopy( min, e->progs.sv->mins);
|
||||
VectorCopy( max, e->progs.sv->maxs);
|
||||
}
|
||||
VectorSubtract (max, min, e->progs.sv->size );
|
||||
|
||||
|
@ -684,7 +684,7 @@ PF_pointcontents
|
|||
*/
|
||||
void PF_pointcontents (void)
|
||||
{
|
||||
PRVM_G_FLOAT(OFS_RETURN) = SV_PointContents(PRVM_G_VECTOR(OFS_PARM0));
|
||||
PRVM_G_FLOAT(OFS_RETURN) = SV_PointContents(PRVM_G_VECTOR(OFS_PARM0), NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -25,94 +25,86 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
/*
|
||||
===============================================================================
|
||||
|
||||
ENTITY AREA CHECKING
|
||||
ENTITY CHECKING
|
||||
|
||||
FIXME: this use of "area" is different from the bsp file use
|
||||
To avoid linearly searching through lists of entities during environment testing,
|
||||
the world is carved up with an evenly spaced, axially aligned bsp tree. Entities
|
||||
are kept in chains either at the final leafs, or at the first node that splits
|
||||
them, which prevents having to deal with multiple fragments of a single entity.
|
||||
===============================================================================
|
||||
*/
|
||||
#define EDICT_FROM_AREA(l) PRVM_EDICT_NUM(l->entnum)
|
||||
|
||||
typedef struct areanode_s
|
||||
{
|
||||
int axis; // -1 = leaf node
|
||||
float dist;
|
||||
struct areanode_s *children[2];
|
||||
link_t trigger_edicts;
|
||||
link_t solid_edicts;
|
||||
} areanode_t;
|
||||
|
||||
#define AREA_DEPTH 4
|
||||
#define AREA_NODES 32
|
||||
#define AREA_NODES 64
|
||||
#define MAX_TOTAL_ENT_LEAFS 128
|
||||
|
||||
areanode_t sv_areanodes[AREA_NODES];
|
||||
int sv_numareanodes;
|
||||
|
||||
float *area_mins, *area_maxs;
|
||||
edict_t **area_list;
|
||||
int area_count, area_maxcount;
|
||||
int area_type;
|
||||
|
||||
// ClearLink is used for new headnodes
|
||||
void ClearLink (link_t *l)
|
||||
typedef struct area_s
|
||||
{
|
||||
l->prev = l->next = l;
|
||||
}
|
||||
const float *mins;
|
||||
const float *maxs;
|
||||
edict_t **list;
|
||||
int count;
|
||||
int maxcount;
|
||||
int type;
|
||||
} area_t;
|
||||
|
||||
void RemoveLink (link_t *l)
|
||||
{
|
||||
l->next->prev = l->prev;
|
||||
l->prev->next = l->next;
|
||||
}
|
||||
worldsector_t sv_worldsectors[AREA_NODES];
|
||||
int sv_numworldsectors;
|
||||
|
||||
void InsertLinkBefore (link_t *l, link_t *before, edict_t *ent)
|
||||
/*
|
||||
===============
|
||||
SV_SectorList_f
|
||||
===============
|
||||
*/
|
||||
void SV_SectorList_f( void )
|
||||
{
|
||||
l->next = before;
|
||||
l->prev = before->prev;
|
||||
l->prev->next = l;
|
||||
l->next->prev = l;
|
||||
l->entnum = PRVM_NUM_FOR_EDICT(ent);
|
||||
int i, c;
|
||||
worldsector_t *sec;
|
||||
sv_edict_t *ent;
|
||||
|
||||
for ( i = 0; i < sv_numworldsectors; i++ )
|
||||
{
|
||||
sec = &sv_worldsectors[i], c = 0;
|
||||
for( ent = sec->entities; ent; ent = ent->nextedict ) c++;
|
||||
if(c) Msg( "sector %i: %i entities\n", i, c );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
SV_CreateAreaNode
|
||||
SV_CreateworldSector
|
||||
|
||||
Builds a uniformly subdivided tree for the given world size
|
||||
===============
|
||||
*/
|
||||
areanode_t *SV_CreateAreaNode (int depth, vec3_t mins, vec3_t maxs)
|
||||
worldsector_t *SV_CreateWorldSector( int depth, vec3_t mins, vec3_t maxs )
|
||||
{
|
||||
areanode_t *anode;
|
||||
worldsector_t *anode;
|
||||
vec3_t size;
|
||||
vec3_t mins1, maxs1, mins2, maxs2;
|
||||
|
||||
anode = &sv_areanodes[sv_numareanodes];
|
||||
sv_numareanodes++;
|
||||
anode = &sv_worldsectors[sv_numworldsectors];
|
||||
sv_numworldsectors++;
|
||||
|
||||
ClearLink (&anode->trigger_edicts);
|
||||
ClearLink (&anode->solid_edicts);
|
||||
|
||||
if (depth == AREA_DEPTH)
|
||||
if( depth == AREA_DEPTH )
|
||||
{
|
||||
anode->axis = -1;
|
||||
anode->children[0] = anode->children[1] = NULL;
|
||||
return anode;
|
||||
}
|
||||
|
||||
VectorSubtract (maxs, mins, size);
|
||||
if (size[0] > size[1]) anode->axis = 0;
|
||||
VectorSubtract( maxs, mins, size );
|
||||
if( size[0] > size[1] ) anode->axis = 0;
|
||||
else anode->axis = 1;
|
||||
|
||||
anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]);
|
||||
VectorCopy (mins, mins1);
|
||||
VectorCopy (mins, mins2);
|
||||
VectorCopy (maxs, maxs1);
|
||||
VectorCopy (maxs, maxs2);
|
||||
|
||||
anode->dist = 0.5f * (maxs[anode->axis] + mins[anode->axis]);
|
||||
VectorCopy(mins, mins1);
|
||||
VectorCopy(mins, mins2);
|
||||
VectorCopy(maxs, maxs1);
|
||||
VectorCopy(maxs, maxs2);
|
||||
|
||||
maxs1[anode->axis] = mins2[anode->axis] = anode->dist;
|
||||
|
||||
anode->children[0] = SV_CreateAreaNode (depth+1, mins2, maxs2);
|
||||
anode->children[1] = SV_CreateAreaNode (depth+1, mins1, maxs1);
|
||||
anode->children[0] = SV_CreateWorldSector( depth+1, mins2, maxs2);
|
||||
anode->children[1] = SV_CreateWorldSector( depth+1, mins1, maxs1);
|
||||
|
||||
return anode;
|
||||
}
|
||||
|
@ -125,90 +117,103 @@ SV_ClearWorld
|
|||
*/
|
||||
void SV_ClearWorld (void)
|
||||
{
|
||||
memset (sv_areanodes, 0, sizeof(sv_areanodes));
|
||||
sv_numareanodes = 0;
|
||||
SV_CreateAreaNode (0, sv.models[1]->mins, sv.models[1]->maxs);
|
||||
cmodel_t *world = sv.models[1];
|
||||
memset( sv_worldsectors, 0, sizeof(sv_worldsectors));
|
||||
sv_numworldsectors = 0;
|
||||
SV_CreateWorldSector( 0, world->mins, world->maxs );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
SV_UnlinkEdict
|
||||
|
||||
===============
|
||||
*/
|
||||
void SV_UnlinkEdict (edict_t *ent)
|
||||
void SV_UnlinkEdict( edict_t *ent )
|
||||
{
|
||||
if (!ent->priv.sv->area.prev) return; // not linked in anywhere
|
||||
RemoveLink (&ent->priv.sv->area);
|
||||
ent->priv.sv->area.prev = ent->priv.sv->area.next = NULL;
|
||||
}
|
||||
sv_edict_t *sv_ent, *scan;
|
||||
worldsector_t *ws;
|
||||
|
||||
sv_ent = ent->priv.sv;
|
||||
ws = sv_ent->worldsector;
|
||||
if( !ws ) return; // not linked in anywhere
|
||||
sv_ent->worldsector = NULL;
|
||||
//sv_ent->linked = false;
|
||||
|
||||
if( ws->entities == sv_ent )
|
||||
{
|
||||
ws->entities = sv_ent->nextedict;
|
||||
return;
|
||||
}
|
||||
|
||||
for( scan = ws->entities; scan; scan = scan->nextedict )
|
||||
{
|
||||
if( scan->nextedict == sv_ent )
|
||||
{
|
||||
scan->nextedict = sv_ent->nextedict;
|
||||
return;
|
||||
}
|
||||
}
|
||||
MsgWarn("SV_UnlinkEdict: not found in worldSector\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
SV_LinkEdict
|
||||
|
||||
SV_LinkEntity
|
||||
===============
|
||||
*/
|
||||
#define MAX_TOTAL_ENT_LEAFS 128
|
||||
void SV_LinkEdict (edict_t *ent)
|
||||
void SV_LinkEdict( edict_t *ent )
|
||||
{
|
||||
areanode_t *node;
|
||||
worldsector_t *node;
|
||||
int leafs[MAX_TOTAL_ENT_LEAFS];
|
||||
int clusters[MAX_TOTAL_ENT_LEAFS];
|
||||
int cluster;
|
||||
int num_leafs;
|
||||
int i, j, k;
|
||||
int area;
|
||||
int topnode;
|
||||
int lastleaf;
|
||||
sv_edict_t *sv_ent;
|
||||
|
||||
if (ent->priv.sv->area.prev) SV_UnlinkEdict (ent); // unlink from old position
|
||||
sv_ent = ent->priv.sv;
|
||||
|
||||
if( sv_ent->worldsector ) SV_UnlinkEdict( ent ); // unlink from old position
|
||||
if (ent == prog->edicts) return; // don't add the world
|
||||
if (ent->priv.sv->free) return;
|
||||
|
||||
// set the size
|
||||
VectorSubtract (ent->progs.sv->maxs, ent->progs.sv->mins, ent->progs.sv->size);
|
||||
|
||||
VectorSubtract( ent->progs.sv->maxs, ent->progs.sv->mins, ent->progs.sv->size );
|
||||
|
||||
// encode the size into the entity_state for client prediction
|
||||
if (ent->progs.sv->solid == SOLID_BBOX && !((int)ent->progs.sv->flags & FL_DEADMONSTER))
|
||||
{
|
||||
// assume that x/y are equal and symetric
|
||||
i = ent->progs.sv->maxs[0]/SV_COORD_FRAC;
|
||||
if (i<1) i = 1;
|
||||
if (i>31) i = 31;
|
||||
if( i < 1 ) i = 1;
|
||||
if( i > 31) i = 31;
|
||||
|
||||
// z is not symetric
|
||||
j = (-ent->progs.sv->mins[2])/SV_COORD_FRAC;
|
||||
if (j < 1) j = 1;
|
||||
if (j > 31) j = 31;
|
||||
if( j < 1 ) j = 1;
|
||||
if( j > 31) j = 31;
|
||||
|
||||
// and z maxs can be negative...
|
||||
k = (ent->progs.sv->maxs[2]+32)/SV_COORD_FRAC;
|
||||
if (k<1) k = 1;
|
||||
if (k>63) k = 63;
|
||||
ent->priv.sv->solid = (k<<10) | (j<<5) | i;
|
||||
if( k < 1 ) k = 1;
|
||||
if( k > 63) k = 63;
|
||||
sv_ent->solid = (k<<10) | (j<<5) | i;
|
||||
}
|
||||
else if (ent->progs.sv->solid == SOLID_BSP)
|
||||
{
|
||||
ent->priv.sv->solid = 31; // a solid_bbox will never create this value
|
||||
sv_ent->solid = 31; // a solid_bbox will never create this value
|
||||
}
|
||||
else ent->priv.sv->solid = 0;
|
||||
else sv_ent->solid = 0;
|
||||
|
||||
// set the abs box
|
||||
if (ent->progs.sv->solid == SOLID_BSP && !VectorIsNull(ent->progs.sv->angles))
|
||||
{
|
||||
// expand for rotation
|
||||
float max = 0, v;
|
||||
int i;
|
||||
float max = RadiusFromBounds( ent->progs.sv->mins, ent->progs.sv->maxs );
|
||||
|
||||
for (i = 0; i<3 ; i++)
|
||||
{
|
||||
v =fabs( ent->progs.sv->mins[i]);
|
||||
if (v > max) max = v;
|
||||
v =fabs( ent->progs.sv->maxs[i]);
|
||||
if (v > max) max = v;
|
||||
}
|
||||
for (i=0 ; i<3 ; i++)
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
ent->progs.sv->absmin[i] = ent->progs.sv->origin[i] - max;
|
||||
ent->progs.sv->absmax[i] = ent->progs.sv->origin[i] + max;
|
||||
|
@ -230,74 +235,69 @@ void SV_LinkEdict (edict_t *ent)
|
|||
ent->progs.sv->absmax[2] += 1;
|
||||
|
||||
// link to PVS leafs
|
||||
ent->priv.sv->num_clusters = 0;
|
||||
ent->priv.sv->areanum = 0;
|
||||
ent->priv.sv->areanum2 = 0;
|
||||
sv_ent->num_clusters = 0;
|
||||
sv_ent->lastcluster = 0;
|
||||
sv_ent->areanum = 0;
|
||||
sv_ent->areanum2 = 0;
|
||||
|
||||
//get all leafs, including solids
|
||||
num_leafs = pe->BoxLeafnums (ent->progs.sv->absmin, ent->progs.sv->absmax, leafs, MAX_TOTAL_ENT_LEAFS, &topnode);
|
||||
// get all leafs, including solids
|
||||
num_leafs = pe->BoxLeafnums( ent->progs.sv->absmin, ent->progs.sv->absmax, leafs, MAX_TOTAL_ENT_LEAFS, &lastleaf );
|
||||
|
||||
// set areas
|
||||
for (i = 0; i < num_leafs; i++)
|
||||
// if none of the leafs were inside the map, the
|
||||
// entity is outside the world and can be considered unlinked
|
||||
if( !num_leafs ) return;
|
||||
|
||||
// set areas, even from clusters that don't fit in the entity array
|
||||
for( i = 0; i < num_leafs; i++ )
|
||||
{
|
||||
clusters[i] = pe->LeafCluster (leafs[i]);
|
||||
area = pe->LeafArea (leafs[i]);
|
||||
if (area)
|
||||
{ // doors may legally straggle two areas,
|
||||
area = pe->LeafArea( leafs[i] );
|
||||
if( area )
|
||||
{
|
||||
// doors may legally straggle two areas,
|
||||
// but nothing should evern need more than that
|
||||
if (ent->priv.sv->areanum && ent->priv.sv->areanum != area)
|
||||
{
|
||||
if (ent->priv.sv->areanum2 && ent->priv.sv->areanum2 != area && sv.state == ss_loading)
|
||||
MsgWarn("SV_LinkEdict: object touching 3 areas at %f %f %f\n", ent->progs.sv->absmin[0], ent->progs.sv->absmin[1], ent->progs.sv->absmin[2]);
|
||||
if (ent->priv.sv->areanum2 && ent->priv.sv->areanum2 != area && sv.state == ss_loading )
|
||||
{
|
||||
float *v = ent->progs.sv->absmin;
|
||||
MsgWarn("SV_LinkEdict: object touching 3 areas at %f %f %f\n", v[0], v[1], v[2]);
|
||||
}
|
||||
ent->priv.sv->areanum2 = area;
|
||||
}
|
||||
else ent->priv.sv->areanum = area;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_leafs >= MAX_TOTAL_ENT_LEAFS)
|
||||
// store as many explicit clusters as we can
|
||||
sv_ent->num_clusters = 0;
|
||||
for (i = 0; i < num_leafs; i++)
|
||||
{
|
||||
// assume we missed some leafs, and mark by headnode
|
||||
ent->priv.sv->num_clusters = -1;
|
||||
ent->priv.sv->headnode = topnode;
|
||||
}
|
||||
else
|
||||
{
|
||||
ent->priv.sv->num_clusters = 0;
|
||||
for (i = 0; i < num_leafs; i++)
|
||||
cluster = pe->LeafCluster( leafs[i] );
|
||||
if( cluster )
|
||||
{
|
||||
if (clusters[i] == -1) continue; // not a visible leaf
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
if (clusters[j] == clusters[i]) break;
|
||||
}
|
||||
if (j == i)
|
||||
{
|
||||
if (ent->priv.sv->num_clusters == MAX_ENT_CLUSTERS)
|
||||
{
|
||||
// assume we missed some leafs, and mark by headnode
|
||||
ent->priv.sv->num_clusters = -1;
|
||||
ent->priv.sv->headnode = topnode;
|
||||
break;
|
||||
}
|
||||
ent->priv.sv->clusternums[ent->priv.sv->num_clusters++] = clusters[i];
|
||||
}
|
||||
sv_ent->clusternums[sv_ent->num_clusters++] = cluster;
|
||||
if( sv_ent->num_clusters == MAX_ENT_CLUSTERS )
|
||||
break; // list is full
|
||||
}
|
||||
}
|
||||
|
||||
// store off a last cluster if we need to
|
||||
if( i != num_leafs ) sv_ent->lastcluster = pe->LeafCluster( lastleaf );
|
||||
|
||||
// if first time, make sure old_origin is valid
|
||||
if (!ent->priv.sv->linkcount)
|
||||
if(!ent->priv.sv->linkcount)
|
||||
{
|
||||
VectorCopy (ent->progs.sv->origin, ent->progs.sv->old_origin);
|
||||
}
|
||||
ent->priv.sv->linkcount++;
|
||||
|
||||
// don't link not solid or rigid bodies
|
||||
if (ent->progs.sv->solid == SOLID_NOT || ent->progs.sv->solid >= SOLID_BOX)
|
||||
return;
|
||||
|
||||
// find the first node that the ent's box crosses
|
||||
node = sv_areanodes;
|
||||
while (1)
|
||||
// find the first world sector node that the ent's box crosses
|
||||
node = sv_worldsectors;
|
||||
while( 1 )
|
||||
{
|
||||
if (node->axis == -1) break;
|
||||
if (ent->progs.sv->absmin[node->axis] > node->dist)
|
||||
|
@ -307,57 +307,57 @@ void SV_LinkEdict (edict_t *ent)
|
|||
else break; // crosses the node
|
||||
}
|
||||
|
||||
// link it in
|
||||
if (ent->progs.sv->solid == SOLID_TRIGGER) InsertLinkBefore (&ent->priv.sv->area, &node->trigger_edicts, ent );
|
||||
else InsertLinkBefore (&ent->priv.sv->area, &node->solid_edicts, ent );
|
||||
// link it in
|
||||
sv_ent->worldsector = node;
|
||||
sv_ent->nextedict = node->entities;
|
||||
node->entities = sv_ent;
|
||||
|
||||
//sv_ent->linked = true;
|
||||
}
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
|
||||
AREA QUERY
|
||||
|
||||
Fills in a list of all entities who's absmin / absmax intersects the given
|
||||
bounds. This does NOT mean that they actually touch in the case of bmodels.
|
||||
============================================================================
|
||||
*/
|
||||
/*
|
||||
====================
|
||||
SV_AreaEdicts_r
|
||||
|
||||
====================
|
||||
*/
|
||||
void SV_AreaEdicts_r (areanode_t *node)
|
||||
void SV_AreaEdicts_r( worldsector_t *node, area_t *ap )
|
||||
{
|
||||
link_t *l, *next, *start;
|
||||
edict_t *check;
|
||||
sv_edict_t *check, *next;
|
||||
edict_t *gcheck;
|
||||
int count = 0;
|
||||
|
||||
// touch linked edicts
|
||||
if (area_type == AREA_SOLID)
|
||||
start = &node->solid_edicts;
|
||||
else start = &node->trigger_edicts;
|
||||
|
||||
for (l = start->next; l != start; l = next)
|
||||
for( check = node->entities; check; check = next )
|
||||
{
|
||||
next = l->next;
|
||||
check = EDICT_FROM_AREA(l);
|
||||
next = check->nextedict;
|
||||
gcheck = PRVM_EDICT_NUM( check->serialnumber );
|
||||
|
||||
if (check->progs.sv->solid == SOLID_NOT) continue; // deactivated
|
||||
if (check->progs.sv->absmin[0] > area_maxs[0] || check->progs.sv->absmin[1] > area_maxs[1] || check->progs.sv->absmin[2] > area_maxs[2]
|
||||
|| check->progs.sv->absmax[0] < area_mins[0] || check->progs.sv->absmax[1] < area_mins[1] || check->progs.sv->absmax[2] < area_mins[2])
|
||||
if (gcheck->progs.sv->absmin[0] > ap->maxs[0] || gcheck->progs.sv->absmin[1] > ap->maxs[1] || gcheck->progs.sv->absmin[2] > ap->maxs[2]
|
||||
|| gcheck->progs.sv->absmax[0] < ap->mins[0] || gcheck->progs.sv->absmax[1] < ap->mins[1] || gcheck->progs.sv->absmax[2] < ap->mins[2])
|
||||
continue; // not touching
|
||||
|
||||
if (area_count == area_maxcount)
|
||||
if( ap->count == ap->maxcount )
|
||||
{
|
||||
MsgWarn("SV_AreaEdicts: maxcount\n");
|
||||
MsgDev(D_NOTE, "SV_AreaEdicts_r: maxcount!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
area_list[area_count] = check;
|
||||
area_count++;
|
||||
ap->list[ap->count] = PRVM_EDICT_NUM( check->serialnumber );
|
||||
ap->count++;
|
||||
}
|
||||
|
||||
if (node->axis == -1) return; // terminal node
|
||||
if( node->axis == -1 ) return; // terminal node
|
||||
|
||||
// recurse down both sides
|
||||
if ( area_maxs[node->axis] > node->dist )
|
||||
SV_AreaEdicts_r ( node->children[0] );
|
||||
if ( area_mins[node->axis] < node->dist )
|
||||
SV_AreaEdicts_r ( node->children[1] );
|
||||
if( ap->maxs[node->axis] > node->dist ) SV_AreaEdicts_r ( node->children[0], ap );
|
||||
if( ap->mins[node->axis] < node->dist ) SV_AreaEdicts_r ( node->children[1], ap );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -365,92 +365,56 @@ void SV_AreaEdicts_r (areanode_t *node)
|
|||
SV_AreaEdicts
|
||||
================
|
||||
*/
|
||||
int SV_AreaEdicts (vec3_t mins, vec3_t maxs, edict_t **list, int maxcount, int areatype)
|
||||
int SV_AreaEdicts( const vec3_t mins, const vec3_t maxs, edict_t **list, int maxcount )
|
||||
{
|
||||
area_mins = mins;
|
||||
area_maxs = maxs;
|
||||
area_list = list;
|
||||
area_count = 0;
|
||||
area_maxcount = maxcount;
|
||||
area_type = areatype;
|
||||
area_t ap;
|
||||
|
||||
SV_AreaEdicts_r (sv_areanodes);
|
||||
ap.mins = mins;
|
||||
ap.maxs = maxs;
|
||||
ap.list = list;
|
||||
ap.count = 0;
|
||||
ap.maxcount = maxcount;
|
||||
|
||||
return area_count;
|
||||
SV_AreaEdicts_r( sv_worldsectors, &ap );
|
||||
|
||||
return ap.count;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
|
||||
/*
|
||||
=============
|
||||
SV_PointContents
|
||||
=============
|
||||
*/
|
||||
int SV_PointContents( vec3_t p )
|
||||
{
|
||||
edict_t *touch[MAX_EDICTS], *hit;
|
||||
int i, num;
|
||||
int contents, c2;
|
||||
float *angles;
|
||||
|
||||
// get base contents from world
|
||||
contents = pe->PointContents( p );
|
||||
|
||||
// or in contents from all the other entities
|
||||
num = SV_AreaEdicts (p, p, touch, MAX_EDICTS, AREA_SOLID);
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
hit = touch[i];
|
||||
|
||||
// might intersect, so do an exact clip
|
||||
angles = hit->progs.sv->angles;
|
||||
if (hit->progs.sv->solid != SOLID_BSP) angles = vec3_origin; // boxes don't rotate
|
||||
c2 = pe->TransformedPointContents( p, hit->progs.sv->origin, hit->progs.sv->angles );
|
||||
contents |= c2;
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t boxmins, boxmaxs;// enclose the test object along entire move
|
||||
float *mins, *maxs; // size of the moving object
|
||||
vec3_t mins2, maxs2; // size when clipping against mosnters
|
||||
float *start, *end;
|
||||
const float *mins, *maxs;
|
||||
const float *start;
|
||||
vec3_t end;
|
||||
trace_t trace;
|
||||
edict_t *passedict;
|
||||
int contentmask;
|
||||
|
||||
} moveclip_t;
|
||||
|
||||
/*
|
||||
====================
|
||||
SV_ClipMoveToEntities
|
||||
|
||||
====================
|
||||
*/
|
||||
void SV_ClipMoveToEntities ( moveclip_t *clip )
|
||||
void SV_ClipMoveToEntities( moveclip_t *clip )
|
||||
{
|
||||
int i, num;
|
||||
edict_t *touchlist[MAX_EDICTS], *touch;
|
||||
trace_t trace;
|
||||
float *angles;
|
||||
cmodel_t *cmodel;
|
||||
float *origin, *angles;
|
||||
|
||||
num = SV_AreaEdicts (clip->boxmins, clip->boxmaxs, touchlist, MAX_EDICTS, AREA_SOLID);
|
||||
num = SV_AreaEdicts( clip->boxmins, clip->boxmaxs, touchlist, MAX_EDICTS );
|
||||
|
||||
// be careful, it is possible to have an entity in this
|
||||
// list removed before we get to it (killtriggered)
|
||||
for (i = 0; i < num; i++)
|
||||
for( i = 0; i < num; i++ )
|
||||
{
|
||||
if( clip->trace.allsolid ) return;
|
||||
|
||||
touch = touchlist[i];
|
||||
if (touch->progs.sv->solid == SOLID_NOT) continue;
|
||||
if (touch == clip->passedict) continue;
|
||||
if (clip->trace.allsolid) return;
|
||||
if (clip->passedict)
|
||||
if( touch == clip->passedict ) continue;
|
||||
if( touch->progs.sv->solid == SOLID_NOT ) continue;
|
||||
if( clip->passedict )
|
||||
{
|
||||
if (PRVM_PROG_TO_EDICT(touch->progs.sv->owner) == clip->passedict)
|
||||
continue; // don't clip against own missiles
|
||||
|
@ -458,56 +422,37 @@ void SV_ClipMoveToEntities ( moveclip_t *clip )
|
|||
continue; // don't clip against owner
|
||||
}
|
||||
|
||||
if ( !(clip->contentmask & CONTENTS_DEADMONSTER) && ((int)touch->progs.sv->flags & FL_DEADMONSTER))
|
||||
if(!(clip->contentmask & CONTENTS_DEADMONSTER) && ((int)touch->progs.sv->flags & FL_DEADMONSTER))
|
||||
continue;
|
||||
|
||||
// might intersect, so do an exact clip
|
||||
cmodel = SV_GetModelPtr( touch );
|
||||
|
||||
origin = touch->progs.sv->origin;
|
||||
angles = touch->progs.sv->angles;
|
||||
if (touch->progs.sv->solid != SOLID_BSP) angles = vec3_origin; // boxes don't rotate
|
||||
|
||||
if ((int)touch->progs.sv->flags & FL_MONSTER)
|
||||
{
|
||||
trace = pe->TransformedBoxTrace (clip->start, clip->end, clip->mins2, clip->maxs2, clip->contentmask, touch->progs.sv->origin, angles);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace = pe->TransformedBoxTrace (clip->start, clip->end, clip->mins, clip->maxs, clip->contentmask, touch->progs.sv->origin, angles);
|
||||
}
|
||||
if (trace.allsolid || trace.startsolid || trace.fraction < clip->trace.fraction)
|
||||
if( !touch->progs.sv->solid == SOLID_BSP ) angles = vec3_origin; // boxes don't rotate
|
||||
|
||||
trace = pe->TransformedBoxTrace((float *)clip->start, (float *)clip->end, (float *)clip->mins, (float *)clip->maxs, cmodel, clip->contentmask, origin, angles );
|
||||
|
||||
if( trace.allsolid )
|
||||
{
|
||||
clip->trace.allsolid = true;
|
||||
trace.ent = touch;
|
||||
if (clip->trace.startsolid)
|
||||
{
|
||||
clip->trace = trace;
|
||||
clip->trace.startsolid = true;
|
||||
}
|
||||
else clip->trace = trace;
|
||||
}
|
||||
else if (trace.startsolid) clip->trace.startsolid = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_TraceBounds
|
||||
==================
|
||||
*/
|
||||
void SV_TraceBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (end[i] > start[i])
|
||||
}
|
||||
else if( trace.startsolid )
|
||||
{
|
||||
boxmins[i] = start[i] + mins[i] - 1;
|
||||
boxmaxs[i] = end[i] + maxs[i] + 1;
|
||||
clip->trace.startsolid = true;
|
||||
trace.ent = touch;
|
||||
}
|
||||
else
|
||||
if( trace.fraction < clip->trace.fraction )
|
||||
{
|
||||
boxmins[i] = end[i] + mins[i] - 1;
|
||||
boxmaxs[i] = start[i] + maxs[i] + 1;
|
||||
bool oldStart;
|
||||
|
||||
// make sure we keep a startsolid from a previous trace
|
||||
oldStart = clip->trace.startsolid;
|
||||
trace.ent = touch;
|
||||
clip->trace = trace;
|
||||
clip->trace.startsolid |= oldStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -517,40 +462,50 @@ void SV_TraceBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t
|
|||
SV_Trace
|
||||
|
||||
Moves the given mins/maxs volume through the world from start to end.
|
||||
|
||||
Passedict and edicts owned by passedict are explicitly not checked.
|
||||
|
||||
passEntityNum and entities owned by passEntityNum are explicitly not checked.
|
||||
==================
|
||||
*/
|
||||
trace_t SV_Trace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passedict, int contentmask)
|
||||
trace_t SV_Trace( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, edict_t *passedict, int contentmask )
|
||||
{
|
||||
moveclip_t clip;
|
||||
int i;
|
||||
|
||||
if (!mins) mins = vec3_origin;
|
||||
if (!maxs) maxs = vec3_origin;
|
||||
|
||||
memset ( &clip, 0, sizeof ( moveclip_t ) );
|
||||
if( !mins ) mins = vec3_origin;
|
||||
if( !maxs ) maxs = vec3_origin;
|
||||
memset( &clip, 0, sizeof( moveclip_t ));
|
||||
|
||||
// clip to world
|
||||
clip.trace = pe->BoxTrace( start, end, mins, maxs, contentmask );
|
||||
clip.trace.ent = prog->edicts;
|
||||
if (clip.trace.fraction == 0) return clip.trace; // blocked by the world
|
||||
clip.trace = pe->BoxTrace( start, end, mins, maxs, NULL, contentmask );
|
||||
clip.trace.ent = clip.trace.fraction != 1.0 ? prog->edicts : NULL;
|
||||
if( clip.trace.fraction == 0 ) return clip.trace; // blocked immediately by the world
|
||||
|
||||
clip.contentmask = contentmask;
|
||||
clip.start = start;
|
||||
clip.end = end;
|
||||
VectorCopy( end, clip.end );
|
||||
clip.mins = mins;
|
||||
clip.maxs = maxs;
|
||||
clip.passedict = passedict;
|
||||
|
||||
VectorCopy (mins, clip.mins2);
|
||||
VectorCopy (maxs, clip.maxs2);
|
||||
|
||||
// create the bounding box of the entire move
|
||||
SV_TraceBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs );
|
||||
// we can limit it to the part of the move not
|
||||
// already clipped off by the world, which can be
|
||||
// a significant savings for line of sight and shot traces
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
if( end[i] > start[i] )
|
||||
{
|
||||
clip.boxmins[i] = clip.start[i] + clip.mins[i] - 1;
|
||||
clip.boxmaxs[i] = clip.end[i] + clip.maxs[i] + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
clip.boxmins[i] = clip.end[i] + clip.mins[i] - 1;
|
||||
clip.boxmaxs[i] = clip.start[i] + clip.maxs[i] + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// clip to other solid entities
|
||||
SV_ClipMoveToEntities ( &clip );
|
||||
SV_ClipMoveToEntities( &clip );
|
||||
|
||||
return clip.trace;
|
||||
}
|
||||
|
@ -595,5 +550,63 @@ trace_t SV_TraceToss (edict_t *tossent, edict_t *ignore)
|
|||
|
||||
trace_t SV_ClipMoveToEntity(edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int contentsmask)
|
||||
{
|
||||
return pe->BoxTrace(start, end, mins, maxs, contentsmask);
|
||||
edict_t *touch;
|
||||
cmodel_t *cmodel;
|
||||
float *origin, *angles;
|
||||
trace_t trace;
|
||||
|
||||
touch = ent;
|
||||
|
||||
memset( &trace, 0, sizeof(trace_t));
|
||||
// if it doesn't have any brushes of a type we
|
||||
// are looking for, ignore it
|
||||
if(!(contentsmask & CONTENTS_DEADMONSTER) && ((int)touch->progs.sv->flags & FL_DEADMONSTER))
|
||||
{
|
||||
trace.fraction = 1.0;
|
||||
return trace;
|
||||
}
|
||||
// might intersect, so do an exact clip
|
||||
cmodel = SV_GetModelPtr( touch );
|
||||
origin = touch->progs.sv->origin;
|
||||
angles = touch->progs.sv->angles;
|
||||
if( !touch->progs.sv->solid == SOLID_BSP ) angles = vec3_origin; // boxes don't rotate
|
||||
|
||||
trace = pe->TransformedBoxTrace( start, end, mins, maxs, cmodel, contentsmask, origin, angles );
|
||||
if( trace.fraction < 1 ) trace.ent = touch;
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
SV_PointContents
|
||||
=============
|
||||
*/
|
||||
int SV_PointContents( const vec3_t p, edict_t *passedict )
|
||||
{
|
||||
edict_t *touch[MAX_EDICTS], *hit;
|
||||
int i, num;
|
||||
int contents, c2;
|
||||
cmodel_t *cmodel;
|
||||
float *angles;
|
||||
|
||||
// get base contents from world
|
||||
contents = pe->PointContents( p, NULL );
|
||||
|
||||
// or in contents from all the other entities
|
||||
num = SV_AreaEdicts( p, p, touch, MAX_EDICTS );
|
||||
|
||||
for( i = 0; i < num; i++ )
|
||||
{
|
||||
if ( touch[i] == passedict ) continue;
|
||||
hit = touch[i];
|
||||
|
||||
// might intersect, so do an exact clip
|
||||
cmodel = SV_GetModelPtr( hit );
|
||||
angles = hit->progs.sv->angles;
|
||||
if( !hit->progs.sv->solid == SOLID_BSP ) angles = vec3_origin; // boxes don't rotate
|
||||
c2 = pe->TransformedPointContents( p, cmodel, hit->progs.sv->origin, angles );
|
||||
contents |= c2;
|
||||
}
|
||||
return contents;
|
||||
}
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include "physic.h"
|
||||
|
||||
#define BOX_MODEL_HANDLE MAX_MODELS - 1
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cplane_t *plane;
|
||||
|
@ -19,15 +21,6 @@ typedef struct
|
|||
csurface_t *surface;
|
||||
} cbrushside_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int contents;
|
||||
int cluster;
|
||||
int area;
|
||||
int firstleafbrush;
|
||||
int numleafbrushes;
|
||||
} cleaf_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int contents;
|
||||
|
@ -138,6 +131,7 @@ typedef struct box_s
|
|||
{
|
||||
cplane_t *planes;
|
||||
cbrush_t *brush;
|
||||
cmodel_t model;
|
||||
} box_t;
|
||||
|
||||
typedef struct mapleaf_s
|
||||
|
@ -171,6 +165,7 @@ typedef struct tracework_s
|
|||
float maxOffset; // longest corner length from origin
|
||||
vec3_t bounds[2]; // enclosing box of start and end surrounding by size
|
||||
vec3_t extents; // greatest of abs(size[0]) and abs(size[1])
|
||||
vec3_t origin;
|
||||
int contents;
|
||||
bool ispoint; // optimized case
|
||||
trace_t result; // returned from trace call
|
||||
|
|
|
@ -59,6 +59,25 @@ void CM_GetPoint2( int index, vec3_t out )
|
|||
CM_ConvertDimensionToMeters( out, cm.vertices[vert_index].point );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CM_BoundBrush
|
||||
=================
|
||||
*/
|
||||
void CM_BoundBrush( cbrush_t *b )
|
||||
{
|
||||
cbrushside_t *sides;
|
||||
sides = &cm.brushsides[b->firstbrushside];
|
||||
|
||||
b->bounds[0][0] = -sides[0].plane->dist;
|
||||
b->bounds[1][0] = sides[1].plane->dist;
|
||||
|
||||
b->bounds[0][1] = -sides[2].plane->dist;
|
||||
b->bounds[1][1] = sides[3].plane->dist;
|
||||
|
||||
b->bounds[0][2] = -sides[4].plane->dist;
|
||||
b->bounds[1][2] = sides[5].plane->dist;
|
||||
}
|
||||
|
||||
int CM_NumTexinfo( void ) { return cm.numtexinfo; }
|
||||
int CM_NumClusters( void ) { return cm.numclusters; }
|
||||
|
@ -231,6 +250,7 @@ void BSP_LoadBrushes( lump_t *l )
|
|||
out->firstbrushside = LittleLong(in->firstside);
|
||||
out->numsides = LittleLong(in->numsides);
|
||||
out->contents = LittleLong(in->contents);
|
||||
CM_BoundBrush( out );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -563,6 +583,19 @@ void BSP_LoadStringData( lump_t *l )
|
|||
Mem_Copy( cm.stringdata, cm.mod_base + l->fileofs, l->filelen );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
BSP_LoadStringData
|
||||
=================
|
||||
*/
|
||||
void BSP_LoadBuiltinProgs( lump_t *l )
|
||||
{
|
||||
if(!l->filelen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
BSP_LoadStringTable
|
||||
|
@ -660,8 +693,8 @@ void CM_LoadBSP( const void *buffer )
|
|||
BSP_LoadSurfedges(&header.lumps[LUMP_SURFEDGES]);
|
||||
BSP_LoadFaces(&header.lumps[LUMP_FACES]);
|
||||
BSP_LoadSurfDesc(&header.lumps[LUMP_SURFDESC]);
|
||||
BSP_LoadCollision(&header.lumps[LUMP_COLLISION]);
|
||||
BSP_LoadModels(&header.lumps[LUMP_MODELS]);
|
||||
BSP_LoadCollision(&header.lumps[LUMP_COLLISION]);
|
||||
cm.loaded = true;
|
||||
cm.use_thread = true;
|
||||
|
||||
|
@ -802,8 +835,8 @@ cmodel_t *CM_BeginRegistration( const char *name, bool clientload, uint *checksu
|
|||
BSP_LoadLeafs(&hdr->lumps[LUMP_LEAFS]);
|
||||
BSP_LoadLeafBrushes(&hdr->lumps[LUMP_LEAFBRUSHES]);
|
||||
BSP_LoadPlanes(&hdr->lumps[LUMP_PLANES]);
|
||||
BSP_LoadBrushes(&hdr->lumps[LUMP_BRUSHES]);
|
||||
BSP_LoadBrushSides(&hdr->lumps[LUMP_BRUSHSIDES]);
|
||||
BSP_LoadBrushes(&hdr->lumps[LUMP_BRUSHES]);
|
||||
BSP_LoadNodes(&hdr->lumps[LUMP_NODES]);
|
||||
BSP_LoadAreas(&hdr->lumps[LUMP_AREAS]);
|
||||
BSP_LoadAreaPortals(&hdr->lumps[LUMP_AREAPORTALS]);
|
||||
|
@ -893,7 +926,7 @@ Set up the planes and nodes so that the six floats of a bounding box
|
|||
can just be stored out and get a proper clipping hull structure.
|
||||
===================
|
||||
*/
|
||||
void CM_InitBoxHull (void)
|
||||
void CM_InitBoxHull( void )
|
||||
{
|
||||
cplane_t *p;
|
||||
cbrushside_t *s;
|
||||
|
@ -903,7 +936,9 @@ void CM_InitBoxHull (void)
|
|||
box.brush = &cm.brushes[cm.numbrushes];
|
||||
box.brush->numsides = 6;
|
||||
box.brush->firstbrushside = cm.numbrushsides;
|
||||
box.brush->contents = CONTENTS_MONSTER;
|
||||
box.brush->contents = CONTENTS_MONSTER;//FIXME
|
||||
box.model.leaf.numleafbrushes = 1;
|
||||
box.model.leaf.firstleafbrush = cm.numleafbrushes;
|
||||
cm.leafbrushes[cm.numleafbrushes] = cm.numbrushes;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
|
@ -931,6 +966,60 @@ void CM_InitBoxHull (void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
CM_TempBoxModel
|
||||
|
||||
To keep everything totally uniform, bounding boxes are turned into small
|
||||
BSP trees instead of being compared directly.
|
||||
Capsules are handled differently though.
|
||||
===================
|
||||
*/
|
||||
int CM_TempBoxModel( const vec3_t mins, const vec3_t maxs )
|
||||
{
|
||||
VectorCopy( mins, box.model.mins );
|
||||
VectorCopy( maxs, box.model.maxs );
|
||||
|
||||
box.planes[0].dist = maxs[0];
|
||||
box.planes[1].dist = -maxs[0];
|
||||
box.planes[2].dist = mins[0];
|
||||
box.planes[3].dist = -mins[0];
|
||||
box.planes[4].dist = maxs[1];
|
||||
box.planes[5].dist = -maxs[1];
|
||||
box.planes[6].dist = mins[1];
|
||||
box.planes[7].dist = -mins[1];
|
||||
box.planes[8].dist = maxs[2];
|
||||
box.planes[9].dist = -maxs[2];
|
||||
box.planes[10].dist = mins[2];
|
||||
box.planes[11].dist = -mins[2];
|
||||
|
||||
VectorCopy( mins, box.brush->bounds[0] );
|
||||
VectorCopy( maxs, box.brush->bounds[1] );
|
||||
|
||||
return BOX_MODEL_HANDLE;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
CM_ModelBounds
|
||||
===================
|
||||
*/
|
||||
void CM_ModelBounds( cmodel_t *cmod, vec3_t mins, vec3_t maxs )
|
||||
{
|
||||
if( cmod )
|
||||
{
|
||||
VectorCopy( cmod->mins, mins );
|
||||
VectorCopy( cmod->maxs, maxs );
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorSet( mins, -32, -32, -32 );
|
||||
VectorSet( maxs, 32, 32, 32 );
|
||||
MsgWarn("can't compute bounding box, use default size\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ int CM_BoxLeafnums( const vec3_t mins, const vec3_t maxs, int *list, int listsiz
|
|||
|
||||
CM_BoxLeafnums_r( &ll, 0 );
|
||||
|
||||
//if( lastleaf ) *lastleaf = ll.lastleaf;//FIXME
|
||||
if( lastleaf ) *lastleaf = ll.lastleaf;
|
||||
return ll.count;
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ CM_PointContents
|
|||
|
||||
==================
|
||||
*/
|
||||
int CM_PointContents( const vec3_t p )
|
||||
int CM_PointContents( const vec3_t p, cmodel_t *model )
|
||||
{
|
||||
int leafnum;
|
||||
int i, k;
|
||||
|
@ -182,9 +182,16 @@ int CM_PointContents( const vec3_t p )
|
|||
float d;
|
||||
|
||||
if(!cm.numnodes) return 0; // map not loaded
|
||||
|
||||
leafnum = CM_PointLeafnum_r (p, 0);
|
||||
leaf = &cm.leafs[leafnum];
|
||||
if( model && model->type == mod_brush )
|
||||
{
|
||||
// ignore studio models
|
||||
leaf = &model->leaf;
|
||||
}
|
||||
else
|
||||
{
|
||||
leafnum = CM_PointLeafnum_r (p, 0);
|
||||
leaf = &cm.leafs[leafnum];
|
||||
}
|
||||
|
||||
contents = 0;
|
||||
for( k = 0; k < leaf->numleafbrushes; k++)
|
||||
|
@ -212,7 +219,7 @@ Handles offseting and rotation of the end points for moving and
|
|||
rotating entities
|
||||
==================
|
||||
*/
|
||||
int CM_TransformedPointContents( const vec3_t p, const vec3_t origin, const vec3_t angles )
|
||||
int CM_TransformedPointContents( const vec3_t p, cmodel_t *model, const vec3_t origin, const vec3_t angles )
|
||||
{
|
||||
vec3_t p_l;
|
||||
vec3_t temp;
|
||||
|
@ -230,5 +237,5 @@ int CM_TransformedPointContents( const vec3_t p, const vec3_t origin, const vec3
|
|||
p_l[1] = -DotProduct( temp, right );
|
||||
p_l[2] = DotProduct( temp, up );
|
||||
}
|
||||
return CM_PointContents( p_l );
|
||||
return CM_PointContents( p_l, model );
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
//=======================================================================
|
||||
|
||||
#include "cm_local.h"
|
||||
#include "basefiles.h"
|
||||
#include "cm_utils.h"
|
||||
|
||||
#define DIST_EPSILON (0.03125) // 1/32 epsilon to keep floating point happy
|
||||
#define MAX_POSITION_LEAFS 1024
|
||||
|
@ -111,16 +111,13 @@ void CM_TestBoxInBrush( tracework_t *tw, cbrush_t *brush )
|
|||
CM_TestInLeaf
|
||||
================
|
||||
*/
|
||||
void CM_TestInLeaf( tracework_t *tw, int leafnum )
|
||||
void CM_TestInLeaf( tracework_t *tw, cleaf_t *leaf )
|
||||
{
|
||||
int k;
|
||||
int brushnum;
|
||||
cleaf_t *leaf;
|
||||
cbrush_t *b;
|
||||
|
||||
leaf = &cm.leafs[leafnum];
|
||||
if(!(leaf->contents & maptrace.contents)) return;
|
||||
|
||||
// test box position against all brushes in the leaf
|
||||
for (k = 0; k < leaf->numleafbrushes; k++)
|
||||
{
|
||||
|
@ -300,7 +297,7 @@ void CM_PositionTest( tracework_t *tw )
|
|||
// test the contents of the leafs
|
||||
for( i = 0; i < ll.count; i++)
|
||||
{
|
||||
CM_TestInLeaf( tw, leafs[i] );
|
||||
CM_TestInLeaf( tw, &cm.leafs[leafs[i]] );
|
||||
if( tw->result.allsolid )
|
||||
break;
|
||||
}
|
||||
|
@ -420,22 +417,23 @@ void CM_TraceThroughTree( tracework_t *tw, int num, float p1f, float p2f, vec3_t
|
|||
CM_Trace
|
||||
==================
|
||||
*/
|
||||
void CM_Trace( trace_t *results, const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, int brushmask )
|
||||
void CM_Trace( trace_t *results, const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *mod, const vec3_t origin, int brushmask )
|
||||
{
|
||||
int i;
|
||||
tracework_t tw;
|
||||
vec3_t offset;
|
||||
|
||||
|
||||
cm.checkcount++; // for multi-check avoidance
|
||||
|
||||
// fill in a default trace
|
||||
memset( &tw, 0, sizeof(tw) );
|
||||
tw.result.fraction = 1; // assume it goes the entire distance until shown otherwise
|
||||
tw.result.fraction = 1; // assume it goes the entire distance until shown otherwise
|
||||
VectorCopy( origin, tw.origin );
|
||||
|
||||
if(!cm.numnodes)
|
||||
{
|
||||
*results = tw.result;
|
||||
return; // map not loaded, shouldn't happen
|
||||
return; // map not loaded, shouldn't happen
|
||||
}
|
||||
|
||||
// allow NULL to be passed in for 0,0,0
|
||||
|
@ -510,7 +508,8 @@ void CM_Trace( trace_t *results, const vec3_t start, const vec3_t end, vec3_t mi
|
|||
// check for position test special case
|
||||
if( VectorCompare( start, end ))
|
||||
{
|
||||
CM_PositionTest( &tw );
|
||||
if( mod && mod->type == mod_brush ) CM_TestInLeaf( &tw, &mod->leaf );
|
||||
else CM_PositionTest( &tw );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -527,8 +526,10 @@ void CM_Trace( trace_t *results, const vec3_t start, const vec3_t end, vec3_t mi
|
|||
tw.extents[1] = tw.maxs[1];
|
||||
tw.extents[2] = tw.maxs[2];
|
||||
}
|
||||
|
||||
// general sweeping through world
|
||||
CM_TraceThroughTree( &tw, 0, 0, 1, tw.start, tw.end );
|
||||
if ( mod && mod->type == mod_brush ) CM_TraceThroughLeaf( &tw, &mod->leaf );
|
||||
else CM_TraceThroughTree( &tw, 0, 0, 1, tw.start, tw.end );
|
||||
}
|
||||
|
||||
// generate endpos from the original, unmodified start/end
|
||||
|
@ -557,15 +558,14 @@ void CM_Trace( trace_t *results, const vec3_t start, const vec3_t end, vec3_t mi
|
|||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_BoxTrace
|
||||
==================
|
||||
*/
|
||||
trace_t CM_BoxTrace( vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, int brushmask )
|
||||
trace_t CM_BoxTrace( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *model, int brushmask )
|
||||
{
|
||||
CM_Trace( &cm.trace, start, end, mins, maxs, brushmask );
|
||||
CM_Trace( &cm.trace, start, end, mins, maxs, model, vec3_origin, brushmask );
|
||||
return cm.trace;
|
||||
}
|
||||
|
||||
|
@ -577,7 +577,7 @@ Handles offseting and rotation of the end points for moving and
|
|||
rotating entities
|
||||
==================
|
||||
*/
|
||||
trace_t CM_TransformedBoxTrace( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, int brushmask, vec3_t origin, vec3_t angles )
|
||||
trace_t CM_TransformedBoxTrace( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *model, int brushmask, vec3_t origin, vec3_t angles )
|
||||
{
|
||||
trace_t trace;
|
||||
vec3_t start_l, end_l;
|
||||
|
@ -608,7 +608,7 @@ trace_t CM_TransformedBoxTrace( const vec3_t start, const vec3_t end, vec3_t min
|
|||
VectorSubtract( end_l, origin, end_l );
|
||||
|
||||
// rotate start and end into the models frame of reference
|
||||
if (!VectorIsNull( angles )) rotated = true;
|
||||
if(!VectorIsNull( angles )) rotated = true;
|
||||
else rotated = false;
|
||||
|
||||
if( rotated )
|
||||
|
@ -625,7 +625,7 @@ trace_t CM_TransformedBoxTrace( const vec3_t start, const vec3_t end, vec3_t min
|
|||
}
|
||||
|
||||
// sweep the box through the model
|
||||
CM_Trace( &trace, start_l, end_l, symetricSize[0], symetricSize[1], brushmask );
|
||||
CM_Trace( &trace, start_l, end_l, symetricSize[0], symetricSize[1], model, origin, brushmask );
|
||||
|
||||
// if the bmodel was rotated and there was a collision
|
||||
if( rotated && trace.fraction != 1.0 )
|
||||
|
|
|
@ -44,10 +44,10 @@ int CM_NumTexinfo( void );
|
|||
int CM_NumInlineModels( void );
|
||||
const char *CM_EntityString( void );
|
||||
const char *CM_TexName( int index );
|
||||
int CM_PointContents( const vec3_t p );
|
||||
int CM_TransformedPointContents( const vec3_t p, const vec3_t origin, const vec3_t angles );
|
||||
trace_t CM_BoxTrace( vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, int brushmask );
|
||||
trace_t CM_TransformedBoxTrace( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, int brushmask, vec3_t origin, vec3_t angles );
|
||||
int CM_PointContents( const vec3_t p, cmodel_t *model );
|
||||
int CM_TransformedPointContents( const vec3_t p, cmodel_t *model, const vec3_t origin, const vec3_t angles );
|
||||
trace_t CM_BoxTrace( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *model, int brushmask );
|
||||
trace_t CM_TransformedBoxTrace( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *model, int brushmask, vec3_t origin, vec3_t angles );
|
||||
byte *CM_ClusterPVS( int cluster );
|
||||
byte *CM_ClusterPHS( int cluster );
|
||||
int CM_PointLeafnum( const vec3_t p );
|
||||
|
@ -56,5 +56,6 @@ int CM_LeafCluster( int leafnum );
|
|||
int CM_LeafArea( int leafnum );
|
||||
bool CM_AreasConnected( int area1, int area2 );
|
||||
int CM_WriteAreaBits( byte *buffer, int area );
|
||||
void CM_ModelBounds( cmodel_t *model, vec3_t mins, vec3_t maxs );
|
||||
|
||||
#endif//CM_UTILS_H
|
|
@ -289,6 +289,7 @@ void() PutClientInServer =
|
|||
pev->mass = 90;
|
||||
pev->th_pain = PlayerPain;
|
||||
pev->th_die = PlayerDie;
|
||||
pev->touch = PlayerTouch;
|
||||
|
||||
setstats( pev, STAT_HEALTH_ICON, "hud/i_health");
|
||||
setstats( pev, STAT_HEALTH, ftoa(pev->health));
|
||||
|
|
|
@ -186,6 +186,11 @@ void() func_mover_touch =
|
|||
}
|
||||
};
|
||||
|
||||
void func_mover_null ( void )
|
||||
{
|
||||
// null touching function
|
||||
}
|
||||
|
||||
void() func_mover_use =
|
||||
{
|
||||
if(pev->message)
|
||||
|
@ -221,6 +226,7 @@ void() func_mover =
|
|||
pev->th_die = func_mover_die;
|
||||
|
||||
if(!pev->targetname) pev->touch = func_mover_touch;
|
||||
else pev->touch = func_mover_null;
|
||||
|
||||
//func_mover; DEFAULTS;
|
||||
if (!pev->speed)
|
||||
|
|
|
@ -51,6 +51,11 @@ void() func_illusionary =
|
|||
pev->solid = SOLID_TRIGGER;
|
||||
};
|
||||
|
||||
void func_wall_touch ( void )
|
||||
{
|
||||
// null touching function
|
||||
}
|
||||
|
||||
void animate_wall( void )
|
||||
{
|
||||
pev->frame++;
|
||||
|
@ -66,6 +71,7 @@ void() func_wall =
|
|||
|
||||
pev->nextthink = time + 1.0;
|
||||
pev->think = animate_wall;
|
||||
pev->touch = func_wall_touch;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -204,6 +204,10 @@ void() DeathSound =
|
|||
sound (pev, CHAN_VOICE, pev->noise, 1, ATTN_NONE);
|
||||
};
|
||||
|
||||
void PlayerTouch( void )
|
||||
{
|
||||
}
|
||||
|
||||
void () PlayerDie =
|
||||
{
|
||||
pev->view_ofs = '0 0 -8';
|
||||
|
|
|
@ -245,10 +245,10 @@ typedef struct physic_exp_s
|
|||
int (*NumBmodels )( void );
|
||||
const char *(*GetEntityString)( void );
|
||||
const char *(*GetTextureName)( int index );
|
||||
int (*PointContents)( const vec3_t p );
|
||||
int (*TransformedPointContents)( const vec3_t p, const vec3_t origin, const vec3_t angles );
|
||||
trace_t (*BoxTrace)( vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, int brushmask);
|
||||
trace_t (*TransformedBoxTrace)( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, int brushmask, vec3_t origin, vec3_t angles );
|
||||
int (*PointContents)( const vec3_t p, cmodel_t *model );
|
||||
int (*TransformedPointContents)( const vec3_t p, cmodel_t *model, const vec3_t origin, const vec3_t angles );
|
||||
trace_t (*BoxTrace)( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *model, int brushmask);
|
||||
trace_t (*TransformedBoxTrace)( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *model, int brushmask, vec3_t origin, vec3_t angles );
|
||||
byte *(*ClusterPVS)( int cluster );
|
||||
byte *(*ClusterPHS)( int cluster );
|
||||
int (*PointLeafnum)( vec3_t p );
|
||||
|
|
|
@ -960,6 +960,23 @@ _inline void CM_RoundUpHullSize( vec3_t size )
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
RadiusFromBounds
|
||||
=================
|
||||
*/
|
||||
_inline float RadiusFromBounds( vec3_t mins, vec3_t maxs )
|
||||
{
|
||||
int i;
|
||||
vec3_t corner;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
|
||||
}
|
||||
return VectorLength( corner );
|
||||
}
|
||||
|
||||
static vec3_t vec3_origin = { 0, 0, 0 };
|
||||
static vec3_t vec3_angles = { 0, 0, 0 };
|
||||
|
||||
|
|
|
@ -1364,6 +1364,15 @@ typedef struct cplane_s
|
|||
byte pad[2];
|
||||
} cplane_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int contents;
|
||||
int cluster;
|
||||
int area;
|
||||
int firstleafbrush;
|
||||
int numleafbrushes;
|
||||
} cleaf_t;
|
||||
|
||||
typedef struct cmesh_s
|
||||
{
|
||||
vec3_t *verts;
|
||||
|
@ -1376,8 +1385,8 @@ typedef struct cmodel_s
|
|||
byte *mempool; // personal mempool
|
||||
int registration_sequence;
|
||||
|
||||
vec3_t mins, maxs; // boundbox
|
||||
int headnode; // bsp info
|
||||
vec3_t mins, maxs; // model boundbox
|
||||
cleaf_t leaf;
|
||||
int type; // model type
|
||||
int firstface; // used to create collision tree
|
||||
int numfaces;
|
||||
|
|
|
@ -372,25 +372,6 @@ void Mod_LoadVertexes (lump_t *l)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
RadiusFromBounds
|
||||
=================
|
||||
*/
|
||||
float RadiusFromBounds (vec3_t mins, vec3_t maxs)
|
||||
{
|
||||
int i;
|
||||
vec3_t corner;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
|
||||
}
|
||||
|
||||
return VectorLength (corner);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadSubmodels
|
||||
|
|
Reference in New Issue