31 Jul 2008
This commit is contained in:
parent
f4cee11c57
commit
ad1f8e3181
|
@ -1,5 +1,5 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2007 ©
|
||||
// Copyright XashXT Group 2008 ©
|
||||
// rc_main.c - resource library
|
||||
//=======================================================================
|
||||
|
||||
|
|
|
@ -260,7 +260,7 @@ void ProcessModels (void)
|
|||
EndBSPFile ();
|
||||
}
|
||||
|
||||
static void AddCollision(void* handle, const void* buffer, size_t size)
|
||||
static void AddCollision( void* handle, const void* buffer, size_t size )
|
||||
{
|
||||
Mem_Copy( dcollision + dcollisiondatasize, (void *)buffer, size );
|
||||
dcollisiondatasize += size;
|
||||
|
|
|
@ -27,7 +27,7 @@ platform.dll needs for some setup operations
|
|||
so do it manually
|
||||
==================
|
||||
*/
|
||||
void InitPlatform ( uint funcname, int argc, char **argv )
|
||||
void InitPlatform ( int argc, char **argv )
|
||||
{
|
||||
byte bspflags = 0, qccflags = 0, roqflags = 0;
|
||||
char source[64], gamedir[64];
|
||||
|
@ -38,13 +38,13 @@ void InitPlatform ( uint funcname, int argc, char **argv )
|
|||
// for custom cmdline parsing
|
||||
com_argc = argc;
|
||||
com_argv = argv;
|
||||
app_name = funcname;
|
||||
app_name = g_Instance;
|
||||
|
||||
Sys_LoadLibrary( &imglib_dll ); // load imagelib
|
||||
CreateImglib = (void *)imglib_dll.main;
|
||||
Image = CreateImglib( &com, NULL ); // second interface not allowed
|
||||
|
||||
switch( funcname )
|
||||
switch( app_name )
|
||||
{
|
||||
case COMP_BSPLIB:
|
||||
if(!FS_GetParmFromCmdLine("-game", gamedir ))
|
||||
|
@ -63,7 +63,7 @@ void InitPlatform ( uint funcname, int argc, char **argv )
|
|||
CreateVprogs = (void *)vprogs_dll.main;
|
||||
PRVM = CreateVprogs( &com, NULL ); // second interface not allowed
|
||||
|
||||
PRVM->Init( funcname, argc, argv );
|
||||
PRVM->Init( argc, argv );
|
||||
|
||||
if(!FS_GetParmFromCmdLine("-dir", gamedir ))
|
||||
com.strncpy(gamedir, ".", sizeof(gamedir));
|
||||
|
@ -84,7 +84,7 @@ void InitPlatform ( uint funcname, int argc, char **argv )
|
|||
break;
|
||||
}
|
||||
|
||||
Image->Init( funcname ); // initialize image support
|
||||
Image->Init(); // initialize image support
|
||||
}
|
||||
|
||||
void RunPlatform ( void )
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// platform export
|
||||
//=====================================
|
||||
|
||||
void InitPlatform ( uint funcname, int argc, char **argv ); // init host
|
||||
void InitPlatform ( int argc, char **argv ); // init host
|
||||
void RunPlatform ( void ); // host frame
|
||||
void ClosePlatform ( void ); // close host
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ void CL_WriteDemoHeader( const char *name )
|
|||
{
|
||||
ent = PRVM_EDICT_NUM( i );
|
||||
state = &ent->priv.cl->baseline;
|
||||
if(!state->modelindex) continue;
|
||||
if(!state->model.index) continue;
|
||||
|
||||
if( buf.cursize + 64 > buf.maxsize )
|
||||
{
|
||||
|
|
|
@ -59,14 +59,19 @@ struct cl_entvars_s
|
|||
float modelindex;
|
||||
float soundindex;
|
||||
int chain;
|
||||
int owner;
|
||||
string_t model;
|
||||
vec3_t origin;
|
||||
vec3_t angles;
|
||||
vec3_t mins;
|
||||
vec3_t maxs;
|
||||
float solid;
|
||||
float sequence;
|
||||
float effects;
|
||||
float frame;
|
||||
float body;
|
||||
float skin;
|
||||
float flags;
|
||||
};
|
||||
|
||||
|
||||
|
@ -74,9 +79,9 @@ struct cl_entvars_s
|
|||
|
||||
static fields_t cl_reqfields[] =
|
||||
{
|
||||
{17, 2, "flags"}
|
||||
{26, 2, "aiflags"}
|
||||
};
|
||||
|
||||
#define PROG_CRC_CLIENT 4546
|
||||
#define PROG_CRC_CLIENT 3720
|
||||
|
||||
#endif//CL_EDICT_H
|
|
@ -78,8 +78,8 @@ void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t
|
|||
frame->num_entities++;
|
||||
|
||||
// some data changes will force no lerping
|
||||
if( state->modelindex != ent->priv.cl->current.modelindex || state->weaponmodel != ent->priv.cl->current.weaponmodel || state->body != ent->priv.cl->current.body
|
||||
|| state->sequence != ent->priv.cl->current.sequence || abs(state->origin[0] - ent->priv.cl->current.origin[0]) > 512
|
||||
if( state->model.index != ent->priv.cl->current.model.index || state->pmodel.index != ent->priv.cl->current.pmodel.index || state->model.body != ent->priv.cl->current.model.body
|
||||
|| state->model.sequence != ent->priv.cl->current.model.sequence || abs(state->origin[0] - ent->priv.cl->current.origin[0]) > 512
|
||||
|| abs(state->origin[1] - ent->priv.cl->current.origin[1]) > 512 || abs(state->origin[2] - ent->priv.cl->current.origin[2]) > 512 )
|
||||
{
|
||||
ent->priv.cl->serverframe = -99;
|
||||
|
@ -335,27 +335,27 @@ void CL_AddPacketEntities( frame_t *frame )
|
|||
|
||||
effects = s1->effects;
|
||||
renderfx = s1->renderfx;
|
||||
refent.frame = s1->frame;
|
||||
refent.frame = s1->model.frame;
|
||||
|
||||
// copy state to progs
|
||||
ent->progs.cl->modelindex = ent->priv.cl->current.modelindex;
|
||||
ent->progs.cl->modelindex = ent->priv.cl->current.model.index;
|
||||
ent->progs.cl->soundindex = ent->priv.cl->current.soundindex;
|
||||
//ent->progs.cl->model = PRVM_SetEngineString( cl.configstrings[CS_MODELS+ent->priv.cl->current.modelindex] );
|
||||
//ent->progs.cl->model = PRVM_SetEngineString( cl.configstrings[CS_MODELS+ent->priv.cl->current.model.index] );
|
||||
|
||||
// copy state to render
|
||||
refent.prev.frame = ent->priv.cl->prev.frame;
|
||||
refent.prev.frame = ent->priv.cl->prev.model.frame;
|
||||
refent.backlerp = 1.0 - cl.lerpfrac;
|
||||
refent.alpha = s1->alpha;
|
||||
refent.body = s1->body;
|
||||
refent.sequence = s1->sequence;
|
||||
refent.animtime = s1->animtime;
|
||||
refent.alpha = s1->renderamt;
|
||||
refent.body = s1->model.body;
|
||||
refent.sequence = s1->model.sequence;
|
||||
refent.animtime = s1->model.animtime;
|
||||
|
||||
// setup latchedvars
|
||||
refent.prev.animtime = ent->priv.cl->prev.animtime;
|
||||
refent.prev.animtime = ent->priv.cl->prev.model.animtime;
|
||||
VectorCopy( ent->priv.cl->prev.origin, refent.prev.origin );
|
||||
VectorCopy( ent->priv.cl->prev.angles, refent.prev.angles );
|
||||
refent.prev.sequence = ent->priv.cl->prev.sequence;
|
||||
refent.prev.frame = ent->priv.cl->prev.frame;
|
||||
refent.prev.sequence = ent->priv.cl->prev.model.sequence;
|
||||
refent.prev.frame = ent->priv.cl->prev.model.frame;
|
||||
//refent.prev.sequencetime;
|
||||
|
||||
// interpolate origin
|
||||
|
@ -366,10 +366,10 @@ void CL_AddPacketEntities( frame_t *frame )
|
|||
}
|
||||
|
||||
// set skin
|
||||
refent.skin = s1->skin;
|
||||
refent.model = cl.model_draw[s1->modelindex];
|
||||
refent.weaponmodel = cl.model_draw[s1->weaponmodel];
|
||||
refent.flags = renderfx;
|
||||
refent.skin = s1->model.skin;
|
||||
refent.model = cl.model_draw[s1->model.index];
|
||||
refent.weaponmodel = cl.model_draw[s1->pmodel.index];
|
||||
refent.flags = renderfx;//FIXME: it's wrong!!!
|
||||
|
||||
// calculate angles
|
||||
if( effects & EF_ROTATE )
|
||||
|
@ -402,7 +402,7 @@ void CL_AddPacketEntities( frame_t *frame )
|
|||
}
|
||||
|
||||
// if set to invisible, skip
|
||||
if( !s1->modelindex ) continue;
|
||||
if( !s1->model.index ) continue;
|
||||
|
||||
// add to refresh list
|
||||
V_AddEntity( &refent );
|
||||
|
@ -416,10 +416,9 @@ void CL_AddPacketEntities( frame_t *frame )
|
|||
CL_AddViewWeapon
|
||||
==============
|
||||
*/
|
||||
void CL_AddViewWeapon( player_state_t *ps, player_state_t *ops )
|
||||
void CL_AddViewWeapon( entity_state_t *ps, entity_state_t *ops )
|
||||
{
|
||||
entity_t gun; // view model
|
||||
int i;
|
||||
|
||||
// allow the gun to be completely removed
|
||||
if( !cl_gun->value ) return;
|
||||
|
@ -434,11 +433,8 @@ void CL_AddViewWeapon( player_state_t *ps, player_state_t *ops )
|
|||
if (!gun.model) return;
|
||||
|
||||
// set up gun position
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
gun.origin[i] = gun.oldorigin[i] = cl.refdef.vieworg[i] + ops->vmodel.offset[i] + (ps->vmodel.offset[i] - ops->vmodel.offset[i]) * cl.lerpfrac;
|
||||
gun.angles[i] = cl.refdef.viewangles[i] + LerpAngle (ops->vmodel.angles[i], ps->vmodel.angles[i], cl.lerpfrac);
|
||||
}
|
||||
VectorCopy( cl.refdef.vieworg, gun.origin );
|
||||
VectorCopy( cl.refdef.viewangles, gun.angles );
|
||||
|
||||
gun.frame = ps->vmodel.frame;
|
||||
if( gun.frame == 0 ) gun.prev.frame = 0; // just changed weapons, don't lerp from old
|
||||
|
@ -467,7 +463,7 @@ void CL_CalcViewValues( void )
|
|||
int i;
|
||||
float lerp, backlerp;
|
||||
frame_t *oldframe;
|
||||
player_state_t *ps, *ops;
|
||||
entity_state_t *ps, *ops;
|
||||
|
||||
// clamp time
|
||||
if( cl.time > cl.frame.servertime )
|
||||
|
@ -540,7 +536,7 @@ void CL_CalcViewValues( void )
|
|||
}
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
cl.refdef.viewangles[i] += LerpAngle( ops->kick_angles[i], ps->kick_angles[i], lerp );
|
||||
cl.refdef.viewangles[i] += LerpAngle( ops->punch_angles[i], ps->punch_angles[i], lerp );
|
||||
|
||||
AngleVectors( cl.refdef.viewangles, cl.v_forward, cl.v_right, cl.v_up );
|
||||
|
||||
|
@ -548,8 +544,7 @@ void CL_CalcViewValues( void )
|
|||
cl.refdef.fov_x = ops->fov + lerp * ( ps->fov - ops->fov );
|
||||
|
||||
// don't interpolate blend color
|
||||
for( i = 0; i < 4; i++ )
|
||||
cl.refdef.blend[i] = ps->blend[i];
|
||||
Vector4Set( cl.refdef.blend, 0, 0, 0, 0 ); // FIXME: calculate blend on client-side
|
||||
|
||||
// add the weapon
|
||||
CL_AddViewWeapon( ps, ops );
|
||||
|
@ -606,7 +601,7 @@ void CL_GetEntitySoundSpatialization( int entnum, vec3_t origin, vec3_t velocity
|
|||
// if a brush model, offset the origin
|
||||
if( VectorIsNull( origin ))
|
||||
{
|
||||
cmodel = cl.model_clip[ent->priv.cl->current.modelindex];
|
||||
cmodel = cl.models[ent->priv.cl->current.model.index];
|
||||
if(!cmodel) return;
|
||||
VectorAverage( cmodel->mins, cmodel->maxs, midPoint );
|
||||
VectorAdd( origin, midPoint, origin );
|
||||
|
|
|
@ -1119,12 +1119,6 @@ void Key_Event(int key, bool down, uint time)
|
|||
// escape is always handled special
|
||||
if ( key == K_ESCAPE && down )
|
||||
{
|
||||
if (cl.frame.ps.stats[STAT_LAYOUTS] && cls.key_dest == key_game)
|
||||
{
|
||||
// put away help computer / inventory
|
||||
Cbuf_AddText ("cmd putaway\n");
|
||||
return;
|
||||
}
|
||||
switch( cls.key_dest )
|
||||
{
|
||||
case key_message:
|
||||
|
|
|
@ -74,10 +74,6 @@ client_t cl;
|
|||
entity_state_t cl_parse_entities[MAX_PARSE_ENTITIES];
|
||||
|
||||
extern cvar_t *allow_download;
|
||||
extern cvar_t *allow_download_players;
|
||||
extern cvar_t *allow_download_models;
|
||||
extern cvar_t *allow_download_sounds;
|
||||
extern cvar_t *allow_download_maps;
|
||||
//======================================================================
|
||||
|
||||
//======================================================================
|
||||
|
@ -900,83 +896,77 @@ void CL_RequestNextDownload (void)
|
|||
{
|
||||
// confirm map
|
||||
precache_check = CS_MODELS+2; // 0 isn't used
|
||||
if (allow_download_maps->value)
|
||||
if (!CL_CheckOrDownloadFile(cl.configstrings[CS_MODELS+1]))
|
||||
return; // started a download
|
||||
if (!CL_CheckOrDownloadFile(cl.configstrings[CS_MODELS+1]))
|
||||
return; // started a download
|
||||
}
|
||||
if (precache_check >= CS_MODELS && precache_check < CS_MODELS+MAX_MODELS)
|
||||
{
|
||||
if (allow_download_models->value)
|
||||
while (precache_check < CS_MODELS+MAX_MODELS && cl.configstrings[precache_check][0])
|
||||
{
|
||||
while (precache_check < CS_MODELS+MAX_MODELS &&
|
||||
cl.configstrings[precache_check][0]) {
|
||||
if (cl.configstrings[precache_check][0] == '*' ||
|
||||
cl.configstrings[precache_check][0] == '#') {
|
||||
if (cl.configstrings[precache_check][0] == '*' || cl.configstrings[precache_check][0] == '#')
|
||||
{
|
||||
precache_check++;
|
||||
continue;
|
||||
}
|
||||
if (precache_model_skin == 0)
|
||||
{
|
||||
if (!CL_CheckOrDownloadFile(cl.configstrings[precache_check])) {
|
||||
precache_model_skin = 1;
|
||||
return; // started a download
|
||||
}
|
||||
precache_model_skin = 1;
|
||||
}
|
||||
|
||||
// checking for skins in the model
|
||||
if (!precache_model)
|
||||
{
|
||||
precache_model = FS_LoadFile (cl.configstrings[precache_check], NULL);
|
||||
if (!precache_model)
|
||||
{
|
||||
precache_model_skin = 0;
|
||||
precache_check++;
|
||||
continue; // couldn't load it
|
||||
}
|
||||
if (LittleLong(*(uint *)precache_model) != IDSTUDIOHEADER)
|
||||
{
|
||||
// not an studio model
|
||||
precache_model = 0;
|
||||
precache_model_skin = 0;
|
||||
precache_check++;
|
||||
continue;
|
||||
}
|
||||
if (precache_model_skin == 0) {
|
||||
if (!CL_CheckOrDownloadFile(cl.configstrings[precache_check])) {
|
||||
precache_model_skin = 1;
|
||||
return; // started a download
|
||||
}
|
||||
precache_model_skin = 1;
|
||||
}
|
||||
|
||||
// checking for skins in the model
|
||||
if (!precache_model) {
|
||||
|
||||
precache_model = FS_LoadFile (cl.configstrings[precache_check], NULL);
|
||||
if (!precache_model)
|
||||
{
|
||||
precache_model_skin = 0;
|
||||
precache_check++;
|
||||
continue; // couldn't load it
|
||||
}
|
||||
if (LittleLong(*(uint *)precache_model) != IDSTUDIOHEADER)
|
||||
{
|
||||
// not an studio model
|
||||
precache_model = 0;
|
||||
precache_model_skin = 0;
|
||||
precache_check++;
|
||||
continue;
|
||||
}
|
||||
pheader = (studiohdr_t *)precache_model;
|
||||
if (LittleLong (pheader->version) != STUDIO_VERSION)
|
||||
{
|
||||
precache_check++;
|
||||
precache_model_skin = 0;
|
||||
continue; // couldn't load it
|
||||
}
|
||||
}
|
||||
|
||||
pheader = (studiohdr_t *)precache_model;
|
||||
|
||||
if (precache_model)
|
||||
{
|
||||
precache_model = 0;
|
||||
if (LittleLong (pheader->version) != STUDIO_VERSION)
|
||||
{
|
||||
precache_check++;
|
||||
precache_model_skin = 0;
|
||||
continue; // couldn't load it
|
||||
}
|
||||
precache_model_skin = 0;
|
||||
precache_check++;
|
||||
}
|
||||
|
||||
pheader = (studiohdr_t *)precache_model;
|
||||
|
||||
if (precache_model)
|
||||
{
|
||||
precache_model = 0;
|
||||
}
|
||||
precache_model_skin = 0;
|
||||
precache_check++;
|
||||
}
|
||||
precache_check = CS_SOUNDS;
|
||||
}
|
||||
if (precache_check >= CS_SOUNDS && precache_check < CS_SOUNDS+MAX_SOUNDS)
|
||||
{
|
||||
if (allow_download_sounds->value)
|
||||
if (precache_check == CS_SOUNDS) precache_check++; // zero is blank
|
||||
while (precache_check < CS_SOUNDS+MAX_SOUNDS && cl.configstrings[precache_check][0])
|
||||
{
|
||||
if (precache_check == CS_SOUNDS) precache_check++; // zero is blank
|
||||
while (precache_check < CS_SOUNDS+MAX_SOUNDS && cl.configstrings[precache_check][0])
|
||||
if (cl.configstrings[precache_check][0] == '*')
|
||||
{
|
||||
if (cl.configstrings[precache_check][0] == '*')
|
||||
{
|
||||
precache_check++;
|
||||
continue;
|
||||
}
|
||||
com.sprintf(fn, "sound/%s", cl.configstrings[precache_check++]);
|
||||
if (!CL_CheckOrDownloadFile(fn)) return; // started a download
|
||||
precache_check++;
|
||||
continue;
|
||||
}
|
||||
com.sprintf(fn, "sound/%s", cl.configstrings[precache_check++]);
|
||||
if (!CL_CheckOrDownloadFile(fn)) return; // started a download
|
||||
}
|
||||
precache_check = CS_IMAGES;
|
||||
}
|
||||
|
@ -995,59 +985,55 @@ void CL_RequestNextDownload (void)
|
|||
// so precache_check is now *3
|
||||
if (precache_check >= CS_PLAYERSKINS && precache_check < CS_PLAYERSKINS + MAX_CLIENTS * PLAYER_MULT)
|
||||
{
|
||||
if (allow_download_players->value)
|
||||
while (precache_check < CS_PLAYERSKINS + MAX_CLIENTS * PLAYER_MULT)
|
||||
{
|
||||
while (precache_check < CS_PLAYERSKINS + MAX_CLIENTS * PLAYER_MULT)
|
||||
int i, n;
|
||||
char model[MAX_QPATH], skin[MAX_QPATH], *p;
|
||||
|
||||
i = (precache_check - CS_PLAYERSKINS)/PLAYER_MULT;
|
||||
n = (precache_check - CS_PLAYERSKINS)%PLAYER_MULT;
|
||||
|
||||
if (!cl.configstrings[CS_PLAYERSKINS+i][0])
|
||||
{
|
||||
int i, n;
|
||||
char model[MAX_QPATH], skin[MAX_QPATH], *p;
|
||||
precache_check = CS_PLAYERSKINS + (i + 1) * PLAYER_MULT;
|
||||
continue;
|
||||
}
|
||||
|
||||
i = (precache_check - CS_PLAYERSKINS)/PLAYER_MULT;
|
||||
n = (precache_check - CS_PLAYERSKINS)%PLAYER_MULT;
|
||||
if ((p = strchr(cl.configstrings[CS_PLAYERSKINS+i], '\\')) != NULL)
|
||||
p++;
|
||||
else p = cl.configstrings[CS_PLAYERSKINS+i];
|
||||
strcpy(model, p);
|
||||
p = strchr(model, '/');
|
||||
if (!p) p = strchr(model, '\\');
|
||||
if (p)
|
||||
{
|
||||
*p++ = 0;
|
||||
strcpy(skin, p);
|
||||
}
|
||||
else *skin = 0;
|
||||
|
||||
if (!cl.configstrings[CS_PLAYERSKINS+i][0]) {
|
||||
precache_check = CS_PLAYERSKINS + (i + 1) * PLAYER_MULT;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((p = strchr(cl.configstrings[CS_PLAYERSKINS+i], '\\')) != NULL)
|
||||
p++;
|
||||
else p = cl.configstrings[CS_PLAYERSKINS+i];
|
||||
strcpy(model, p);
|
||||
p = strchr(model, '/');
|
||||
if (!p)
|
||||
p = strchr(model, '\\');
|
||||
if (p)
|
||||
switch (n)
|
||||
{
|
||||
case 0: // model
|
||||
com.sprintf(fn, "models/players/%s/player.mdl", model);
|
||||
if (!CL_CheckOrDownloadFile(fn))
|
||||
{
|
||||
*p++ = 0;
|
||||
strcpy(skin, p);
|
||||
precache_check = CS_PLAYERSKINS + i * PLAYER_MULT + 1;
|
||||
return; // started a download
|
||||
}
|
||||
else *skin = 0;
|
||||
|
||||
switch (n)
|
||||
n++;
|
||||
/*FALL THROUGH*/
|
||||
case 1: // weapon model
|
||||
com.sprintf(fn, "weapons/%s.mdl", model);
|
||||
if (!CL_CheckOrDownloadFile(fn))
|
||||
{
|
||||
case 0: // model
|
||||
com.sprintf(fn, "models/players/%s/player.mdl", model);
|
||||
if (!CL_CheckOrDownloadFile(fn))
|
||||
{
|
||||
precache_check = CS_PLAYERSKINS + i * PLAYER_MULT + 1;
|
||||
return; // started a download
|
||||
}
|
||||
n++;
|
||||
/*FALL THROUGH*/
|
||||
|
||||
case 1: // weapon model
|
||||
com.sprintf(fn, "weapons/%s.mdl", model);
|
||||
if (!CL_CheckOrDownloadFile(fn))
|
||||
{
|
||||
precache_check = CS_PLAYERSKINS + i * PLAYER_MULT + 2;
|
||||
return; // started a download
|
||||
}
|
||||
n++;
|
||||
/*FALL THROUGH*/
|
||||
default:
|
||||
break;
|
||||
precache_check = CS_PLAYERSKINS + i * PLAYER_MULT + 2;
|
||||
return; // started a download
|
||||
}
|
||||
n++;
|
||||
/*FALL THROUGH*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// precache phase completed
|
||||
|
@ -1058,7 +1044,7 @@ void CL_RequestNextDownload (void)
|
|||
{
|
||||
precache_check = ENV_CNT + 1;
|
||||
|
||||
pe->BeginRegistration( cl.configstrings[CS_MODELS+1], true, &map_checksum );
|
||||
cl.worldmodel = pe->BeginRegistration( cl.configstrings[CS_MODELS+1], true, &map_checksum );
|
||||
if( map_checksum != com.atoi(cl.configstrings[CS_MAPCHECKSUM]))
|
||||
{
|
||||
Host_Error("Local map version differs from server: %i != '%s'\n", map_checksum, cl.configstrings[CS_MAPCHECKSUM]);
|
||||
|
@ -1068,7 +1054,7 @@ void CL_RequestNextDownload (void)
|
|||
|
||||
if (precache_check > ENV_CNT && precache_check < TEXTURE_CNT)
|
||||
{
|
||||
if (allow_download->value && allow_download_maps->value)
|
||||
if( allow_download->value )
|
||||
{
|
||||
while (precache_check < TEXTURE_CNT)
|
||||
{
|
||||
|
@ -1091,7 +1077,7 @@ void CL_RequestNextDownload (void)
|
|||
// confirm existance of textures, download any that don't exist
|
||||
if (precache_check == TEXTURE_CNT+1)
|
||||
{
|
||||
if (allow_download->value && allow_download_maps->value)
|
||||
if( allow_download->value )
|
||||
{
|
||||
while( precache_tex < pe->NumTextures())
|
||||
{
|
||||
|
|
|
@ -466,10 +466,8 @@ void CL_ParseConfigString( sizebuf_t *msg )
|
|||
{
|
||||
if(cl.refresh_prepped)
|
||||
{
|
||||
cl.model_draw[i-CS_MODELS] = re->RegisterModel (cl.configstrings[i]);
|
||||
if (cl.configstrings[i][0] == '*')
|
||||
cl.model_clip[i-CS_MODELS] = pe->RegisterModel(cl.configstrings[i] );
|
||||
else cl.model_clip[i-CS_MODELS] = NULL;
|
||||
cl.model_draw[i-CS_MODELS] = re->RegisterModel( cl.configstrings[i] );
|
||||
cl.models[i-CS_MODELS] = pe->RegisterModel( cl.configstrings[i] );
|
||||
}
|
||||
}
|
||||
else if (i >= CS_SOUNDS && i < CS_SOUNDS+MAX_MODELS)
|
||||
|
|
|
@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include "matrixlib.h"
|
||||
|
||||
/*
|
||||
===================
|
||||
|
@ -60,6 +61,127 @@ void CL_CheckPredictionError (void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CL_Trace
|
||||
==================
|
||||
*/
|
||||
trace_t CL_Trace( const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, edict_t *passedict, int contentsmask )
|
||||
{
|
||||
vec3_t hullmins, hullmaxs;
|
||||
int i, bodycontents;
|
||||
int passedictprog;
|
||||
bool pointtrace;
|
||||
edict_t *traceowner, *touch;
|
||||
trace_t trace;
|
||||
vec3_t clipboxmins, clipboxmaxs; // bounding box of entire move area
|
||||
vec3_t clipmins, clipmaxs; // size of the moving object
|
||||
vec3_t clipmins2, clipmaxs2; // size when clipping against monsters
|
||||
vec3_t clipstart, clipend; // start and end origin of move
|
||||
trace_t cliptrace; // trace results
|
||||
matrix4x4 matrix, imatrix; // matrices to transform into/out of other entity's space
|
||||
cmodel_t *model; // model of other entity
|
||||
int numtouchedicts = 0; // list of entities to test for collisions
|
||||
edict_t *touchedicts[MAX_EDICTS];
|
||||
|
||||
VectorCopy( start, clipstart );
|
||||
VectorCopy( end, clipend );
|
||||
VectorCopy( mins, clipmins );
|
||||
VectorCopy( maxs, clipmaxs );
|
||||
VectorCopy( mins, clipmins2 );
|
||||
VectorCopy( maxs, clipmaxs2 );
|
||||
|
||||
// clip to world
|
||||
pe->ClipToWorld( &cliptrace, cl.worldmodel, clipstart, clipmins, clipmaxs, clipend, contentsmask );
|
||||
cliptrace.startstuck = cliptrace.startsolid;
|
||||
if( cliptrace.startsolid || cliptrace.fraction < 1 ) cliptrace.ent = prog ? prog->edicts : NULL;
|
||||
if( type == MOVE_WORLDONLY ) return cliptrace;
|
||||
|
||||
if( type == MOVE_MISSILE )
|
||||
{
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
clipmins2[i] -= 15;
|
||||
clipmaxs2[i] += 15;
|
||||
}
|
||||
}
|
||||
|
||||
// get adjusted box for bmodel collisions if the world is q1bsp or hlbsp
|
||||
VectorCopy( clipmins, hullmins );
|
||||
VectorCopy( clipmaxs, hullmaxs );
|
||||
|
||||
// create the bounding box of the entire move
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
clipboxmins[i] = min(clipstart[i], cliptrace.endpos[i]) + min(hullmins[i], clipmins2[i]) - 1;
|
||||
clipboxmaxs[i] = max(clipstart[i], cliptrace.endpos[i]) + max(hullmaxs[i], clipmaxs2[i]) + 1;
|
||||
}
|
||||
|
||||
// if the passedict is world, make it NULL (to avoid two checks each time)
|
||||
// this checks prog because this function is often called without a CSQC
|
||||
// VM context
|
||||
if( prog == NULL || passedict == prog->edicts ) passedict = NULL;
|
||||
// precalculate prog value for passedict for comparisons
|
||||
passedictprog = prog != NULL ? PRVM_EDICT_TO_PROG(passedict) : 0;
|
||||
// figure out whether this is a point trace for comparisons
|
||||
pointtrace = VectorCompare( clipmins, clipmaxs );
|
||||
// precalculate passedict's owner edict pointer for comparisons
|
||||
traceowner = passedict ? PRVM_PROG_TO_EDICT( passedict->progs.cl->owner ) : NULL;
|
||||
|
||||
// clip to entities
|
||||
// because this uses World_EntitiestoBox, we know all entity boxes overlap
|
||||
// the clip region, so we can skip culling checks in the loop below
|
||||
// note: if prog is NULL then there won't be any linked entities
|
||||
numtouchedicts = 0;//CL_AreaEdicts( clipboxmins, clipboxmaxs, touchedicts, host.max_edicts );
|
||||
if( numtouchedicts > host.max_edicts )
|
||||
{
|
||||
// this never happens
|
||||
MsgDev( D_WARN, "CL_AreaEdicts returned %i edicts, max was %i\n", numtouchedicts, host.max_edicts );
|
||||
numtouchedicts = host.max_edicts;
|
||||
}
|
||||
for( i = 0; i < numtouchedicts; i++ )
|
||||
{
|
||||
touch = touchedicts[i];
|
||||
|
||||
if( touch->progs.cl->solid < SOLID_BBOX ) continue;
|
||||
if( type == MOVE_NOMONSTERS && touch->progs.cl->solid != SOLID_BSP )
|
||||
continue;
|
||||
|
||||
if( passedict )
|
||||
{
|
||||
// don't clip against self
|
||||
if( passedict == touch ) continue;
|
||||
// don't clip owned entities against owner
|
||||
if( traceowner == touch ) continue;
|
||||
// don't clip owner against owned entities
|
||||
if( passedictprog == touch->progs.cl->owner ) continue;
|
||||
// don't clip points against points (they can't collide)
|
||||
if( pointtrace && VectorCompare( touch->progs.cl->mins, touch->progs.cl->maxs) && (type != MOVE_MISSILE || !((int)touch->progs.cl->flags & FL_MONSTER)))
|
||||
continue;
|
||||
}
|
||||
|
||||
bodycontents = CONTENTS_BODY;
|
||||
|
||||
// might interact, so do an exact clip
|
||||
model = NULL;
|
||||
if((int)touch->progs.cl->solid == SOLID_BSP || type == MOVE_HITMODEL )
|
||||
{
|
||||
uint modelindex = (uint)touch->progs.cl->modelindex;
|
||||
// if the modelindex is 0, it shouldn't be SOLID_BSP!
|
||||
if( modelindex > 0 && modelindex < MAX_MODELS )
|
||||
model = cl.models[(int)touch->progs.cl->modelindex];
|
||||
}
|
||||
if( model ) Matrix4x4_CreateFromEntity( matrix, touch->progs.cl->origin[0], touch->progs.cl->origin[1], touch->progs.cl->origin[2], touch->progs.cl->angles[0], touch->progs.cl->angles[1], touch->progs.cl->angles[2], 1 );
|
||||
else Matrix4x4_CreateTranslate( matrix, touch->progs.cl->origin[0], touch->progs.cl->origin[1], touch->progs.cl->origin[2] );
|
||||
Matrix4x4_Invert_Simple( imatrix, matrix );
|
||||
if((int)touch->progs.cl->flags & FL_MONSTER)
|
||||
pe->ClipToGenericEntity(&trace, model, touch->progs.cl->mins, touch->progs.cl->maxs, bodycontents, matrix, imatrix, clipstart, clipmins2, clipmaxs2, clipend, contentsmask );
|
||||
else pe->ClipToGenericEntity(&trace, model, touch->progs.cl->mins, touch->progs.cl->maxs, bodycontents, matrix, imatrix, clipstart, clipmins, clipmaxs, clipend, contentsmask );
|
||||
pe->CombineTraces(&cliptrace, &trace, touch, touch->progs.cl->solid == SOLID_BSP );
|
||||
}
|
||||
return cliptrace;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
|
@ -69,57 +191,36 @@ CL_ClipMoveToEntities
|
|||
*/
|
||||
void CL_ClipMoveToEntities ( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, trace_t *tr )
|
||||
{
|
||||
int i, x, zd, zu;
|
||||
trace_t trace;
|
||||
float *angles;
|
||||
entity_state_t *ent;
|
||||
int num;
|
||||
cmodel_t *cmodel;
|
||||
vec3_t bmins, bmaxs;
|
||||
/*
|
||||
for( i = 0; i < cl.frame.num_entities; i++ )
|
||||
{
|
||||
num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
|
||||
ent = &cl_parse_entities[num];
|
||||
|
||||
for( i = 0; i < cl.frame.num_entities; i++ )
|
||||
{
|
||||
num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
|
||||
ent = &cl_parse_entities[num];
|
||||
if(!ent->solid) continue;
|
||||
if(ent->number == cl.playernum + 1) continue;
|
||||
|
||||
if(!ent->solid) continue;
|
||||
if(ent->number == cl.playernum + 1) continue;
|
||||
|
||||
if( ent->solid == SOLID_BMODEL )
|
||||
{
|
||||
// special value for bmodel
|
||||
cmodel = cl.model_clip[ent->modelindex];
|
||||
if(!cmodel) continue;
|
||||
angles = ent->angles;
|
||||
}
|
||||
else
|
||||
{ // encoded bbox
|
||||
x = (ent->solid & 255);
|
||||
zd = ((ent->solid>>8) & 255);
|
||||
zu = ((ent->solid>>16) & 255) - 32;
|
||||
|
||||
bmins[0] = bmins[1] = -x;
|
||||
bmaxs[0] = bmaxs[1] = x;
|
||||
bmins[2] = -zd;
|
||||
bmaxs[2] = zu;
|
||||
angles = ent->angles;
|
||||
}
|
||||
if( tr->allsolid ) return;
|
||||
|
||||
trace = pe->TransformedBoxTrace( start, end, mins, maxs, cmodel, MASK_PLAYERSOLID, ent->origin, angles, false );
|
||||
|
||||
if( trace.allsolid || trace.startsolid || trace.fraction < tr->fraction )
|
||||
{
|
||||
trace.ent = (edict_t *)ent;
|
||||
if (tr->startsolid)
|
||||
{
|
||||
*tr = trace;
|
||||
tr->startsolid = true;
|
||||
}
|
||||
else *tr = trace;
|
||||
}
|
||||
else if (trace.startsolid) tr->startsolid = true;
|
||||
if( ent->solid == SOLID_BMODEL )
|
||||
{
|
||||
// special value for bmodel
|
||||
cmodel = cl.model_clip[ent->modelindex];
|
||||
if(!cmodel) continue;
|
||||
angles = ent->angles;
|
||||
}
|
||||
else
|
||||
{ // encoded bbox
|
||||
x = (ent->solid & 255);
|
||||
zd = ((ent->solid>>8) & 255);
|
||||
zu = ((ent->solid>>16) & 255) - 32;
|
||||
|
||||
bmins[0] = bmins[1] = -x;
|
||||
bmaxs[0] = bmaxs[1] = x;
|
||||
bmins[2] = -zd;
|
||||
bmaxs[2] = zu;
|
||||
angles = ent->angles;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -130,38 +231,15 @@ CL_PMTrace
|
|||
*/
|
||||
void CL_PMTrace( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, trace_t *tr )
|
||||
{
|
||||
// check against world
|
||||
pe->BoxTrace( start, end, mins, maxs, NULL, tr, MASK_PLAYERSOLID );
|
||||
if( tr->fraction < 1.0 ) tr->ent = (edict_t *)1; //FIXME: get client entity = world
|
||||
|
||||
// check all other solid models
|
||||
CL_ClipMoveToEntities( start, mins, maxs, end, tr );
|
||||
*tr = CL_Trace( start, mins, maxs, end, MOVE_NORMAL, NULL, MASK_PLAYERSOLID );
|
||||
}
|
||||
|
||||
int CL_PMpointcontents( vec3_t point )
|
||||
{
|
||||
int i;
|
||||
entity_state_t *ent;
|
||||
int num;
|
||||
cmodel_t *cmodel;
|
||||
int contents;
|
||||
|
||||
contents = pe->PointContents( point, NULL );
|
||||
|
||||
for( i = 0; i < cl.frame.num_entities; i++ )
|
||||
{
|
||||
num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
|
||||
ent = &cl_parse_entities[num];
|
||||
|
||||
if (ent->solid != SOLID_BMODEL) // special value for bmodel
|
||||
continue;
|
||||
|
||||
cmodel = cl.model_clip[ent->modelindex];
|
||||
if (!cmodel) continue;
|
||||
|
||||
contents |= pe->TransformedPointContents( point, cmodel, ent->origin, ent->angles );
|
||||
}
|
||||
return contents;
|
||||
// get world supercontents at this point
|
||||
if( cl.worldmodel && cl.worldmodel->PointContents )
|
||||
return cl.worldmodel->PointContents( point, cl.worldmodel );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ void CL_DrawHUD( void )
|
|||
CL_VM_Begin();
|
||||
|
||||
// setup pparms
|
||||
prog->globals.cl->health = cl.frame.ps.stats[STAT_HEALTH];
|
||||
prog->globals.cl->health = cl.frame.ps.health;
|
||||
prog->globals.cl->maxclients = com.atoi(cl.configstrings[CS_MAXCLIENTS]);
|
||||
prog->globals.cl->realtime = cls.realtime * 0.001f;
|
||||
prog->globals.cl->paused = cl_paused->integer;
|
||||
|
@ -70,7 +70,7 @@ bool CL_ParseUserMessage( int svc_number )
|
|||
bool msg_parsed = false;
|
||||
|
||||
// setup pparms
|
||||
prog->globals.cl->health = cl.frame.ps.stats[STAT_HEALTH];
|
||||
prog->globals.cl->health = cl.frame.ps.health;
|
||||
prog->globals.cl->maxclients = com.atoi(cl.configstrings[CS_MAXCLIENTS]);
|
||||
prog->globals.cl->realtime = cls.realtime * 0.001f;
|
||||
prog->globals.cl->paused = cl_paused->integer;
|
||||
|
|
|
@ -312,8 +312,7 @@ void CL_PrepRefresh( void )
|
|||
Sys_SendKeyEvents(); // pump message loop
|
||||
|
||||
cl.model_draw[i] = re->RegisterModel( name );
|
||||
if (name[0] == '*') cl.model_clip[i] = pe->RegisterModel( name );
|
||||
else cl.model_clip[i] = NULL;//get studio models here?
|
||||
cl.models[i] = pe->RegisterModel( name );
|
||||
Cvar_SetValue("scr_loading", scr_loading->value + 50.0f/mdlcount );
|
||||
SCR_UpdateScreen();
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ typedef struct frame_s
|
|||
byte areabits[MAX_MAP_AREAS/8]; // portalarea visibility bits
|
||||
int num_entities;
|
||||
int parse_entities; // non-masked index into cl_parse_entities array
|
||||
player_state_t ps;
|
||||
entity_state_t ps;
|
||||
} frame_t;
|
||||
|
||||
// console stuff
|
||||
|
@ -140,7 +140,8 @@ typedef struct
|
|||
// locally derived information from server state
|
||||
//
|
||||
model_t *model_draw[MAX_MODELS];
|
||||
cmodel_t *model_clip[MAX_MODELS];
|
||||
cmodel_t *models[MAX_MODELS];
|
||||
cmodel_t *worldmodel;
|
||||
|
||||
sound_t sound_precache[MAX_SOUNDS];
|
||||
image_t *image_precache[MAX_IMAGES];
|
||||
|
|
|
@ -83,6 +83,18 @@ void VM_ValidateString( const char *s )
|
|||
if( s[0] <= ' ' ) PRVM_ERROR( "%s: bad string\n", PRVM_NAME );
|
||||
}
|
||||
|
||||
void VM_SetTraceGlobals( const trace_t *trace )
|
||||
{
|
||||
prog->globals.sv->trace_allsolid = trace->allsolid;
|
||||
prog->globals.sv->trace_startsolid = trace->startsolid;
|
||||
prog->globals.sv->trace_fraction = trace->fraction;
|
||||
prog->globals.sv->trace_contents = trace->contents;
|
||||
VectorCopy (trace->endpos, prog->globals.sv->trace_endpos);
|
||||
VectorCopy (trace->plane.normal, prog->globals.sv->trace_plane_normal);
|
||||
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 ); // world
|
||||
}
|
||||
|
||||
/*
|
||||
=========
|
||||
|
|
|
@ -193,7 +193,7 @@ typedef struct host_parm_s
|
|||
|
||||
extern host_parm_t host;
|
||||
long Host_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam );
|
||||
void Host_Init ( uint funcname, int argc, char **argv );
|
||||
void Host_Init ( int argc, char **argv );
|
||||
void Host_Main ( void );
|
||||
void Host_Free ( void );
|
||||
void Host_SetServerState( int state );
|
||||
|
@ -220,6 +220,16 @@ CLIENT / SERVER SYSTEMS
|
|||
|
||||
==============================================================
|
||||
*/
|
||||
#define FL_CLIENT (1<<0) // this is client
|
||||
#define FL_MONSTER (1<<1) // this is npc
|
||||
#define FL_DEADMONSTER (1<<2) // dead npc or dead player
|
||||
#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 conection
|
||||
#define FL_FLOAT (1<<7) // this entity can be floating. FIXME: remove this ?
|
||||
#define FL_TRACKTRAIN (1<<8) // old stuff...
|
||||
|
||||
void CL_Init( void );
|
||||
void CL_Shutdown( void );
|
||||
void CL_Frame( dword time );
|
||||
|
@ -261,6 +271,8 @@ _inline edict_t *_PRVM_EDICT_NUM( int n, const char * file, const int line )
|
|||
#define PRVM_PUSH_GLOBALS prog->pev_save = prog->globals.sv->pev, prog->other_save = prog->globals.sv->other
|
||||
#define PRVM_POP_GLOBALS prog->globals.sv->pev = prog->pev_save, prog->globals.sv->other = prog->other_save
|
||||
|
||||
#define PRVM_E_FLOAT(e,o) (((float*)e->progs.vp)[o])
|
||||
#define PRVM_E_INT(e,o) (((int*)e->progs.vp)[o])
|
||||
#define PRVM_G_FLOAT(o) (prog->globals.gp[o])
|
||||
#define PRVM_G_INT(o) (*(int *)&prog->globals.gp[o])
|
||||
#define PRVM_G_EDICT(o) (PRVM_PROG_TO_EDICT(*(int *)&prog->globals.gp[o]))
|
||||
|
@ -274,6 +286,7 @@ _inline edict_t *_PRVM_EDICT_NUM( int n, const char * file, const int line )
|
|||
// helper common functions
|
||||
const char *VM_VarArgs( int start_arg );
|
||||
bool VM_ValidateArgs( const char *builtin, int num_argc );
|
||||
void VM_SetTraceGlobals( const trace_t *trace );
|
||||
void VM_ValidateString( const char *s );
|
||||
void VM_Cmd_Init( void );
|
||||
void VM_Cmd_Reset( void );
|
||||
|
@ -392,6 +405,15 @@ MISC COMMON FUNCTIONS
|
|||
#define MAX_INFO_VALUE 64
|
||||
#define MAX_INFO_STRING 512
|
||||
|
||||
enum e_trace
|
||||
{
|
||||
MOVE_NORMAL = 0,
|
||||
MOVE_NOMONSTERS,
|
||||
MOVE_MISSILE,
|
||||
MOVE_WORLDONLY,
|
||||
MOVE_HITMODEL,
|
||||
};
|
||||
|
||||
// client printf level
|
||||
enum e_clprint
|
||||
{
|
||||
|
|
|
@ -494,7 +494,7 @@ void _MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t
|
|||
{
|
||||
// NOTE: entity must have changes from one at first of 32 fields
|
||||
// otherwise it will ignore updates
|
||||
if( flags == 0 && force == 0 )
|
||||
if( flags == 0 && force == 0 && i < 32 )
|
||||
{
|
||||
msg->cursize -= sizeof(word); // kill header
|
||||
return;
|
||||
|
@ -559,7 +559,7 @@ void MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state_t *
|
|||
/*
|
||||
============================================================================
|
||||
|
||||
player_state_t communication
|
||||
player state communication
|
||||
|
||||
============================================================================
|
||||
*/
|
||||
|
@ -569,10 +569,10 @@ MSG_WriteDeltaPlayerstate
|
|||
|
||||
=============
|
||||
*/
|
||||
void MSG_WriteDeltaPlayerstate( player_state_t *from, player_state_t *to, sizebuf_t *msg )
|
||||
void MSG_WriteDeltaPlayerstate( entity_state_t *from, entity_state_t *to, sizebuf_t *msg )
|
||||
{
|
||||
player_state_t dummy;
|
||||
player_state_t *ops, *ps = to;
|
||||
entity_state_t dummy;
|
||||
entity_state_t *ops, *ps = to;
|
||||
net_field_t *field, *field2;
|
||||
int *fromF, *toF;
|
||||
int i, j, k;
|
||||
|
@ -588,12 +588,12 @@ void MSG_WriteDeltaPlayerstate( player_state_t *from, player_state_t *to, sizebu
|
|||
|
||||
MSG_WriteByte( msg, svc_playerinfo );
|
||||
|
||||
for( i = j = 0, field = field2 = ps_fields; field->name; i++, j++, field++ )
|
||||
for( i = j = 0, field = field2 = ent_fields; field->name; i++, j++, field++ )
|
||||
{
|
||||
fromF = (int *)((byte *)ops + field->offset );
|
||||
toF = (int *)((byte *)ps + field->offset );
|
||||
if(*fromF != *toF || field->force) flags |= 1<<j;
|
||||
if( j > 31 || !ps_fields[i+1].name) // dump packet
|
||||
if( j > 31 || !ent_fields[i+1].name) // dump packet
|
||||
{
|
||||
MSG_WriteLong( msg, flags ); // send flags who indicates changes
|
||||
for( k = 0; field2->name; k++, field2++ )
|
||||
|
@ -605,15 +605,6 @@ void MSG_WriteDeltaPlayerstate( player_state_t *from, player_state_t *to, sizebu
|
|||
j = flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// send stats
|
||||
for( i = 0, flags = 0; i < MAX_STATS; i++ )
|
||||
if( ps->stats[i] != ops->stats[i] )
|
||||
flags |= 1<<i;
|
||||
|
||||
MSG_WriteLong( msg, flags );
|
||||
for( i = 0; i < MAX_STATS; i++ )
|
||||
if(flags & (1<<i)) MSG_WriteShort( msg, ps->stats[i]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -622,11 +613,11 @@ void MSG_WriteDeltaPlayerstate( player_state_t *from, player_state_t *to, sizebu
|
|||
MSG_ReadDeltaPlayerstate
|
||||
===================
|
||||
*/
|
||||
void MSG_ReadDeltaPlayerstate( sizebuf_t *msg, player_state_t *from, player_state_t *to )
|
||||
void MSG_ReadDeltaPlayerstate( sizebuf_t *msg, entity_state_t *from, entity_state_t *to )
|
||||
{
|
||||
net_field_t *field;
|
||||
int *fromF, *toF;
|
||||
player_state_t dummy;
|
||||
entity_state_t dummy;
|
||||
uint i, flags;
|
||||
|
||||
// clear to old value before delta parsing
|
||||
|
@ -637,7 +628,7 @@ void MSG_ReadDeltaPlayerstate( sizebuf_t *msg, player_state_t *from, player_stat
|
|||
}
|
||||
*to = *from;
|
||||
|
||||
for( i = 0, field = ps_fields; field->name; i++, field++ )
|
||||
for( i = 0, field = ent_fields; field->name; i++, field++ )
|
||||
{
|
||||
// get flags of next packet if LONG out of range
|
||||
if((i & 31) == 0) flags = MSG_ReadLong( msg );
|
||||
|
@ -647,11 +638,4 @@ void MSG_ReadDeltaPlayerstate( sizebuf_t *msg, player_state_t *from, player_stat
|
|||
if(flags & (1<<i)) *toF = MSG_ReadBits( msg, field->bits );
|
||||
else *toF = *fromF; // no change
|
||||
}
|
||||
|
||||
// parse stats
|
||||
for( i = 0; i < MAX_STATS; i++ )
|
||||
{
|
||||
if((i & 31) == 0) flags = MSG_ReadLong( msg );
|
||||
if(flags & (1<<i)) to->stats[i] = MSG_ReadShort( msg );
|
||||
}
|
||||
}
|
|
@ -121,7 +121,6 @@ static const net_desc_t NWDesc[] =
|
|||
#define MAX_GENERAL (MAX_CLIENTS * 2) // general config strings
|
||||
|
||||
#define ES_FIELD(x) #x,(int)&((entity_state_t*)0)->x
|
||||
#define PS_FIELD(x) #x,(int)&((player_state_t*)0)->x
|
||||
#define CM_FIELD(x) #x,(int)&((usercmd_t*)0)->x
|
||||
|
||||
// config strings are a general means of communication from
|
||||
|
@ -156,84 +155,107 @@ static const net_desc_t NWDesc[] =
|
|||
|
||||
static net_field_t ent_fields[] =
|
||||
{
|
||||
{ ES_FIELD(origin[0]), NET_FLOAT, false },
|
||||
{ ES_FIELD(origin[1]), NET_FLOAT, false },
|
||||
{ ES_FIELD(origin[2]), NET_FLOAT, false },
|
||||
{ ES_FIELD(angles[0]), NET_FLOAT, false },
|
||||
{ ES_FIELD(angles[1]), NET_FLOAT, false },
|
||||
{ ES_FIELD(angles[2]), NET_FLOAT, false },
|
||||
{ ES_FIELD(old_origin[0]), NET_FLOAT, true },
|
||||
{ ES_FIELD(old_origin[1]), NET_FLOAT, true },
|
||||
{ ES_FIELD(old_origin[2]), NET_FLOAT, true },
|
||||
{ ES_FIELD(modelindex), NET_WORD, false }, // 4096 models
|
||||
{ ES_FIELD(soundindex), NET_WORD, false }, // 512 sounds ( OpenAL software limit is 255 )
|
||||
{ ES_FIELD(weaponmodel), NET_WORD, false }, // 4096 models
|
||||
{ ES_FIELD(skin), NET_BYTE, false }, // 255 skins
|
||||
{ ES_FIELD(frame), NET_FLOAT, false }, // interpolate value
|
||||
{ ES_FIELD(body), NET_BYTE, false }, // 255 bodies
|
||||
{ ES_FIELD(sequence), NET_WORD, false }, // 1024 sequences
|
||||
{ ES_FIELD(effects), NET_LONG, false }, // effect flags
|
||||
{ ES_FIELD(renderfx), NET_LONG, false }, // renderfx flags
|
||||
{ ES_FIELD(solid), NET_LONG, false }, // encoded mins/maxs
|
||||
{ ES_FIELD(alpha), NET_FLOAT, false }, // alpha value (FIXME: send a byte ? )
|
||||
{ ES_FIELD(animtime), NET_FLOAT, false }, // auto-animating time
|
||||
{ NULL }, // terminator
|
||||
};
|
||||
|
||||
static net_field_t ps_fields[] =
|
||||
{
|
||||
{ PS_FIELD(pm_type), NET_BYTE, false }, // 16 player movetypes allowed
|
||||
{ PS_FIELD(pm_flags), NET_WORD, true }, // 16 movetype flags allowed
|
||||
{ PS_FIELD(pm_time), NET_BYTE, true }, // each unit 8 msec
|
||||
#ifdef USE_COORD_FRAC
|
||||
{ PS_FIELD(origin[0]), NET_COORD, false },
|
||||
{ PS_FIELD(origin[1]), NET_COORD, false },
|
||||
{ PS_FIELD(origin[2]), NET_COORD, false },
|
||||
{ PS_FIELD(velocity[0]), NET_COORD, false },
|
||||
{ PS_FIELD(velocity[1]), NET_COORD, false },
|
||||
{ PS_FIELD(velocity[2]), NET_COORD, false },
|
||||
#else
|
||||
{ PS_FIELD(origin[0]), NET_FLOAT, false },
|
||||
{ PS_FIELD(origin[1]), NET_FLOAT, false },
|
||||
{ PS_FIELD(origin[2]), NET_FLOAT, false },
|
||||
{ PS_FIELD(velocity[0]), NET_FLOAT, false },
|
||||
{ PS_FIELD(velocity[1]), NET_FLOAT, false },
|
||||
{ PS_FIELD(velocity[2]), NET_FLOAT, false },
|
||||
#endif
|
||||
{ PS_FIELD(delta_angles[0]), NET_FLOAT, false },
|
||||
{ PS_FIELD(delta_angles[1]), NET_FLOAT, false },
|
||||
{ PS_FIELD(delta_angles[2]), NET_FLOAT, false },
|
||||
{ PS_FIELD(gravity), NET_SHORT, false }, // may be 12 bits ?
|
||||
{ PS_FIELD(effects), NET_LONG, false }, // copied to entity_state_t->effects
|
||||
{ PS_FIELD(viewangles[0]), NET_FLOAT, false }, // for fixed views
|
||||
{ PS_FIELD(viewangles[1]), NET_FLOAT, false },
|
||||
{ PS_FIELD(viewangles[2]), NET_FLOAT, false },
|
||||
{ PS_FIELD(viewoffset[0]), NET_SCALE, false }, // get rid of this
|
||||
{ PS_FIELD(viewoffset[1]), NET_SCALE, false },
|
||||
{ PS_FIELD(viewoffset[2]), NET_SCALE, false },
|
||||
{ PS_FIELD(kick_angles[0]), NET_SCALE, false },
|
||||
{ PS_FIELD(kick_angles[1]), NET_SCALE, false },
|
||||
{ PS_FIELD(kick_angles[2]), NET_SCALE, false },
|
||||
{ PS_FIELD(blend[0]), NET_COLOR, false }, // FIXME: calc on client, don't send over the net
|
||||
{ PS_FIELD(blend[1]), NET_COLOR, false },
|
||||
{ PS_FIELD(blend[2]), NET_COLOR, false },
|
||||
{ PS_FIELD(blend[3]), NET_COLOR, false },
|
||||
{ PS_FIELD(fov), NET_FLOAT, false }, // FIXME: send as byte * 4 ?
|
||||
{ PS_FIELD(vmodel.index), NET_WORD, false }, // 4096 models
|
||||
{ PS_FIELD(vmodel.angles[0]), NET_SCALE, false }, // can be some different with viewangles
|
||||
{ PS_FIELD(vmodel.angles[1]), NET_SCALE, false },
|
||||
{ PS_FIELD(vmodel.angles[2]), NET_SCALE, false },
|
||||
{ PS_FIELD(vmodel.offset[0]), NET_SCALE, false }, // center offset
|
||||
{ PS_FIELD(vmodel.offset[1]), NET_SCALE, false },
|
||||
{ PS_FIELD(vmodel.offset[2]), NET_SCALE, false },
|
||||
{ PS_FIELD(vmodel.sequence), NET_WORD, false }, // 1024 sequences
|
||||
{ PS_FIELD(vmodel.frame), NET_FLOAT, false }, // interpolate value
|
||||
{ PS_FIELD(vmodel.body), NET_BYTE, false }, // 255 bodies
|
||||
{ PS_FIELD(vmodel.skin), NET_BYTE, false }, // 255 skins
|
||||
{ PS_FIELD(pmodel.index), NET_WORD, false }, // 4096 models
|
||||
{ PS_FIELD(pmodel.sequence), NET_WORD, false }, // 1024 sequences
|
||||
{ PS_FIELD(vmodel.frame), NET_FLOAT, false }, // interpolate value
|
||||
{ NULL }, // terminator
|
||||
{ ES_FIELD(ed_type), NET_BYTE, true },
|
||||
{ ES_FIELD(soundindex), NET_WORD, false }, // 512 sounds ( OpenAL software limit is 255 )
|
||||
{ ES_FIELD(origin[0]), NET_FLOAT, false },
|
||||
{ ES_FIELD(origin[1]), NET_FLOAT, false },
|
||||
{ ES_FIELD(origin[2]), NET_FLOAT, false },
|
||||
{ ES_FIELD(angles[0]), NET_FLOAT, false },
|
||||
{ ES_FIELD(angles[1]), NET_FLOAT, false },
|
||||
{ ES_FIELD(angles[2]), NET_FLOAT, false },
|
||||
{ ES_FIELD(velocity[0]), NET_FLOAT, false },
|
||||
{ ES_FIELD(velocity[1]), NET_FLOAT, false },
|
||||
{ ES_FIELD(velocity[2]), NET_FLOAT, false },
|
||||
{ ES_FIELD(old_origin[0]), NET_FLOAT, true }, // send always
|
||||
{ ES_FIELD(old_origin[1]), NET_FLOAT, true },
|
||||
{ ES_FIELD(old_origin[2]), NET_FLOAT, true },
|
||||
{ ES_FIELD(old_velocity[0]), NET_FLOAT, true }, // client velocity
|
||||
{ ES_FIELD(old_velocity[1]), NET_FLOAT, true },
|
||||
{ ES_FIELD(old_velocity[2]), NET_FLOAT, true },
|
||||
{ ES_FIELD(model.index), NET_WORD, false }, // 4096 models
|
||||
{ ES_FIELD(model.colormap), NET_WORD, false }, // encoded as two shorts for top and bottom color
|
||||
{ ES_FIELD(model.scale), NET_COLOR, false }, // 0-255 values
|
||||
{ ES_FIELD(model.frame), NET_FLOAT, false }, // interpolate value
|
||||
{ ES_FIELD(model.animtime), NET_FLOAT, false }, // auto-animating time
|
||||
{ ES_FIELD(model.framerate), NET_FLOAT, false }, // custom framerate
|
||||
{ ES_FIELD(model.sequence), NET_WORD, false }, // 1024 sequences
|
||||
{ ES_FIELD(model.gaitsequence), NET_WORD, false }, // 1024 gaitsequences
|
||||
{ ES_FIELD(model.skin), NET_BYTE, false }, // 255 skins
|
||||
{ ES_FIELD(model.body), NET_BYTE, false }, // 255 bodies
|
||||
{ ES_FIELD(model.blending[0]), NET_COLOR, false }, // animation blending
|
||||
{ ES_FIELD(model.blending[1]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.blending[2]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.blending[3]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.blending[4]), NET_COLOR, false }, // send flags (first 4 bytes)
|
||||
{ ES_FIELD(model.blending[5]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.blending[6]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.blending[7]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.blending[8]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[0]), NET_COLOR, false }, // bone controllers #
|
||||
{ ES_FIELD(model.controller[1]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[2]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[3]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[4]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[5]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[6]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[7]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[8]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[9]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[10]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[11]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[12]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[13]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[14]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[15]), NET_COLOR, false },
|
||||
{ ES_FIELD(model.controller[16]), NET_COLOR, false }, // FIXME: sending as array
|
||||
{ ES_FIELD(solidtype), NET_BYTE, false },
|
||||
{ ES_FIELD(movetype), NET_BYTE, false }, // send flags (second 4 bytes)
|
||||
{ ES_FIELD(gravity), NET_SHORT, false }, // gravity multiplier
|
||||
{ ES_FIELD(aiment), NET_WORD, false }, // entity index
|
||||
{ ES_FIELD(solid), NET_LONG, false }, // encoded mins/maxs
|
||||
{ ES_FIELD(mins[0]), NET_FLOAT, false },
|
||||
{ ES_FIELD(mins[1]), NET_FLOAT, false },
|
||||
{ ES_FIELD(mins[2]), NET_FLOAT, false },
|
||||
{ ES_FIELD(maxs[0]), NET_FLOAT, false },
|
||||
{ ES_FIELD(maxs[1]), NET_FLOAT, false },
|
||||
{ ES_FIELD(maxs[2]), NET_FLOAT, false },
|
||||
{ ES_FIELD(effects), NET_LONG, false }, // effect flags
|
||||
{ ES_FIELD(renderfx), NET_LONG, false }, // renderfx flags
|
||||
{ ES_FIELD(renderamt), NET_COLOR, false }, // alpha amount
|
||||
{ ES_FIELD(rendercolor[0]), NET_COLOR, false }, // animation blending
|
||||
{ ES_FIELD(rendercolor[1]), NET_COLOR, false },
|
||||
{ ES_FIELD(rendercolor[2]), NET_COLOR, false },
|
||||
{ ES_FIELD(rendermode), NET_BYTE, false }, // render mode (legacy stuff)
|
||||
{ ES_FIELD(pm_type), NET_BYTE, false }, // 16 player movetypes allowed
|
||||
{ ES_FIELD(pm_flags), NET_WORD, true }, // 16 movetype flags allowed
|
||||
{ ES_FIELD(pm_time), NET_BYTE, true }, // each unit 8 msec
|
||||
{ ES_FIELD(delta_angles[0]), NET_FLOAT, false },
|
||||
{ ES_FIELD(delta_angles[1]), NET_FLOAT, false },
|
||||
{ ES_FIELD(delta_angles[2]), NET_FLOAT, false },
|
||||
{ ES_FIELD(punch_angles[0]), NET_SCALE, false },
|
||||
{ ES_FIELD(punch_angles[1]), NET_SCALE, false },
|
||||
{ ES_FIELD(punch_angles[2]), NET_SCALE, false },
|
||||
{ ES_FIELD(viewangles[0]), NET_FLOAT, false }, // for fixed views
|
||||
{ ES_FIELD(viewangles[1]), NET_FLOAT, false },
|
||||
{ ES_FIELD(viewangles[2]), NET_FLOAT, false },
|
||||
// FIXME: replace with viewoffset
|
||||
//{ ES_FIELD(viewheight), NET_SHORT, false }, // client viewheight
|
||||
{ ES_FIELD(viewoffset[0]), NET_SCALE, false }, // get rid of this
|
||||
{ ES_FIELD(viewoffset[1]), NET_SCALE, false },
|
||||
{ ES_FIELD(viewoffset[2]), NET_SCALE, false },
|
||||
{ ES_FIELD(maxspeed), NET_WORD, false }, // send flags (third 4 bytes )
|
||||
{ ES_FIELD(fov), NET_FLOAT, false }, // client horizontal field of view
|
||||
{ ES_FIELD(vmodel.index), NET_WORD, false }, // 4096 models
|
||||
{ ES_FIELD(vmodel.colormap), NET_LONG, false }, // 4096 models
|
||||
{ ES_FIELD(vmodel.sequence), NET_WORD, false }, // 1024 sequences
|
||||
{ ES_FIELD(vmodel.frame), NET_FLOAT, false }, // interpolate value
|
||||
{ ES_FIELD(vmodel.body), NET_BYTE, false }, // 255 bodies
|
||||
{ ES_FIELD(vmodel.skin), NET_BYTE, false }, // 255 skins
|
||||
{ ES_FIELD(pmodel.index), NET_WORD, false }, // 4096 models
|
||||
{ ES_FIELD(pmodel.colormap), NET_LONG, false }, // 4096 models
|
||||
{ ES_FIELD(pmodel.sequence), NET_WORD, false }, // 1024 sequences
|
||||
{ ES_FIELD(vmodel.frame), NET_FLOAT, false }, // interpolate value
|
||||
{ NULL }, // terminator
|
||||
};
|
||||
|
||||
// probably usercmd_t never reached 32 field integer limit (in theory of course)
|
||||
|
@ -307,8 +329,8 @@ void MSG_ReadPos( sizebuf_t *sb, vec3_t pos );
|
|||
void MSG_ReadData( sizebuf_t *sb, void *buffer, size_t size );
|
||||
void MSG_ReadDeltaUsercmd( sizebuf_t *sb, usercmd_t *from, usercmd_t *cmd );
|
||||
void MSG_ReadDeltaEntity( sizebuf_t *sb, entity_state_t *from, entity_state_t *to, int number );
|
||||
void MSG_WriteDeltaPlayerstate( player_state_t *from, player_state_t *to, sizebuf_t *msg );
|
||||
void MSG_ReadDeltaPlayerstate( sizebuf_t *msg, player_state_t *from, player_state_t *to );
|
||||
void MSG_WriteDeltaPlayerstate( entity_state_t *from, entity_state_t *to, sizebuf_t *msg );
|
||||
void MSG_ReadDeltaPlayerstate( sizebuf_t *msg, entity_state_t *from, entity_state_t *to );
|
||||
|
||||
// huffman compression
|
||||
void Huff_Init( void );
|
||||
|
|
|
@ -226,6 +226,10 @@ SOURCE=.\server\sv_main.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\server\sv_move.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\server\sv_phys.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -238,10 +242,6 @@ SOURCE=.\server\sv_spawn.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\server\sv_studio.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\server\sv_world.c
|
||||
# End Source File
|
||||
# End Group
|
||||
|
|
|
@ -156,7 +156,7 @@ void Host_InitVprogs( int argc, char **argv )
|
|||
CreateVprogs = (void *)vprogs_dll.main;
|
||||
vm = CreateVprogs( &newcom, NULL ); // second interface not allowed
|
||||
|
||||
vm->Init( host.type, argc, argv );
|
||||
vm->Init( argc, argv );
|
||||
}
|
||||
|
||||
void Host_FreeVprogs( void )
|
||||
|
@ -700,7 +700,7 @@ static void Host_Crash_f (void)
|
|||
*(int *)0 = 0xffffffff;
|
||||
}
|
||||
|
||||
void Host_InitCommon( uint funcname, int argc, char **argv )
|
||||
void Host_InitCommon( int argc, char **argv )
|
||||
{
|
||||
char dev_level[4];
|
||||
|
||||
|
@ -733,16 +733,16 @@ void Host_FreeCommon( void )
|
|||
Host_Init
|
||||
=================
|
||||
*/
|
||||
void Host_Init (uint funcname, int argc, char **argv)
|
||||
void Host_Init( int argc, char **argv)
|
||||
{
|
||||
char *s;
|
||||
|
||||
host.state = HOST_INIT; // initialzation started
|
||||
host.type = funcname;
|
||||
host.type = g_Instance;
|
||||
|
||||
srand(time(NULL)); // init random generator
|
||||
|
||||
Host_InitCommon( funcname, argc, argv ); // loading common.dll
|
||||
Host_InitCommon( argc, argv ); // loading common.dll
|
||||
Key_Init();
|
||||
|
||||
// get default configuration
|
||||
|
@ -779,7 +779,7 @@ void Host_Init (uint funcname, int argc, char **argv)
|
|||
Host_InitVprogs( argc, argv );
|
||||
|
||||
// per level user limit
|
||||
host.max_edicts = bound( 8, Cvar_VariableValue("prvm_maxedicts"), 65535 );
|
||||
host.max_edicts = bound( 8, Cvar_VariableValue("prvm_maxedicts"), MAX_EDICTS - 1 );
|
||||
|
||||
SV_Init();
|
||||
CL_Init();
|
||||
|
|
|
@ -52,16 +52,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define AI_SPECTATOR (1<<12) // spectator mode for clients
|
||||
#define AI_WATERJUMP (1<<13) // npc or player take out of water
|
||||
|
||||
#define FL_CLIENT (1<<0) // this is client
|
||||
#define FL_MONSTER (1<<1) // this is npc
|
||||
#define FL_DEADMONSTER (1<<2) // dead npc or dead player
|
||||
#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 conection
|
||||
#define FL_FLOAT (1<<7) // this entity can be floating. FIXME: remove this ?
|
||||
#define FL_TRACKTRAIN (1<<8) // old stuff...
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ss_dead, // no map loaded
|
||||
|
@ -91,6 +81,7 @@ typedef struct server_s
|
|||
|
||||
char name[MAX_QPATH]; // map name, or cinematic name
|
||||
cmodel_t *models[MAX_MODELS];
|
||||
cmodel_t *worldmodel;
|
||||
|
||||
char configstrings[MAX_CONFIGSTRINGS][MAX_QPATH];
|
||||
|
||||
|
@ -107,7 +98,7 @@ typedef struct server_s
|
|||
|
||||
typedef struct
|
||||
{
|
||||
player_state_t ps;
|
||||
entity_state_t ps;
|
||||
int areabytes;
|
||||
byte areabits[MAX_MAP_AREAS/8]; // portalarea visibility bits
|
||||
int num_entities;
|
||||
|
@ -121,12 +112,15 @@ typedef struct sv_client_s
|
|||
{
|
||||
cl_state_t state;
|
||||
|
||||
player_state_t ps; // communicated by server to clients
|
||||
entity_state_t ps; // communicated by server to clients
|
||||
char userinfo[MAX_INFO_STRING]; // name, etc
|
||||
|
||||
int lastframe; // for delta compression
|
||||
usercmd_t lastcmd; // for filling in big drops
|
||||
usercmd_t cmd; // current user commands
|
||||
|
||||
vec3_t fix_angles; // q1 legacy
|
||||
bool fixangle;
|
||||
// commands exhaust it, assume time cheating
|
||||
int ping;
|
||||
int rate;
|
||||
|
@ -147,6 +141,7 @@ typedef struct sv_client_s
|
|||
int downloadsize; // total bytes (can't use EOF because of paks)
|
||||
int downloadcount; // bytes sent
|
||||
|
||||
int skipframes; // client synchronyze with phys frame
|
||||
int lastmessage; // sv.framenum when packet was last received
|
||||
int lastconnect;
|
||||
|
||||
|
@ -156,8 +151,6 @@ typedef struct sv_client_s
|
|||
} sv_client_t;
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct worldsector_s
|
||||
{
|
||||
int axis; // -1 = leaf node
|
||||
|
@ -182,13 +175,19 @@ struct sv_edict_s
|
|||
int num_clusters; // if -1, use headnode instead
|
||||
int clusternums[MAX_ENT_CLUSTERS];
|
||||
int areanum, areanum2;
|
||||
bool forceupdate; // physic_push force update
|
||||
bool suspended; // suspended in air toss object
|
||||
|
||||
vec3_t water_origin; // step old origin
|
||||
vec3_t moved_origin; // push old origin
|
||||
vec3_t moved_angles; // push old angles
|
||||
|
||||
int serialnumber; // unical entity #id
|
||||
int solid; // see entity_state_t for details
|
||||
physbody_t *physbody; // ptr to phys body
|
||||
|
||||
// baselines
|
||||
entity_state_t s;
|
||||
entity_state_t s; // this is a player_state too
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -229,6 +228,7 @@ typedef struct
|
|||
int next_client_entities; // next client_entity to use
|
||||
entity_state_t *client_entities; // [num_client_entities]
|
||||
entity_state_t *baselines; // [host.max_edicts]
|
||||
func_t ClientMove; // qc client physic
|
||||
|
||||
int last_heartbeat;
|
||||
|
||||
|
@ -246,6 +246,8 @@ extern cvar_t *sv_paused;
|
|||
extern cvar_t *maxclients;
|
||||
extern cvar_t *sv_noreload; // don't reload level state when reentering
|
||||
extern cvar_t *sv_airaccelerate; // don't reload level state when reentering
|
||||
extern cvar_t *sv_accelerate;
|
||||
extern cvar_t *sv_friction;
|
||||
extern cvar_t *sv_maxvelocity;
|
||||
extern cvar_t *sv_gravity;
|
||||
extern cvar_t *sv_fps; // running server at
|
||||
|
@ -255,6 +257,11 @@ extern cvar_t *allow_download;
|
|||
extern cvar_t *rcon_password;
|
||||
extern cvar_t *sv_fatpvs;
|
||||
extern cvar_t *hostname;
|
||||
extern cvar_t *sv_stepheight;
|
||||
extern cvar_t *sv_playersonly;
|
||||
extern cvar_t *sv_rollangle;
|
||||
extern cvar_t *sv_rollspeed;
|
||||
extern cvar_t *sv_maxspeed;
|
||||
|
||||
extern sv_client_t *sv_client;
|
||||
|
||||
|
@ -292,15 +299,23 @@ void SV_VM_End(void);
|
|||
//
|
||||
// sv_phys.c
|
||||
//
|
||||
void SV_Physics( void );
|
||||
void SV_PlayerMove( sv_edict_t *ed );
|
||||
void SV_PrepWorldFrame (void);
|
||||
void SV_Physics (edict_t *ent);
|
||||
void SV_DropToFloor (edict_t *ent);
|
||||
void SV_CheckGround (edict_t *ent);
|
||||
int SV_ContentsMask( const edict_t *passedict );
|
||||
bool SV_MoveStep (edict_t *ent, vec3_t move, bool relink);
|
||||
void SV_Physics_ClientMove( sv_client_t *cl, usercmd_t *cmd );
|
||||
void SV_CheckVelocity (edict_t *ent);
|
||||
bool SV_CheckBottom (edict_t *ent);
|
||||
|
||||
//
|
||||
// sv_move.c
|
||||
//
|
||||
void SV_Transform( sv_edict_t *ed, matrix4x3 transform );
|
||||
void SV_PlaySound( sv_edict_t *ed, float volume, const char *sample );
|
||||
bool SV_movestep( edict_t *ent, vec3_t move, bool relink, bool noenemy, bool settrace );
|
||||
|
||||
//
|
||||
// sv_send.c
|
||||
//
|
||||
|
@ -318,6 +333,7 @@ char *SV_StatusString( void );
|
|||
void SV_GetChallenge( netadr_t from );
|
||||
void SV_DirectConnect( netadr_t from );
|
||||
void SV_PutClientInServer( edict_t *ent );
|
||||
void SV_ClientThink( sv_client_t *cl, usercmd_t *cmd );
|
||||
void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg );
|
||||
void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg );
|
||||
|
||||
|
@ -350,6 +366,7 @@ void SV_SetModel (edict_t *ent, const char *name);
|
|||
void SV_CreatePhysBody( edict_t *ent );
|
||||
void SV_SetPhysForce( edict_t *ent );
|
||||
void SV_SetMassCentre( edict_t *ent);
|
||||
float SV_AngleMod( float ideal, float current, float speed );
|
||||
|
||||
//
|
||||
// sv_studio.c
|
||||
|
@ -364,18 +381,12 @@ bool SV_CreateMeshBuffer( edict_t *in, cmodel_t *out );
|
|||
//
|
||||
void SV_SpawnEntities( const char *mapname, const char *entities );
|
||||
void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count);
|
||||
void SV_Transform( sv_edict_t *ed, matrix4x3 transform );
|
||||
void SV_PlaySound( sv_edict_t *ed, float volume, const char *sample );
|
||||
void SV_FreeEdict (edict_t *ed);
|
||||
void SV_InitEdict (edict_t *e);
|
||||
edict_t *SV_Spawn (void);
|
||||
void SV_RunFrame (void);
|
||||
void SV_ClientUserinfoChanged (edict_t *ent, char *userinfo);
|
||||
bool SV_ClientConnect (edict_t *ent, char *userinfo);
|
||||
void SV_ClientBegin (edict_t *ent);
|
||||
void ClientThink (edict_t *ent, usercmd_t *ucmd);
|
||||
void SV_ClientDisconnect (edict_t *ent);
|
||||
void SV_ClientCommand (edict_t *ent);
|
||||
void SV_TouchTriggers (edict_t *ent);
|
||||
|
||||
//
|
||||
|
@ -416,14 +427,12 @@ int SV_AreaEdicts( const vec3_t mins, const vec3_t maxs, edict_t **list, int max
|
|||
//
|
||||
// functions that interact with everything apropriate
|
||||
//
|
||||
int SV_PointContents( const vec3_t p, edict_t *passedict );
|
||||
int SV_PointContents( const vec3_t p );
|
||||
// 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( 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);
|
||||
trace_t SV_Trace( const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, edict_t *passedict, int contentmask );
|
||||
trace_t SV_TraceToss( edict_t *tossent, edict_t *ignore );
|
||||
// mins and maxs are relative
|
||||
|
||||
// if the entire move stays in a solid volume, trace.allsolid will be set,
|
||||
|
|
|
@ -12,6 +12,10 @@ typedef struct ucmd_s
|
|||
void (*func)( sv_client_t *cl );
|
||||
} ucmd_t;
|
||||
|
||||
static vec3_t wishdir, forward, right, up;
|
||||
static float wishspeed;
|
||||
static bool onground;
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_GetChallenge
|
||||
|
@ -205,6 +209,31 @@ gotnewcl:
|
|||
svs.last_heartbeat = MAX_HEARTBEAT;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
SV_ClientCconnect
|
||||
|
||||
QC code can rejected a connection for some reasons
|
||||
e.g. ipban
|
||||
=====================
|
||||
*/
|
||||
bool SV_ClientConnect( edict_t *ent, char *userinfo )
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
// make sure we start with known default
|
||||
ent->progs.sv->flags = 0;
|
||||
ent->progs.sv->health = 100;
|
||||
|
||||
MsgDev(D_NOTE, "SV_ClientConnect()\n");
|
||||
prog->globals.sv->time = sv.time;
|
||||
prog->globals.sv->pev = PRVM_EDICT_TO_PROG(ent);
|
||||
PRVM_ExecuteProgram (prog->globals.sv->ClientConnect, "ClientConnect");
|
||||
result = (int)PRVM_G_FLOAT(OFS_RETURN);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
SV_DropClient
|
||||
|
@ -319,7 +348,7 @@ char *SV_StatusString( void )
|
|||
cl = &svs.clients[i];
|
||||
if( cl->state == cs_connected || cl->state == cs_spawned )
|
||||
{
|
||||
com.sprintf( player, "%i %i \"%s\"\n", cl->edict->priv.sv->client->ps.stats[STAT_FRAGS], cl->ping, cl->name );
|
||||
com.sprintf( player, "%i %i \"%s\"\n", (int)cl->edict->progs.sv->frags, cl->ping, cl->name );
|
||||
playerLength = com.strlen(player);
|
||||
if( statusLength + playerLength >= sizeof(status))
|
||||
break; // can't hold any more
|
||||
|
@ -617,7 +646,7 @@ void SV_Baselines_f( sv_client_t *cl )
|
|||
while( start < host.max_edicts )
|
||||
{
|
||||
base = &svs.baselines[start];
|
||||
if( base->modelindex || base->soundindex || base->effects )
|
||||
if( base->model.index || base->soundindex || base->effects )
|
||||
{
|
||||
MSG_WriteByte( &cl->netchan.message, svc_spawnbaseline );
|
||||
MSG_WriteDeltaEntity( &nullstate, base, &cl->netchan.message, true, true );
|
||||
|
@ -648,7 +677,7 @@ void SV_Begin_f( sv_client_t *cl )
|
|||
return;
|
||||
}
|
||||
cl->state = cs_spawned;
|
||||
SV_ClientBegin( cl->edict );
|
||||
SV_PutClientInServer( cl->edict );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -979,6 +1008,267 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
|||
else MsgDev( D_ERROR, "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), s );
|
||||
}
|
||||
|
||||
void SV_ApplyClientMove( sv_client_t *cl, usercmd_t *cmd )
|
||||
{
|
||||
short temp;
|
||||
int i;
|
||||
|
||||
// set the edict fields
|
||||
cl->edict->progs.sv->button0 = cmd->buttons & 1;
|
||||
cl->edict->progs.sv->button2 = (cmd->buttons & 2)>>1;
|
||||
if( cmd->impulse ) cl->edict->progs.sv->impulse = cmd->impulse;
|
||||
// only send the impulse to qc once
|
||||
cmd->impulse = 0;
|
||||
|
||||
// circularly clamp the angles with deltas
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
temp = cmd->angles[i] + cl->ps.delta_angles[i];
|
||||
cl->ps.viewangles[i] = SHORT2ANGLE( temp );
|
||||
}
|
||||
|
||||
// don't let the player look up or down more than 90 degrees
|
||||
if( cl->ps.viewangles[PITCH] > 89 && cl->ps.viewangles[PITCH] < 180 )
|
||||
cl->ps.viewangles[PITCH] = 89;
|
||||
else if( cl->ps.viewangles[PITCH] < 271 && cl->ps.viewangles[PITCH] >= 180 )
|
||||
cl->ps.viewangles[PITCH] = 271;
|
||||
|
||||
VectorCopy( cl->ps.viewangles, cl->edict->progs.sv->v_angle );
|
||||
VectorCopy( cl->ps.viewangles, cl->edict->progs.sv->angles );
|
||||
}
|
||||
|
||||
void SV_DropPunchAngle( sv_client_t *cl )
|
||||
{
|
||||
float len;
|
||||
|
||||
len = VectorNormalizeLength( cl->edict->progs.sv->punchangle );
|
||||
|
||||
len -= 10 * sv.frametime;
|
||||
if( len < 0 ) len = 0;
|
||||
VectorScale( cl->edict->progs.sv->punchangle, len, cl->edict->progs.sv->punchangle );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_UserFriction
|
||||
|
||||
==================
|
||||
*/
|
||||
void SV_UserFriction( sv_client_t *cl )
|
||||
{
|
||||
float speed, newspeed;
|
||||
float control, friction;
|
||||
vec3_t start, stop;
|
||||
trace_t trace;
|
||||
|
||||
speed = sqrt(cl->edict->progs.sv->velocity[0] * cl->edict->progs.sv->velocity[0] + cl->edict->progs.sv->velocity[1] * cl->edict->progs.sv->velocity[1]);
|
||||
if( !speed ) return;
|
||||
|
||||
// if the leading edge is over a dropoff, increase friction
|
||||
start[0] = stop[0] = cl->edict->progs.sv->origin[0] + cl->edict->progs.sv->velocity[0] / speed * 16;
|
||||
start[1] = stop[1] = cl->edict->progs.sv->origin[1] + cl->edict->progs.sv->velocity[1] / speed * 16;
|
||||
start[2] = cl->edict->progs.sv->origin[2] + cl->edict->progs.sv->mins[2];
|
||||
stop[2] = start[2] - 34;
|
||||
|
||||
trace = SV_Trace( start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, cl->edict, SV_ContentsMask( cl->edict ));
|
||||
|
||||
if( trace.fraction == 1.0 ) friction = sv_friction->value * 2;
|
||||
else friction = sv_friction->value;
|
||||
|
||||
// apply friction
|
||||
control = speed < 100 ? 100 : speed;
|
||||
newspeed = speed - sv.frametime * control * friction;
|
||||
|
||||
if( newspeed < 0 ) newspeed = 0;
|
||||
else newspeed /= speed;
|
||||
VectorScale( cl->edict->progs.sv->velocity, newspeed, cl->edict->progs.sv->velocity );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
V_CalcRoll
|
||||
|
||||
Used by view and sv_user
|
||||
===============
|
||||
*/
|
||||
float SV_CalcRoll( vec3_t angles, vec3_t velocity )
|
||||
{
|
||||
vec3_t right;
|
||||
float sign, side, value;
|
||||
|
||||
AngleVectors( angles, NULL, right, NULL );
|
||||
side = DotProduct( velocity, right );
|
||||
sign = side < 0 ? -1 : 1;
|
||||
side = fabs( side );
|
||||
|
||||
value = sv_rollangle->value;
|
||||
|
||||
if( side < sv_rollspeed->value )
|
||||
side = side * value / sv_rollspeed->value;
|
||||
else side = value;
|
||||
|
||||
return side*sign;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SV_Accelerate
|
||||
==============
|
||||
*/
|
||||
void SV_Accelerate( sv_client_t *cl )
|
||||
{
|
||||
int i;
|
||||
float addspeed;
|
||||
float accelspeed, currentspeed;
|
||||
|
||||
currentspeed = DotProduct( cl->edict->progs.sv->velocity, wishdir );
|
||||
addspeed = wishspeed - currentspeed;
|
||||
if( addspeed <= 0 ) return;
|
||||
accelspeed = sv_accelerate->value * sv.frametime * wishspeed;
|
||||
if( accelspeed > addspeed ) accelspeed = addspeed;
|
||||
for( i = 0; i < 3; i++ ) cl->edict->progs.sv->velocity[i] += accelspeed * wishdir[i];
|
||||
}
|
||||
|
||||
void SV_AirAccelerate( sv_client_t *cl, vec3_t wishveloc )
|
||||
{
|
||||
int i;
|
||||
float addspeed;
|
||||
float wishspd, accelspeed, currentspeed;
|
||||
|
||||
wishspd = VectorNormalizeLength( wishveloc );
|
||||
if( wishspd > 30 ) wishspd = 30;
|
||||
currentspeed = DotProduct( cl->edict->progs.sv->velocity, wishveloc );
|
||||
addspeed = wishspd - currentspeed;
|
||||
if( addspeed <= 0 ) return;
|
||||
accelspeed = sv_accelerate->value * wishspeed * sv.frametime;
|
||||
if( accelspeed > addspeed ) accelspeed = addspeed;
|
||||
|
||||
for( i = 0; i < 3; i++ ) cl->edict->progs.sv->velocity[i] += accelspeed * wishveloc[i];
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
SV_WaterMove
|
||||
|
||||
===================
|
||||
*/
|
||||
void SV_WaterMove( sv_client_t *cl, usercmd_t *cmd )
|
||||
{
|
||||
int i;
|
||||
vec3_t wishvel;
|
||||
float speed, newspeed;
|
||||
float wishspeed, addspeed;
|
||||
float accelspeed, temp;
|
||||
|
||||
// user intentions
|
||||
AngleVectors( cl->edict->progs.sv->v_angle, forward, right, up );
|
||||
|
||||
for( i = 0; i < 3; i++ ) wishvel[i] = forward[i] * cmd->forwardmove + right[i] * cmd->sidemove;
|
||||
|
||||
if(!cmd->forwardmove && !cmd->sidemove && !cmd->upmove)
|
||||
wishvel[2] -= 60; // drift towards bottom
|
||||
else wishvel[2] += cmd->upmove;
|
||||
|
||||
wishspeed = VectorLength( wishvel );
|
||||
if( wishspeed > sv_maxspeed->value )
|
||||
{
|
||||
temp = sv_maxspeed->value / wishspeed;
|
||||
VectorScale( wishvel, temp, wishvel );
|
||||
wishspeed = sv_maxspeed->value;
|
||||
}
|
||||
wishspeed *= 0.7;
|
||||
|
||||
// water friction
|
||||
speed = VectorLength( cl->edict->progs.sv->velocity );
|
||||
if( speed )
|
||||
{
|
||||
newspeed = speed - sv.frametime * speed * sv_friction->value;
|
||||
if( newspeed < 0 ) newspeed = 0;
|
||||
temp = newspeed / speed;
|
||||
VectorScale( cl->edict->progs.sv->velocity, temp, cl->edict->progs.sv->velocity );
|
||||
}
|
||||
else newspeed = 0;
|
||||
|
||||
// water acceleration
|
||||
if( !wishspeed ) return;
|
||||
|
||||
addspeed = wishspeed - newspeed;
|
||||
if( addspeed <= 0 ) return;
|
||||
|
||||
VectorNormalize( wishvel );
|
||||
accelspeed = sv_accelerate->value * wishspeed * sv.frametime;
|
||||
if( accelspeed > addspeed ) accelspeed = addspeed;
|
||||
|
||||
for( i = 0; i < 3; i++ ) cl->edict->progs.sv->velocity[i] += accelspeed * wishvel[i];
|
||||
}
|
||||
|
||||
void SV_WaterJump( sv_client_t *cl )
|
||||
{
|
||||
if (sv.time > cl->edict->progs.sv->teleport_time || !cl->edict->progs.sv->waterlevel )
|
||||
{
|
||||
cl->edict->progs.sv->flags = (int)cl->edict->progs.sv->aiflags & ~AI_WATERJUMP;
|
||||
cl->edict->progs.sv->teleport_time = 0;
|
||||
}
|
||||
cl->edict->progs.sv->velocity[0] = cl->edict->progs.sv->movedir[0];
|
||||
cl->edict->progs.sv->velocity[1] = cl->edict->progs.sv->movedir[1];
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
SV_AirMove
|
||||
|
||||
===================
|
||||
*/
|
||||
void SV_AirMove( sv_client_t *cl, usercmd_t *cmd )
|
||||
{
|
||||
int i;
|
||||
vec3_t wishvel;
|
||||
float fmove, smove, temp;
|
||||
|
||||
wishvel[0] = wishvel[2] = 0;
|
||||
wishvel[1] = cl->edict->progs.sv->angles[1];
|
||||
AngleVectors( wishvel, forward, right, up );
|
||||
|
||||
fmove = cmd->forwardmove;
|
||||
smove = cmd->sidemove;
|
||||
|
||||
// hack to not let you back into teleporter
|
||||
if( sv.time < cl->edict->progs.sv->teleport_time && fmove < 0 )
|
||||
fmove = 0;
|
||||
|
||||
for( i = 0; i < 3; i++ ) wishvel[i] = forward[i] * fmove + right[i] * smove;
|
||||
|
||||
if((int)cl->edict->progs.sv->movetype != MOVETYPE_WALK )
|
||||
wishvel[2] += cmd->upmove;
|
||||
|
||||
VectorCopy( wishvel, wishdir );
|
||||
wishspeed = VectorNormalizeLength( wishdir );
|
||||
if( wishspeed > sv_maxspeed->value )
|
||||
{
|
||||
temp = sv_maxspeed->value / wishspeed;
|
||||
VectorScale( wishvel, temp, wishvel );
|
||||
wishspeed = sv_maxspeed->value;
|
||||
}
|
||||
|
||||
if( cl->edict->progs.sv->movetype == MOVETYPE_NOCLIP )
|
||||
{
|
||||
// noclip
|
||||
VectorCopy( wishvel, cl->edict->progs.sv->velocity );
|
||||
}
|
||||
else if( onground )
|
||||
{
|
||||
SV_UserFriction( cl );
|
||||
SV_Accelerate( cl );
|
||||
}
|
||||
else
|
||||
{
|
||||
// not on ground, so little effect on velocity
|
||||
SV_AirAccelerate( cl, wishvel );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_ClientThink
|
||||
|
@ -988,12 +1278,71 @@ Also called by bot code
|
|||
*/
|
||||
void SV_ClientThink( sv_client_t *cl, usercmd_t *cmd )
|
||||
{
|
||||
cl->lastcmd = *cmd;
|
||||
|
||||
vec3_t v_angle;
|
||||
|
||||
cl->cmd = *cmd;
|
||||
cl->skipframes = 0;
|
||||
#if 1
|
||||
// may have been kicked during the last usercmd
|
||||
if( sv_paused->integer )
|
||||
if( sv_paused->integer ) return;
|
||||
|
||||
SV_ApplyClientMove( cl, cmd );
|
||||
// make sure the velocity is sane (not a NaN)
|
||||
SV_CheckVelocity( cl->edict );
|
||||
|
||||
// LordHavoc: QuakeC replacement for SV_ClientThink (player movement)
|
||||
/*if( svs.ClientMove )
|
||||
{
|
||||
prog->globals.sv->time = sv.time;
|
||||
prog->globals.sv->pev = PRVM_EDICT_TO_PROG( cl->edict );
|
||||
PRVM_ExecuteProgram( svs.ClientMove, "ClientMove" );
|
||||
SV_CheckVelocity( cl->edict );
|
||||
return;
|
||||
}*/
|
||||
|
||||
if( cl->edict->progs.sv->movetype == MOVETYPE_NONE )
|
||||
return;
|
||||
|
||||
onground = (int)cl->edict->progs.sv->aiflags & AI_ONGROUND;
|
||||
|
||||
SV_DropPunchAngle( cl );
|
||||
|
||||
// if dead, behave differently
|
||||
if( cl->edict->progs.sv->health <= 0 )
|
||||
return;
|
||||
|
||||
// angles
|
||||
// show 1/3 the pitch angle and all the roll angle
|
||||
VectorAdd( cl->edict->progs.sv->v_angle, cl->edict->progs.sv->punchangle, v_angle );
|
||||
cl->edict->progs.sv->angles[ROLL] = SV_CalcRoll( cl->edict->progs.sv->angles, cl->edict->progs.sv->velocity) * 4;
|
||||
if( !cl->edict->progs.sv->fixangle )
|
||||
{
|
||||
cl->edict->progs.sv->angles[PITCH] = -v_angle[PITCH]/3;
|
||||
cl->edict->progs.sv->angles[YAW] = v_angle[YAW];
|
||||
}
|
||||
|
||||
if((int)cl->edict->progs.sv->aiflags & AI_WATERJUMP )
|
||||
{
|
||||
SV_WaterJump( cl );
|
||||
SV_CheckVelocity( cl->edict );
|
||||
return;
|
||||
}
|
||||
|
||||
// walk
|
||||
if((cl->edict->progs.sv->waterlevel >= 2) && (cl->edict->progs.sv->movetype != MOVETYPE_NOCLIP))
|
||||
{
|
||||
SV_WaterMove( cl, &cl->cmd );
|
||||
SV_CheckVelocity( cl->edict );
|
||||
return;
|
||||
}
|
||||
SV_AirMove( cl, &cl->cmd );
|
||||
SV_CheckVelocity( cl->edict );
|
||||
|
||||
VectorCopy( cl->edict->progs.sv->origin, cl->ps.origin );
|
||||
VectorCopy( cl->edict->progs.sv->velocity, cl->ps.velocity );
|
||||
#else
|
||||
ClientThink( cl->edict, cmd );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1055,13 +1404,13 @@ static void SV_UserMove( sv_client_t *cl, sizebuf_t *msg )
|
|||
{
|
||||
while( net_drop > 2 )
|
||||
{
|
||||
SV_ClientThink( cl, &cl->lastcmd );
|
||||
SV_Physics_ClientMove( cl, &cl->lastcmd );
|
||||
net_drop--;
|
||||
}
|
||||
if( net_drop > 1 ) SV_ClientThink( cl, &oldest );
|
||||
if( net_drop > 0 ) SV_ClientThink( cl, &oldcmd );
|
||||
if( net_drop > 1 ) SV_Physics_ClientMove( cl, &oldest );
|
||||
if( net_drop > 0 ) SV_Physics_ClientMove( cl, &oldcmd );
|
||||
}
|
||||
SV_ClientThink( cl, &newcmd );
|
||||
SV_Physics_ClientMove( cl, &newcmd );
|
||||
}
|
||||
cl->lastcmd = newcmd;
|
||||
}
|
||||
|
|
|
@ -457,7 +457,7 @@ void SV_Status_f( void )
|
|||
if( !cl->state ) continue;
|
||||
|
||||
Msg("%3i ", i);
|
||||
Msg("%5i ", cl->edict->priv.sv->client->ps.stats[STAT_FRAGS]);
|
||||
Msg("%5i ", (int)cl->edict->progs.sv->frags );
|
||||
|
||||
if (cl->state == cs_connected) Msg("Connect");
|
||||
else if (cl->state == cs_zombie) Msg ("Zombie ");
|
||||
|
|
|
@ -103,6 +103,10 @@ struct sv_entvars_s
|
|||
vec3_t punchangle;
|
||||
vec3_t view_ofs;
|
||||
vec3_t v_angle;
|
||||
float button0;
|
||||
float button1;
|
||||
float button2;
|
||||
float impulse;
|
||||
string_t v_model;
|
||||
float v_frame;
|
||||
float v_body;
|
||||
|
@ -121,6 +125,8 @@ struct sv_entvars_s
|
|||
int owner;
|
||||
int enemy;
|
||||
int aiment;
|
||||
int goalentity;
|
||||
float fixangle;
|
||||
float ideal_yaw;
|
||||
float yaw_speed;
|
||||
float teleport_time;
|
||||
|
@ -129,6 +135,7 @@ struct sv_entvars_s
|
|||
float nextthink;
|
||||
float health;
|
||||
float gravity;
|
||||
float frags;
|
||||
float team;
|
||||
};
|
||||
|
||||
|
@ -137,23 +144,16 @@ struct sv_entvars_s
|
|||
|
||||
static fields_t sv_reqfields[] =
|
||||
{
|
||||
{142, 6, "walk"},
|
||||
{143, 6, "jump"},
|
||||
{144, 6, "duck"},
|
||||
{145, 2, "v_animtime"},
|
||||
{146, 2, "frags"},
|
||||
{147, 2, "weapon"},
|
||||
{148, 2, "items"},
|
||||
{149, 1, "target"},
|
||||
{150, 1, "parent"},
|
||||
{151, 1, "targetname"},
|
||||
{152, 4, "goalentity"},
|
||||
{153, 2, "deadflag"},
|
||||
{154, 2, "button0"},
|
||||
{155, 2, "button1"},
|
||||
{156, 2, "button2"},
|
||||
{157, 2, "impulse"},
|
||||
{158, 2, "fixangle"},
|
||||
{149, 6, "walk"},
|
||||
{150, 6, "jump"},
|
||||
{151, 6, "duck"},
|
||||
{152, 2, "v_animtime"},
|
||||
{153, 2, "weapon"},
|
||||
{154, 2, "items"},
|
||||
{155, 1, "target"},
|
||||
{156, 1, "parent"},
|
||||
{157, 1, "targetname"},
|
||||
{158, 2, "deadflag"},
|
||||
{159, 2, "idealpitch"},
|
||||
{160, 1, "netname"},
|
||||
{161, 2, "max_health"},
|
||||
|
@ -244,6 +244,6 @@ static fields_t sv_reqfields[] =
|
|||
{264, 1, "oldmodel"}
|
||||
};
|
||||
|
||||
#define PROG_CRC_SERVER 2740
|
||||
#define PROG_CRC_SERVER 61861
|
||||
|
||||
#endif//SV_EDICT_H
|
|
@ -70,23 +70,24 @@ void SV_UpdateEntityState( edict_t *ent )
|
|||
VectorCopy (ent->progs.sv->origin, ent->priv.sv->s.origin);
|
||||
VectorCopy (ent->progs.sv->angles, ent->priv.sv->s.angles);
|
||||
VectorCopy (ent->progs.sv->old_origin, ent->priv.sv->s.old_origin);
|
||||
ent->priv.sv->s.modelindex = (int)ent->progs.sv->modelindex;
|
||||
ent->priv.sv->s.model.index = (int)ent->progs.sv->modelindex;
|
||||
ent->priv.sv->s.health = ent->progs.sv->health;
|
||||
|
||||
if( ent->priv.sv->client )
|
||||
{
|
||||
// attached weaponmodel
|
||||
// FIXME: let any entity send weaponmodel
|
||||
ent->priv.sv->s.weaponmodel = ent->priv.sv->client->ps.pmodel.index;
|
||||
ent->priv.sv->s.pmodel.index = ent->priv.sv->client->ps.pmodel.index;
|
||||
}
|
||||
|
||||
ent->priv.sv->s.skin = (short)ent->progs.sv->skin; // studio model skin
|
||||
ent->priv.sv->s.body = (byte)ent->progs.sv->body; // studio model submodel
|
||||
ent->priv.sv->s.frame = ent->progs.sv->frame; // any model current frame
|
||||
ent->priv.sv->s.sequence = (byte)ent->progs.sv->sequence; // studio model sequence
|
||||
ent->priv.sv->s.effects = (uint)ent->progs.sv->effects; // shared client and render flags
|
||||
ent->priv.sv->s.renderfx = (int)ent->progs.sv->renderfx; // renderer flags
|
||||
ent->priv.sv->s.alpha = ent->progs.sv->alpha; // alpha value
|
||||
ent->priv.sv->s.animtime = ent->progs.sv->animtime; // auto-animating time
|
||||
ent->priv.sv->s.model.skin = (short)ent->progs.sv->skin; // studio model skin
|
||||
ent->priv.sv->s.model.body = (byte)ent->progs.sv->body; // studio model submodel
|
||||
ent->priv.sv->s.model.frame = ent->progs.sv->frame; // any model current frame
|
||||
ent->priv.sv->s.model.sequence = (byte)ent->progs.sv->sequence; // studio model sequence
|
||||
ent->priv.sv->s.effects = (uint)ent->progs.sv->effects; // shared client and render flags
|
||||
ent->priv.sv->s.renderfx = (int)ent->progs.sv->renderfx; // renderer flags
|
||||
ent->priv.sv->s.renderamt = ent->progs.sv->alpha; // alpha value
|
||||
ent->priv.sv->s.model.animtime = ent->progs.sv->animtime; // auto-animating time
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -264,7 +265,7 @@ void SV_BuildClientFrame( sv_client_t *cl )
|
|||
// calculate the visible areas
|
||||
frame->areabytes = pe->WriteAreaBits( frame->areabits, clientarea );
|
||||
|
||||
// grab the current player_state_t
|
||||
// grab the current player state
|
||||
frame->ps = clent->priv.sv->client->ps;
|
||||
|
||||
clientpvs = pe->ClusterPVS( clientcluster );
|
||||
|
@ -389,7 +390,7 @@ bool SV_SendClientDatagram( sv_client_t *cl )
|
|||
MSG_Init( &msg, msg_buf, sizeof(msg_buf));
|
||||
|
||||
// send over all the relevant entity_state_t
|
||||
// and the player_state_t
|
||||
// and the player state
|
||||
SV_WriteFrameToClient( cl, &msg );
|
||||
|
||||
// copy the accumulated multicast datagram
|
||||
|
|
|
@ -185,12 +185,12 @@ void SV_SpawnServer( char *server, char *savename, sv_state_t serverstate )
|
|||
|
||||
if (serverstate != ss_active)
|
||||
{
|
||||
sv.models[1] = pe->BeginRegistration( "", false, &checksum); // no real map
|
||||
sv.worldmodel = sv.models[1] = pe->BeginRegistration( "", false, &checksum); // no real map
|
||||
}
|
||||
else
|
||||
{
|
||||
com.sprintf(sv.configstrings[CS_MODELS+1], "maps/%s", server);
|
||||
sv.models[1] = pe->BeginRegistration(sv.configstrings[CS_MODELS+1], false, &checksum);
|
||||
sv.worldmodel = sv.models[1] = pe->BeginRegistration(sv.configstrings[CS_MODELS+1], false, &checksum);
|
||||
}
|
||||
com.sprintf(sv.configstrings[CS_MAPCHECKSUM], "%i", checksum);
|
||||
|
||||
|
|
|
@ -18,16 +18,18 @@ cvar_t *zombietime; // seconds to sink messages after disconnect
|
|||
cvar_t *rcon_password; // password for remote server commands
|
||||
|
||||
cvar_t *allow_download;
|
||||
cvar_t *allow_download_players;
|
||||
cvar_t *allow_download_models;
|
||||
cvar_t *allow_download_sounds;
|
||||
cvar_t *allow_download_maps;
|
||||
|
||||
cvar_t *sv_airaccelerate;
|
||||
cvar_t *sv_maxvelocity;
|
||||
cvar_t *sv_gravity;
|
||||
|
||||
cvar_t *sv_stepheight;
|
||||
cvar_t *sv_noreload; // don't reload level state when reentering
|
||||
cvar_t *sv_playersonly;
|
||||
cvar_t *sv_rollangle;
|
||||
cvar_t *sv_rollspeed;
|
||||
cvar_t *sv_maxspeed;
|
||||
cvar_t *sv_accelerate;
|
||||
cvar_t *sv_friction;
|
||||
|
||||
|
||||
cvar_t *maxclients; // FIXME: rename sv_maxclients
|
||||
cvar_t *hostname;
|
||||
|
@ -192,8 +194,6 @@ SV_RunGameFrame
|
|||
*/
|
||||
void SV_RunGameFrame (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if( sv_paused->integer && maxclients->integer == 1 )
|
||||
return;
|
||||
|
||||
|
@ -205,10 +205,7 @@ void SV_RunGameFrame (void)
|
|||
sv.frametime = HOST_FRAMETIME * 0.001f;
|
||||
sv.time = sv.framenum * sv.frametime;
|
||||
|
||||
if(!cm_paused->value)
|
||||
for( i = 0; i < 6; i++ )
|
||||
pe->Frame( sv.frametime * i );//FIXME
|
||||
SV_RunFrame ();
|
||||
SV_Physics();
|
||||
|
||||
// never get more than one tic behind
|
||||
if( sv.time * 1000 < svs.realtime )
|
||||
|
@ -369,6 +366,8 @@ void SV_Init (void)
|
|||
Cvar_Get ("protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO|CVAR_INIT, "displays server protocol version" );
|
||||
|
||||
sv_fps = Cvar_Get( "sv_fps", "60", CVAR_ARCHIVE|CVAR_LATCH, "running server at" );
|
||||
sv_stepheight = Cvar_Get( "sv_stepheight", "18", CVAR_ARCHIVE|CVAR_LATCH, "how high you can step up" );
|
||||
sv_playersonly = Cvar_Get( "playersonly", "0", 0, "freezes time, except for players" );
|
||||
maxclients = Cvar_Get ("maxclients", "1", CVAR_SERVERINFO | CVAR_LATCH, "max count of clients for current game" );
|
||||
hostname = Cvar_Get ("hostname", "unnamed", CVAR_SERVERINFO | CVAR_ARCHIVE, "host name" );
|
||||
timeout = Cvar_Get ("timeout", "125", 0, "connection timeout" );
|
||||
|
@ -376,16 +375,15 @@ void SV_Init (void)
|
|||
sv_paused = Cvar_Get ("paused", "0", 0, "server pause" );
|
||||
sv_enforcetime = Cvar_Get ("sv_enforcetime", "0", 0, "client enforce time" );
|
||||
allow_download = Cvar_Get ("allow_download", "1", CVAR_ARCHIVE, "allow download resources" );
|
||||
allow_download_players = Cvar_Get ("allow_download_players", "0", CVAR_ARCHIVE, "let downloading playermodels" );
|
||||
allow_download_models = Cvar_Get ("allow_download_models", "1", CVAR_ARCHIVE, "let downloading models");
|
||||
allow_download_sounds = Cvar_Get ("allow_download_sounds", "1", CVAR_ARCHIVE, "let downloading sounds" );
|
||||
allow_download_maps = Cvar_Get ("allow_download_maps", "1", CVAR_ARCHIVE, "let downloading maps" );
|
||||
|
||||
sv_noreload = Cvar_Get ("sv_noreload", "0", 0, "ignore savepoints for singleplayer" );
|
||||
|
||||
sv_noreload = Cvar_Get("sv_noreload", "0", 0, "ignore savepoints for singleplayer" );
|
||||
sv_rollangle = Cvar_Get("sv_rollangle", "2", 0, "how much to tilt the view when strafing" );
|
||||
sv_rollspeed = Cvar_Get("sv_rollspeed", "200", 0, "how much strafing is necessary to tilt the view" );
|
||||
sv_airaccelerate = Cvar_Get("sv_airaccelerate", "0", CVAR_LATCH, "player accellerate in air" );
|
||||
sv_maxvelocity = Cvar_Get("sv_maxvelocity", "2000", 0, "max world velocity" );
|
||||
sv_gravity = Cvar_Get("sv_gravity", "800", 0, "world gravity" );
|
||||
sv_maxspeed = Cvar_Get("sv_maxspeed", "320", 0, "maximum speed a player can accelerate to when on ground (can be exceeded by tricks)");
|
||||
sv_accelerate = Cvar_Get( "sv_accelerate", "10", 0, "rate at which a player accelerates to sv_maxspeed" );
|
||||
sv_friction = Cvar_Get( "sv_friction", "4", 0, "how fast you slow down" );
|
||||
|
||||
public_server = Cvar_Get ("public", "0", 0, "change server type from private to public" );
|
||||
|
||||
|
|
|
@ -0,0 +1,485 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2007 ©
|
||||
// sv_move.c - monsters movement
|
||||
//=======================================================================
|
||||
|
||||
#include "common.h"
|
||||
#include "server.h"
|
||||
|
||||
/*
|
||||
=============
|
||||
SV_CheckBottom
|
||||
|
||||
Returns false if any part of the bottom of the entity is off an edge that
|
||||
is not a staircase.
|
||||
|
||||
=============
|
||||
*/
|
||||
bool SV_CheckBottom( edict_t *ent )
|
||||
{
|
||||
vec3_t mins, maxs, start, stop;
|
||||
float mid, bottom;
|
||||
trace_t trace;
|
||||
int x, y;
|
||||
|
||||
VectorAdd (ent->progs.sv->origin, ent->progs.sv->mins, mins);
|
||||
VectorAdd (ent->progs.sv->origin, ent->progs.sv->maxs, maxs);
|
||||
|
||||
// if all of the points under the corners are solid world, don't bother
|
||||
// with the tougher checks
|
||||
// the corners must be within 16 of the midpoint
|
||||
start[2] = mins[2] - 1;
|
||||
for( x = 0; x <= 1; x++ )
|
||||
{
|
||||
for( y = 0; y <= 1; y++ )
|
||||
{
|
||||
start[0] = x ? maxs[0] : mins[0];
|
||||
start[1] = y ? maxs[1] : mins[1];
|
||||
if(!(SV_PointContents( start ) & (CONTENTS_SOLID | CONTENTS_BODY)))
|
||||
goto realcheck;
|
||||
}
|
||||
}
|
||||
return true; // we got out easy
|
||||
|
||||
realcheck:
|
||||
// check it for real...
|
||||
start[2] = mins[2];
|
||||
|
||||
// the midpoint must be within 16 of the bottom
|
||||
start[0] = stop[0] = (mins[0] + maxs[0]) * 0.5f;
|
||||
start[1] = stop[1] = (mins[1] + maxs[1]) * 0.5f;
|
||||
stop[2] = start[2] - 2 * sv_stepheight->value;
|
||||
trace = SV_Trace( start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, SV_ContentsMask(ent));
|
||||
|
||||
if( trace.fraction == 1.0 )
|
||||
return false;
|
||||
mid = bottom = trace.endpos[2];
|
||||
|
||||
// the corners must be within 16 of the midpoint
|
||||
for( x = 0; x <= 1; x++ )
|
||||
{
|
||||
for( y = 0; y <= 1; y++ )
|
||||
{
|
||||
start[0] = stop[0] = x ? maxs[0] : mins[0];
|
||||
start[1] = stop[1] = y ? maxs[1] : mins[1];
|
||||
|
||||
trace = SV_Trace( start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, SV_ContentsMask(ent));
|
||||
|
||||
if( trace.fraction != 1.0 && trace.endpos[2] > bottom )
|
||||
bottom = trace.endpos[2];
|
||||
if( trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight->value )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
SV_movestep
|
||||
|
||||
Called by monster program code.
|
||||
The move will be adjusted for slopes and stairs, but if the move isn't
|
||||
possible, no move is done and false is returned
|
||||
=============
|
||||
*/
|
||||
bool SV_movestep( edict_t *ent, vec3_t move, bool relink, bool noenemy, bool settrace )
|
||||
{
|
||||
float dz;
|
||||
vec3_t oldorg, neworg, end, traceendpos;
|
||||
edict_t *enemy;
|
||||
trace_t trace;
|
||||
int i;
|
||||
|
||||
// try the move
|
||||
VectorCopy (ent->progs.sv->origin, oldorg);
|
||||
VectorAdd (ent->progs.sv->origin, move, neworg);
|
||||
|
||||
// flying monsters don't step up
|
||||
if((int)ent->progs.sv->aiflags & (AI_SWIM|AI_FLY))
|
||||
{
|
||||
// try one move with vertical motion, then one without
|
||||
for( i = 0; i < 2; i++ )
|
||||
{
|
||||
VectorAdd( ent->progs.sv->origin, move, neworg );
|
||||
if( noenemy ) enemy = prog->edicts;
|
||||
else
|
||||
{
|
||||
enemy = PRVM_PROG_TO_EDICT( ent->progs.sv->enemy );
|
||||
if( i == 0 && enemy != prog->edicts )
|
||||
{
|
||||
dz = ent->progs.sv->origin[2] - PRVM_PROG_TO_EDICT(ent->progs.sv->enemy)->progs.sv->origin[2];
|
||||
if( dz > 40 ) neworg[2] -= 8;
|
||||
if( dz < 30 ) neworg[2] += 8;
|
||||
}
|
||||
}
|
||||
trace = SV_Trace( ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, neworg, MOVE_NORMAL, ent, SV_ContentsMask(ent));
|
||||
|
||||
if( trace.fraction == 1 )
|
||||
{
|
||||
VectorCopy( trace.endpos, traceendpos );
|
||||
if(((int)ent->progs.sv->aiflags & AI_SWIM) && !(SV_PointContents(traceendpos) & MASK_WATER))
|
||||
return false; // swim monster left water
|
||||
|
||||
VectorCopy( traceendpos, ent->progs.sv->origin );
|
||||
if( relink ) SV_LinkEdict( ent );
|
||||
return true;
|
||||
}
|
||||
if( enemy == prog->edicts ) break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// push down from a step height above the wished position
|
||||
neworg[2] += sv_stepheight->value;
|
||||
VectorCopy( neworg, end );
|
||||
end[2] -= sv_stepheight->value * 2;
|
||||
|
||||
trace = SV_Trace( neworg, ent->progs.sv->mins, ent->progs.sv->maxs, end, MOVE_NORMAL, ent, SV_ContentsMask(ent));
|
||||
|
||||
if( trace.startsolid )
|
||||
{
|
||||
neworg[2] -= sv_stepheight->value;
|
||||
trace = SV_Trace( neworg, ent->progs.sv->mins, ent->progs.sv->maxs, end, MOVE_NORMAL, ent, SV_ContentsMask(ent));
|
||||
if( trace.startsolid ) return false;
|
||||
}
|
||||
if( trace.fraction == 1 )
|
||||
{
|
||||
// if monster had the ground pulled out, go ahead and fall
|
||||
if((int)ent->progs.sv->aiflags & AI_PARTIALONGROUND )
|
||||
{
|
||||
VectorAdd( ent->progs.sv->origin, move, ent->progs.sv->origin );
|
||||
if (relink) SV_LinkEdict( ent );
|
||||
ent->progs.sv->aiflags = (int)ent->progs.sv->aiflags & ~AI_ONGROUND;
|
||||
return true;
|
||||
}
|
||||
return false; // walked off an edge
|
||||
}
|
||||
|
||||
// check point traces down for dangling corners
|
||||
VectorCopy( trace.endpos, ent->progs.sv->origin );
|
||||
|
||||
if(!SV_CheckBottom( ent ))
|
||||
{
|
||||
if((int)ent->progs.sv->aiflags & AI_PARTIALONGROUND )
|
||||
{
|
||||
// entity had floor mostly pulled out from underneath it
|
||||
// and is trying to correct
|
||||
if( relink ) SV_LinkEdict( ent );
|
||||
return true;
|
||||
}
|
||||
VectorCopy( oldorg, ent->progs.sv->origin );
|
||||
return false;
|
||||
}
|
||||
|
||||
if((int)ent->progs.sv->aiflags & AI_PARTIALONGROUND )
|
||||
ent->progs.sv->flags = (int)ent->progs.sv->flags & ~AI_PARTIALONGROUND;
|
||||
|
||||
ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG( trace.ent );
|
||||
|
||||
// the move is ok
|
||||
if( relink ) SV_LinkEdict( ent );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*
|
||||
======================
|
||||
SV_StepDirection
|
||||
|
||||
Turns to the movement direction, and walks the current distance if
|
||||
facing it.
|
||||
|
||||
======================
|
||||
*/
|
||||
bool SV_StepDirection( edict_t *ent, float yaw, float dist )
|
||||
{
|
||||
vec3_t move, oldorigin;
|
||||
float delta, current;
|
||||
|
||||
ent->progs.sv->ideal_yaw = yaw;
|
||||
current = anglemod( ent->progs.sv->angles[1] );
|
||||
ent->progs.sv->angles[1] = SV_AngleMod( ent->progs.sv->ideal_yaw, current, ent->progs.sv->yaw_speed );
|
||||
|
||||
yaw = yaw * M_PI*2 / 360;
|
||||
move[0] = cos(yaw)*dist;
|
||||
move[1] = sin(yaw)*dist;
|
||||
move[2] = 0;
|
||||
|
||||
VectorCopy( ent->progs.sv->origin, oldorigin );
|
||||
if(SV_movestep( ent, move, false, false, false ))
|
||||
{
|
||||
delta = ent->progs.sv->angles[YAW] - ent->progs.sv->ideal_yaw;
|
||||
if( delta > 45 && delta < 315 )
|
||||
{
|
||||
// not turned far enough, so don't take the step
|
||||
VectorCopy( oldorigin, ent->progs.sv->origin );
|
||||
}
|
||||
SV_LinkEdict( ent );
|
||||
return true;
|
||||
}
|
||||
SV_LinkEdict( ent );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
======================
|
||||
SV_FixCheckBottom
|
||||
|
||||
======================
|
||||
*/
|
||||
void SV_FixCheckBottom( edict_t *ent )
|
||||
{
|
||||
ent->progs.sv->flags = (int)ent->progs.sv->aiflags | AI_PARTIALONGROUND;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
SV_NewChaseDir
|
||||
|
||||
================
|
||||
*/
|
||||
void SV_NewChaseDir( edict_t *actor, edict_t *enemy, float dist )
|
||||
{
|
||||
float deltax, deltay;
|
||||
float d[3], tdir, olddir, turnaround;
|
||||
|
||||
olddir = anglemod((int)(actor->progs.sv->ideal_yaw/45) * 45);
|
||||
turnaround = anglemod( olddir - 180 );
|
||||
|
||||
deltax = enemy->progs.sv->origin[0] - actor->progs.sv->origin[0];
|
||||
deltay = enemy->progs.sv->origin[1] - actor->progs.sv->origin[1];
|
||||
if( deltax > 10 ) d[1]= 0;
|
||||
else if( deltax < -10 ) d[1] = 180;
|
||||
else d[1] = -1;
|
||||
if( deltay < -10 ) d[2] = 270;
|
||||
else if( deltay > 10 ) d[2] = 90;
|
||||
else d[2] = -1;
|
||||
|
||||
// try direct route
|
||||
if( d[1] != -1 && d[2] != -1 )
|
||||
{
|
||||
if( d[1] == 0 ) tdir = d[2] == 90 ? 45 : 315;
|
||||
else tdir = d[2] == 90 ? 135 : 215;
|
||||
|
||||
if( tdir != turnaround && SV_StepDirection( actor, tdir, dist ))
|
||||
return;
|
||||
}
|
||||
|
||||
// try other directions
|
||||
if(((rand()&3) & 1) || fabs(deltay) > fabs(deltax))
|
||||
{
|
||||
tdir = d[1];
|
||||
d[1] = d[2];
|
||||
d[2] = tdir;
|
||||
}
|
||||
|
||||
if( d[1] != -1 && d[1] != turnaround && SV_StepDirection( actor, d[1], dist ))
|
||||
return;
|
||||
|
||||
if( d[2] != -1 && d[2] != turnaround && SV_StepDirection( actor, d[2], dist ))
|
||||
return;
|
||||
|
||||
// there is no direct path to the player, so pick another direction
|
||||
if( olddir != -1 && SV_StepDirection( actor, olddir, dist ))
|
||||
return;
|
||||
|
||||
// randomly determine direction of search
|
||||
if( rand() & 1 )
|
||||
{
|
||||
for( tdir = 0; tdir <= 315; tdir += 45 )
|
||||
if( tdir != turnaround && SV_StepDirection( actor, tdir, dist ))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( tdir = 315; tdir >= 0; tdir -= 45 )
|
||||
if( tdir != turnaround && SV_StepDirection( actor, tdir, dist ))
|
||||
return;
|
||||
}
|
||||
|
||||
if( turnaround != -1 && SV_StepDirection( actor, turnaround, dist ))
|
||||
return;
|
||||
|
||||
actor->progs.sv->ideal_yaw = olddir; // can't move
|
||||
|
||||
// if a bridge was pulled out from underneath a monster, it may not have
|
||||
// a valid standing position at all
|
||||
if(!SV_CheckBottom( actor )) SV_FixCheckBottom( actor );
|
||||
}
|
||||
|
||||
/*
|
||||
======================
|
||||
SV_CloseEnough
|
||||
|
||||
======================
|
||||
*/
|
||||
bool SV_CloseEnough( edict_t *ent, edict_t *goal, float dist )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
if( goal->progs.sv->absmin[i] > ent->progs.sv->absmax[i] + dist )
|
||||
return false;
|
||||
if( goal->progs.sv->absmax[i] < ent->progs.sv->absmin[i] - dist )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
======================
|
||||
SV_MoveToGoal
|
||||
|
||||
======================
|
||||
*/
|
||||
void SV_MoveToGoal( void )
|
||||
{
|
||||
edict_t *ent, *goal;
|
||||
float dist;
|
||||
|
||||
if(!VM_ValidateArgs( "movetogoal", 1 ))
|
||||
return;
|
||||
|
||||
ent = PRVM_PROG_TO_EDICT( prog->globals.sv->pev );
|
||||
goal = PRVM_PROG_TO_EDICT( ent->progs.sv->goalentity );
|
||||
dist = PRVM_G_FLOAT( OFS_PARM0 );
|
||||
|
||||
if(!((int)ent->progs.sv->aiflags & (AI_ONGROUND|AI_FLY|AI_SWIM)))
|
||||
{
|
||||
PRVM_G_FLOAT(OFS_RETURN) = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// if the next step hits the enemy, return immediately
|
||||
if(PRVM_PROG_TO_EDICT(ent->progs.sv->enemy) != prog->edicts && SV_CloseEnough( ent, goal, dist))
|
||||
return;
|
||||
|
||||
// bump around...
|
||||
if(( rand() & 3) == 1 || !SV_StepDirection( ent, ent->progs.sv->ideal_yaw, dist ))
|
||||
{
|
||||
SV_NewChaseDir( ent, goal, dist );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// g-cont: my stupid callbacks
|
||||
cmodel_t *SV_GetModelPtr( edict_t *ent )
|
||||
{
|
||||
return pe->RegisterModel( sv.configstrings[CS_MODELS + (int)ent->progs.sv->modelindex] );
|
||||
}
|
||||
|
||||
float *SV_GetModelVerts( sv_edict_t *ed, int *numvertices )
|
||||
{
|
||||
cmodel_t *cmod;
|
||||
edict_t *ent;
|
||||
|
||||
ent = PRVM_EDICT_NUM(ed->serialnumber);
|
||||
cmod = pe->RegisterModel( sv.configstrings[CS_MODELS + (int)ent->progs.sv->modelindex] );
|
||||
if( cmod )
|
||||
{
|
||||
int i = (int)ent->progs.sv->body;
|
||||
i = bound( 0, i, cmod->numbodies ); // make sure what body exist
|
||||
|
||||
if( cmod->col[i] )
|
||||
{
|
||||
*numvertices = cmod->col[i]->numverts;
|
||||
return (float *)cmod->col[i]->verts;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SV_Transform( sv_edict_t *ed, matrix4x3 transform )
|
||||
{
|
||||
edict_t *edict;
|
||||
vec3_t origin, angles;
|
||||
matrix4x4 objmatrix;
|
||||
|
||||
if(!ed) return;
|
||||
edict = PRVM_EDICT_NUM( ed->serialnumber );
|
||||
|
||||
// save matrix (fourth value will be reset on save\load)
|
||||
VectorCopy( transform[0], edict->progs.sv->m_pmatrix[0] );
|
||||
VectorCopy( transform[1], edict->progs.sv->m_pmatrix[1] );
|
||||
VectorCopy( transform[2], edict->progs.sv->m_pmatrix[2] );
|
||||
VectorCopy( transform[3], edict->progs.sv->m_pmatrix[3] );
|
||||
|
||||
MatrixLoadIdentity( objmatrix );
|
||||
VectorCopy( transform[0], objmatrix[0] );
|
||||
VectorCopy( transform[1], objmatrix[1] );
|
||||
VectorCopy( transform[2], objmatrix[2] );
|
||||
VectorCopy( transform[3], objmatrix[3] );
|
||||
MatrixAngles( objmatrix, origin, angles );
|
||||
|
||||
VectorCopy( origin, edict->progs.sv->origin );
|
||||
VectorCopy( angles, edict->progs.sv->angles );
|
||||
|
||||
// refresh force and torque
|
||||
pe->GetForce( ed->physbody, edict->progs.sv->velocity, edict->progs.sv->avelocity, edict->progs.sv->force, edict->progs.sv->torque );
|
||||
pe->GetMassCentre( ed->physbody, edict->progs.sv->m_pcentre );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SV_ClientMove
|
||||
|
||||
grab user cmd from player state
|
||||
send it to transform callback
|
||||
==============
|
||||
*/
|
||||
void SV_PlayerMove( sv_edict_t *ed )
|
||||
{
|
||||
pmove_t pm;
|
||||
sv_client_t *client;
|
||||
edict_t *player;
|
||||
|
||||
client = ed->client;
|
||||
player = PRVM_PROG_TO_EDICT( ed->serialnumber );
|
||||
memset( &pm, 0, sizeof(pm) );
|
||||
|
||||
if( player->progs.sv->movetype == MOVETYPE_NOCLIP )
|
||||
client->ps.pm_type = PM_SPECTATOR;
|
||||
else client->ps.pm_type = PM_NORMAL;
|
||||
client->ps.gravity = sv_gravity->value;
|
||||
|
||||
if( player->progs.sv->teleport_time )
|
||||
client->ps.pm_flags |= PMF_TIME_TELEPORT;
|
||||
else client->ps.pm_flags &= ~PMF_TIME_TELEPORT;
|
||||
|
||||
pm.ps = client->ps;
|
||||
pm.cmd = client->lastcmd;
|
||||
pm.body = ed->physbody; // member body ptr
|
||||
|
||||
VectorCopy( player->progs.sv->origin, pm.ps.origin );
|
||||
VectorCopy( player->progs.sv->velocity, pm.ps.velocity );
|
||||
|
||||
pe->PlayerMove( &pm, false ); // server move
|
||||
|
||||
// save results of pmove
|
||||
client->ps = pm.ps;
|
||||
|
||||
VectorCopy(pm.ps.origin, player->progs.sv->origin);
|
||||
VectorCopy(pm.ps.velocity, player->progs.sv->velocity);
|
||||
VectorCopy(pm.mins, player->progs.sv->mins);
|
||||
VectorCopy(pm.maxs, player->progs.sv->maxs);
|
||||
VectorCopy(pm.ps.viewangles, client->ps.viewangles);
|
||||
}
|
||||
|
||||
void SV_PlaySound( sv_edict_t *ed, float volume, const char *sample )
|
||||
{
|
||||
float vol = bound( 0.0f, volume/255.0f, 255.0f );
|
||||
int sound_idx = SV_SoundIndex( sample );
|
||||
edict_t *ent;
|
||||
if( !ed ) ed = prog->edicts->priv.sv;
|
||||
ent = PRVM_PROG_TO_EDICT( ed->serialnumber );
|
||||
|
||||
//SV_StartSound( ent->progs.sv->origin, ent, CHAN_BODY, sound_idx, vol, 1.0f, 0 );
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -101,6 +101,43 @@ void SV_SetMinMaxSize (edict_t *e, float *min, float *max, bool rotate)
|
|||
SV_LinkEdict (e);
|
||||
}
|
||||
|
||||
static trace_t SV_TraceToss( edict_t *tossent, edict_t *ignore)
|
||||
{
|
||||
int i;
|
||||
float gravity;
|
||||
vec3_t move, end;
|
||||
vec3_t original_origin;
|
||||
vec3_t original_velocity;
|
||||
vec3_t original_angles;
|
||||
vec3_t original_avelocity;
|
||||
trace_t trace;
|
||||
|
||||
VectorCopy( tossent->progs.sv->origin, original_origin );
|
||||
VectorCopy( tossent->progs.sv->velocity, original_velocity );
|
||||
VectorCopy( tossent->progs.sv->angles, original_angles );
|
||||
VectorCopy( tossent->progs.sv->avelocity, original_avelocity );
|
||||
gravity = tossent->progs.sv->gravity * sv_gravity->value * 0.05;
|
||||
|
||||
for( i = 0; i < 200; i++ )
|
||||
{
|
||||
// LordHavoc: sanity check; never trace more than 10 seconds
|
||||
SV_CheckVelocity( tossent );
|
||||
tossent->progs.sv->velocity[2] -= gravity;
|
||||
VectorMA( tossent->progs.sv->angles, 0.05, tossent->progs.sv->avelocity, tossent->progs.sv->angles );
|
||||
VectorScale( tossent->progs.sv->velocity, 0.05, move );
|
||||
VectorAdd( tossent->progs.sv->origin, move, end );
|
||||
trace = SV_Trace( tossent->progs.sv->origin, tossent->progs.sv->mins, tossent->progs.sv->maxs, end, MOVE_NORMAL, tossent, SV_ContentsMask( tossent ));
|
||||
VectorCopy( trace.endpos, tossent->progs.sv->origin );
|
||||
if( trace.fraction < 1 ) break;
|
||||
}
|
||||
VectorCopy( original_origin, tossent->progs.sv->origin );
|
||||
VectorCopy( original_velocity, tossent->progs.sv->velocity );
|
||||
VectorCopy( original_angles, tossent->progs.sv->angles );
|
||||
VectorCopy( original_avelocity, tossent->progs.sv->avelocity );
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
||||
void SV_CreatePhysBody( edict_t *ent )
|
||||
{
|
||||
if( !ent || ent->progs.sv->movetype != MOVETYPE_PHYSIC ) return;
|
||||
|
@ -339,7 +376,7 @@ void SV_WriteSaveFile( char *name )
|
|||
MsgDev(D_ERROR, "SV_WriteSaveFile: can't savegame in a deathmatch\n");
|
||||
return;
|
||||
}
|
||||
if(maxclients->integer == 1 && svs.clients[0].edict->priv.sv->client->ps.stats[STAT_HEALTH] <= 0)
|
||||
if( maxclients->integer == 1 && svs.clients[0].edict->progs.sv->health <= 0 )
|
||||
{
|
||||
MsgDev(D_ERROR, "SV_WriteSaveFile: can't savegame while dead!\n");
|
||||
return;
|
||||
|
@ -1305,7 +1342,7 @@ void PF_droptofloor( void )
|
|||
|
||||
VectorCopy( ent->progs.sv->origin, end );
|
||||
end[2] -= 256;
|
||||
trace = SV_Trace(ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, MASK_SOLID );
|
||||
trace = SV_Trace(ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, end, MOVE_NORMAL, ent, MASK_SOLID );
|
||||
|
||||
if( trace.startsolid )
|
||||
{
|
||||
|
@ -1368,7 +1405,7 @@ void PF_walkmove( void )
|
|||
oldf = prog->xfunction;
|
||||
oldpev = prog->globals.sv->pev;
|
||||
|
||||
PRVM_G_FLOAT(OFS_RETURN) = SV_MoveStep( ent, move, true );
|
||||
PRVM_G_FLOAT(OFS_RETURN) = SV_movestep( ent, move, true, false, true );
|
||||
|
||||
// restore program state
|
||||
prog->xfunction = oldf;
|
||||
|
@ -1538,7 +1575,7 @@ void PF_traceline( void )
|
|||
PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n",
|
||||
PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], mask, PRVM_EDICT_TO_PROG(ent));
|
||||
|
||||
trace = SV_Trace( v1, vec3_origin, vec3_origin, v2, ent, mask );
|
||||
trace = SV_Trace( v1, vec3_origin, vec3_origin, v2, MOVE_NORMAL, ent, mask );
|
||||
|
||||
prog->globals.sv->trace_allsolid = trace.allsolid;
|
||||
prog->globals.sv->trace_startsolid = trace.startsolid;
|
||||
|
@ -1624,7 +1661,7 @@ void PF_tracebox( void )
|
|||
PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n",
|
||||
PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], mask, PRVM_EDICT_TO_PROG(ent));
|
||||
|
||||
trace = SV_Trace (v1, m1, m2, v2, ent, mask );
|
||||
trace = SV_Trace (v1, m1, m2, v2, MOVE_NORMAL, ent, mask );
|
||||
|
||||
prog->globals.sv->trace_allsolid = trace.allsolid;
|
||||
prog->globals.sv->trace_startsolid = trace.startsolid;
|
||||
|
@ -1678,7 +1715,7 @@ void PF_aim( void )
|
|||
// try sending a trace straight
|
||||
VectorCopy(prog->globals.sv->v_forward, dir);
|
||||
VectorMA(start, 2048, dir, end);
|
||||
tr = SV_Trace( start, vec3_origin, vec3_origin, end, ent, MASK_ALL );
|
||||
tr = SV_Trace( start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, MASK_ALL );
|
||||
|
||||
if( tr.ent && ((edict_t *)tr.ent)->progs.sv->takedamage == 2 && (flags & DF_NO_FRIENDLY_FIRE
|
||||
|| ent->progs.sv->team <=0 || ent->progs.sv->team != ((edict_t *)tr.ent)->progs.sv->team))
|
||||
|
@ -1707,7 +1744,7 @@ void PF_aim( void )
|
|||
VectorNormalize (dir);
|
||||
dist = DotProduct (dir, prog->globals.sv->v_forward);
|
||||
if (dist < bestdist) continue; // to far to turn
|
||||
tr = SV_Trace (start, vec3_origin, vec3_origin, end, ent, MASK_ALL );
|
||||
tr = SV_Trace (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, MASK_ALL );
|
||||
if (tr.ent == check)
|
||||
{
|
||||
// can shoot at this one
|
||||
|
@ -1856,7 +1893,7 @@ float pointcontents( vector v )
|
|||
void PF_pointcontents( void )
|
||||
{
|
||||
if(!VM_ValidateArgs( "pointcontents", 1 )) return;
|
||||
PRVM_G_FLOAT(OFS_RETURN) = SV_PointContents(PRVM_G_VECTOR(OFS_PARM0), NULL );
|
||||
PRVM_G_FLOAT(OFS_RETURN) = SV_PointContents(PRVM_G_VECTOR(OFS_PARM0));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2000,70 +2037,6 @@ void PF_AreaPortalState( void )
|
|||
pe->SetAreaPortalState((int)PRVM_G_FLOAT(OFS_PARM0), (bool)PRVM_G_FLOAT(OFS_PARM1));
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
PF_setstats
|
||||
|
||||
void setstats( entity client, float stat, string value )
|
||||
=================
|
||||
*/
|
||||
void PF_setstats( void )
|
||||
{
|
||||
edict_t *e;
|
||||
int stat_num;
|
||||
const char *string;
|
||||
short value;
|
||||
|
||||
if(!VM_ValidateArgs( "setstats", 3 )) return;
|
||||
e = PRVM_G_EDICT(OFS_PARM0);
|
||||
if(!e->priv.sv->client)
|
||||
{
|
||||
VM_Warning("setstats: stats applied only for players\n");
|
||||
return;
|
||||
}
|
||||
|
||||
stat_num = (int)PRVM_G_FLOAT(OFS_PARM1);
|
||||
if(stat_num < 0 || stat_num > MAX_STATS)
|
||||
{
|
||||
VM_Warning("setstats: invalid stats number\n");
|
||||
return;
|
||||
}
|
||||
string = PRVM_G_STRING(OFS_PARM2);
|
||||
|
||||
switch(stat_num)
|
||||
{
|
||||
case STAT_ZOOM:
|
||||
case STAT_SPEED:
|
||||
case STAT_CHASE:
|
||||
case STAT_HELPICON:
|
||||
case STAT_AMMO_ICON:
|
||||
case STAT_ARMOR_ICON:
|
||||
case STAT_TIMER_ICON:
|
||||
case STAT_HEALTH_ICON:
|
||||
case STAT_PICKUP_ICON:
|
||||
case STAT_SELECTED_ICON:
|
||||
case STAT_SELECTED_ITEM:
|
||||
value = SV_ImageIndex( string );
|
||||
break;
|
||||
case STAT_AMMO:
|
||||
case STAT_FRAGS:
|
||||
case STAT_TIMER:
|
||||
case STAT_ARMOR:
|
||||
case STAT_HEALTH:
|
||||
case STAT_FLASHES:
|
||||
case STAT_LAYOUTS:
|
||||
case STAT_SPECTATOR:
|
||||
value = (short)com.atoi( string );
|
||||
break;
|
||||
default:
|
||||
MsgDev( D_WARN, "unknown stat type %d\n", stat_num );
|
||||
return;
|
||||
}
|
||||
|
||||
// refresh stats
|
||||
e->priv.sv->client->ps.stats[stat_num] = value;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
PF_InfoPrint
|
||||
|
@ -2379,7 +2352,7 @@ NULL, // #164 setView
|
|||
NULL, // #165 crosshairangle
|
||||
PF_AreaPortalState, // #166 void areaportal( float num, float state )
|
||||
NULL, // #167 compareFileTime
|
||||
PF_setstats, // #168 void setstats(entity e, float f, string stats)
|
||||
NULL, // #168
|
||||
PF_InfoPrint, // #169 void Info_Print( entity client )
|
||||
PF_InfoValueForKey, // #170 string Info_ValueForKey( entity client, string key )
|
||||
PF_InfoRemoveKey, // #171 void Info_RemoveKey( entity client, string key )
|
||||
|
@ -2472,6 +2445,9 @@ void SV_InitServerProgs( void )
|
|||
prog->error_cmd = VM_Error;
|
||||
PRVM_LoadProgs( va("%s/server.dat", GI->vprogs_dir ), 0, NULL, SV_NUM_REQFIELDS, sv_reqfields );
|
||||
}
|
||||
|
||||
// try to get custom movement function from qc code
|
||||
svs.ClientMove = PRVM_ED_FindFunctionOffset( "ClientMove" );
|
||||
PRVM_End;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,13 @@ edict_t *pm_passent;
|
|||
void PM_trace( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, trace_t *tr )
|
||||
{
|
||||
if( pm_passent->progs.sv->health > 0 )
|
||||
*tr = SV_Trace (start, mins, maxs, end, pm_passent, MASK_PLAYERSOLID );
|
||||
*tr = SV_Trace (start, mins, maxs, end, pm_passent, MASK_DEADSOLID );
|
||||
*tr = SV_Trace (start, mins, maxs, end, MOVE_NORMAL, pm_passent, MASK_PLAYERSOLID );
|
||||
*tr = SV_Trace (start, mins, maxs, end, MOVE_NORMAL, pm_passent, MASK_DEADSOLID );
|
||||
}
|
||||
|
||||
int PM_pointcontents( vec3_t point )
|
||||
{
|
||||
return SV_PointContents( point, pm_passent );
|
||||
return SV_PointContents( point );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -25,10 +25,7 @@ SV_TouchTriggers
|
|||
void SV_TouchTriggers (edict_t *ent)
|
||||
{
|
||||
int i, num;
|
||||
edict_t **touch, *hit;
|
||||
|
||||
// list of pointers, not data
|
||||
touch = Z_Malloc( sizeof(*touch) * host.max_edicts );
|
||||
edict_t *touch[MAX_EDICTS], *hit;
|
||||
|
||||
// dead things don't activate triggers!
|
||||
if ((ent->priv.sv->client || ((int)ent->progs.sv->flags & FL_MONSTER)) && (ent->progs.sv->health <= 0))
|
||||
|
@ -53,7 +50,6 @@ void SV_TouchTriggers (edict_t *ent)
|
|||
PRVM_ExecuteProgram (hit->progs.sv->touch, "pev->touch");
|
||||
}
|
||||
}
|
||||
Mem_Free( touch );
|
||||
|
||||
// restore state
|
||||
PRVM_POP_GLOBALS;
|
||||
|
@ -72,7 +68,7 @@ SV_CalcRoll
|
|||
|
||||
===============
|
||||
*/
|
||||
float SV_CalcRoll (vec3_t angles, vec3_t velocity)
|
||||
static float SV_CalcRoll (vec3_t angles, vec3_t velocity)
|
||||
{
|
||||
float sign;
|
||||
float side;
|
||||
|
@ -91,50 +87,6 @@ float SV_CalcRoll (vec3_t angles, vec3_t velocity)
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SV_CalcGunOffset
|
||||
==============
|
||||
*/
|
||||
void SV_CalcGunOffset( edict_t *ent )
|
||||
{
|
||||
int i;
|
||||
float delta;
|
||||
|
||||
// gun angles from bobbing
|
||||
ent->priv.sv->client->ps.vmodel.angles[ROLL] = xyspeed * bobfracsin * 0.005;
|
||||
ent->priv.sv->client->ps.vmodel.angles[YAW] = xyspeed * bobfracsin * 0.01;
|
||||
if( bobcycle & 1 )
|
||||
{
|
||||
ent->priv.sv->client->ps.vmodel.angles[ROLL] = -ent->priv.sv->client->ps.vmodel.angles[ROLL];
|
||||
ent->priv.sv->client->ps.vmodel.angles[YAW] = -ent->priv.sv->client->ps.vmodel.angles[YAW];
|
||||
}
|
||||
ent->priv.sv->client->ps.vmodel.angles[PITCH] = xyspeed * bobfracsin * 0.005;
|
||||
|
||||
// gun angles from delta movement
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
delta = ent->priv.sv->client->ps.oldviewangles[i] - ent->priv.sv->client->ps.viewangles[i];
|
||||
if( delta > 180 ) delta -= 360;
|
||||
if( delta < -180 ) delta += 360;
|
||||
if( delta > 45 ) delta = 45;
|
||||
if( delta < -45 ) delta = -45;
|
||||
if( i == YAW ) ent->priv.sv->client->ps.vmodel.angles[ROLL] += 0.1f * delta;
|
||||
ent->priv.sv->client->ps.vmodel.angles[i] += 0.2 * delta;
|
||||
}
|
||||
|
||||
// gun height
|
||||
VectorClear( ent->priv.sv->client->ps.vmodel.offset );
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
ent->priv.sv->client->ps.vmodel.offset[i] += forward[i];
|
||||
ent->priv.sv->client->ps.vmodel.offset[i] += right[i];
|
||||
ent->priv.sv->client->ps.vmodel.offset[i] += up[i] * -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SV_CalcViewOffset (edict_t *ent)
|
||||
{
|
||||
float *angles;
|
||||
|
@ -143,7 +95,7 @@ void SV_CalcViewOffset (edict_t *ent)
|
|||
vec3_t v;
|
||||
|
||||
// base angles
|
||||
angles = ent->priv.sv->client->ps.kick_angles;
|
||||
angles = ent->priv.sv->client->ps.punch_angles;
|
||||
|
||||
VectorCopy(ent->progs.sv->punchangle, angles);
|
||||
// add angles based on velocity
|
||||
|
@ -180,14 +132,9 @@ void SV_CalcViewOffset (edict_t *ent)
|
|||
VectorCopy( v, ent->priv.sv->client->ps.viewoffset );
|
||||
}
|
||||
|
||||
void SV_SetStats (edict_t *ent)
|
||||
{
|
||||
ent->priv.sv->client->ps.stats[STAT_HEALTH] = ent->progs.sv->health;
|
||||
}
|
||||
|
||||
void ClientEndServerFrame (edict_t *ent)
|
||||
{
|
||||
float bobtime;
|
||||
float bobtime = 0;
|
||||
|
||||
current_player = ent;
|
||||
current_client = ent->priv.sv->client;
|
||||
|
@ -222,11 +169,7 @@ void ClientEndServerFrame (edict_t *ent)
|
|||
//
|
||||
xyspeed = sqrt(ent->progs.sv->velocity[0] * ent->progs.sv->velocity[0] + ent->progs.sv->velocity[1] * ent->progs.sv->velocity[1]);
|
||||
|
||||
if (xyspeed < 5)
|
||||
{
|
||||
bobmove = 0;
|
||||
current_client->ps.bobtime = 0; // start at beginning of cycle again
|
||||
}
|
||||
if( xyspeed < 5 ) bobmove = 0;
|
||||
else if (ent->progs.sv->groundentity)
|
||||
{
|
||||
// so bobbing only cycles when on ground
|
||||
|
@ -235,7 +178,7 @@ void ClientEndServerFrame (edict_t *ent)
|
|||
else bobmove = 0.0625;
|
||||
}
|
||||
|
||||
bobtime = (current_client->ps.bobtime += bobmove);
|
||||
bobtime += bobmove;
|
||||
|
||||
if (current_client->ps.pm_flags & PMF_DUCKED)
|
||||
bobtime *= 4;
|
||||
|
@ -245,16 +188,6 @@ void ClientEndServerFrame (edict_t *ent)
|
|||
|
||||
// determine the view offsets
|
||||
SV_CalcViewOffset (ent);
|
||||
|
||||
// determine the gun offsets
|
||||
SV_CalcGunOffset (ent);
|
||||
|
||||
SV_SetStats( ent );
|
||||
|
||||
// if the scoreboard is up, update it
|
||||
if (!(sv.framenum & 31))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -284,110 +217,8 @@ Advances the world by 0.1 seconds
|
|||
*/
|
||||
void SV_RunFrame( void )
|
||||
{
|
||||
int i;
|
||||
edict_t *ent;
|
||||
|
||||
// let the progs know that a new frame has started
|
||||
prog->globals.sv->pev = PRVM_EDICT_TO_PROG(prog->edicts);
|
||||
prog->globals.sv->other = PRVM_EDICT_TO_PROG(prog->edicts);
|
||||
prog->globals.sv->time = sv.time;
|
||||
prog->globals.sv->frametime = sv.frametime;
|
||||
PRVM_ExecuteProgram (prog->globals.sv->StartFrame, "StartFrame");
|
||||
|
||||
for (i = 1; i < prog->num_edicts; i++ )
|
||||
{
|
||||
ent = PRVM_EDICT_NUM(i);
|
||||
if (ent->priv.sv->free) continue;
|
||||
|
||||
VectorCopy (ent->progs.sv->origin, ent->progs.sv->old_origin);
|
||||
|
||||
// don't apply phys on clients
|
||||
if (i > 0 && i <= maxclients->value) continue;
|
||||
SV_Physics( ent );
|
||||
}
|
||||
|
||||
// build the playerstate_t structures for all players
|
||||
ClientEndServerFrames ();
|
||||
|
||||
prog->globals.sv->pev = PRVM_EDICT_TO_PROG(prog->edicts);
|
||||
prog->globals.sv->other = PRVM_EDICT_TO_PROG(prog->edicts);
|
||||
prog->globals.sv->time = sv.time;
|
||||
PRVM_ExecuteProgram (prog->globals.sv->EndFrame, "EndFrame");
|
||||
|
||||
// decrement prog->num_edicts if the highest number entities died
|
||||
for ( ;PRVM_EDICT_NUM(prog->num_edicts - 1)->priv.sv->free; prog->num_edicts-- );
|
||||
}
|
||||
|
||||
bool SV_ClientConnect (edict_t *ent, char *userinfo)
|
||||
{
|
||||
// they can connect
|
||||
ent->progs.sv->flags = 0; // make sure we start with known default
|
||||
ent->progs.sv->health = 100;
|
||||
|
||||
MsgDev(D_NOTE, "SV_ClientConnect()\n");
|
||||
prog->globals.sv->time = sv.time;
|
||||
prog->globals.sv->pev = PRVM_EDICT_TO_PROG(ent);
|
||||
PRVM_ExecuteProgram (prog->globals.sv->ClientConnect, "ClientConnect");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SV_ClientUserinfoChanged (edict_t *ent, char *userinfo)
|
||||
{
|
||||
char *s;
|
||||
int playernum;
|
||||
|
||||
// check for malformed or illegal info strings
|
||||
if (!Info_Validate(userinfo))
|
||||
{
|
||||
strcpy (userinfo, "\\name\\badinfo\\skin\\male/grunt");
|
||||
}
|
||||
|
||||
// set skin
|
||||
s = Info_ValueForKey (userinfo, "skin");
|
||||
|
||||
playernum = PRVM_NUM_FOR_EDICT(ent);
|
||||
|
||||
// combine name and skin into a configstring
|
||||
SV_ConfigString (CS_PLAYERSKINS + playernum, va("%s\\%s", Info_ValueForKey (userinfo, "name"), Info_ValueForKey (userinfo, "skin")));
|
||||
|
||||
ent->priv.sv->client->ps.fov = bound(1, atoi(Info_ValueForKey(userinfo, "fov")), 160);
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
SV_ClientBegin
|
||||
|
||||
called when a client has finished connecting, and is ready
|
||||
to be placed into the game. This will happen every level load.
|
||||
============
|
||||
*/
|
||||
void SV_ClientBegin (edict_t *ent)
|
||||
{
|
||||
int i;
|
||||
|
||||
// if there is already a body waiting for us (a loadgame), just
|
||||
// take it, otherwise spawn one from scratch
|
||||
if (ent->priv.sv->free)
|
||||
{
|
||||
// the client has cleared the client side viewangles upon
|
||||
// connecting to the server, which is different than the
|
||||
// state when the game is saved, so we need to compensate
|
||||
// with deltaangles
|
||||
for (i = 0; i < 3; i++)
|
||||
ent->priv.sv->client->ps.delta_angles[i] = ANGLE2SHORT(ent->priv.sv->client->ps.viewangles[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// a spawn point will completely reinitialize the entity
|
||||
// except for the persistant data that was initialized at
|
||||
// ClientConnect() time
|
||||
SV_InitEdict (ent);
|
||||
SV_PutClientInServer (ent);
|
||||
}
|
||||
|
||||
// make sure all view stuff is valid
|
||||
ClientEndServerFrame (ent);
|
||||
;
|
||||
//ClientEndServerFrames();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -461,8 +292,8 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
|
|||
VectorCopy(pm.maxs, ent->progs.sv->maxs);
|
||||
VectorCopy(pm.ps.viewangles, ent->progs.sv->v_angle);
|
||||
VectorCopy(pm.ps.viewangles, ent->progs.sv->angles);
|
||||
if( pm.ps.groundentity )
|
||||
ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG( pm.ps.groundentity );
|
||||
if( pm.groundentity )
|
||||
ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG( pm.groundentity );
|
||||
else ent->progs.sv->groundentity = 0;
|
||||
|
||||
// copy viewmodel info
|
||||
|
@ -470,8 +301,6 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
|
|||
client->ps.vmodel.body = ent->progs.sv->v_body;
|
||||
client->ps.vmodel.skin = ent->progs.sv->v_skin;
|
||||
client->ps.vmodel.sequence = ent->progs.sv->v_sequence;
|
||||
VectorCopy(ent->progs.sv->v_offset, client->ps.vmodel.offset );
|
||||
VectorCopy(ent->progs.sv->v_angles, client->ps.vmodel.angles );
|
||||
|
||||
SV_LinkEdict(ent);
|
||||
|
||||
|
@ -506,31 +335,6 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
|
|||
PRVM_ExecuteProgram (prog->globals.sv->PlayerPostThink, "PlayerPostThink");
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
SV_ClientDisconnect
|
||||
|
||||
Called when a player drops from the server.
|
||||
Will not be called between levels.
|
||||
============
|
||||
*/
|
||||
void SV_ClientDisconnect (edict_t *ent)
|
||||
{
|
||||
int playernum;
|
||||
|
||||
if (!ent->priv.sv->client) return;
|
||||
|
||||
SV_UnlinkEdict(ent);
|
||||
ent->progs.sv->modelindex = 0;
|
||||
ent->progs.sv->solid = SOLID_NOT;
|
||||
ent->priv.sv->free = true;
|
||||
ent->progs.sv->classname = PRVM_SetEngineString("disconnected");
|
||||
|
||||
playernum = PRVM_NUM_FOR_EDICT(ent) - 1;
|
||||
SV_ConfigString (CS_PLAYERSKINS + playernum, "");
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_StartParticle
|
||||
|
@ -538,203 +342,7 @@ SV_StartParticle
|
|||
Make sure the event gets sent to all clients
|
||||
==================
|
||||
*/
|
||||
void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count)
|
||||
void SV_StartParticle( vec3_t org, vec3_t dir, int color, int count )
|
||||
{
|
||||
MsgDev( D_ERROR, "SV_StartParticle: implement me\n");
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
PF_cprintf
|
||||
|
||||
Print to a single client
|
||||
===============
|
||||
*/
|
||||
void PF_cprintf (edict_t *ent, int level, char *fmt, ...)
|
||||
{
|
||||
char msg[1024];
|
||||
va_list argptr;
|
||||
int n;
|
||||
|
||||
if (ent)
|
||||
{
|
||||
n = PRVM_NUM_FOR_EDICT(ent);
|
||||
if (n < 1 || n > maxclients->value)
|
||||
Host_Error("cprintf to a non-client\n");
|
||||
}
|
||||
|
||||
va_start (argptr,fmt);
|
||||
com.vsprintf (msg, fmt, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (ent) SV_ClientPrintf (svs.clients+(n-1), level, "%s", msg);
|
||||
else Msg ("%s", msg);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Cmd_Say_f
|
||||
==================
|
||||
*/
|
||||
void Cmd_Say_f (edict_t *ent, bool team, bool arg0)
|
||||
{
|
||||
int j;
|
||||
edict_t *other;
|
||||
char *p;
|
||||
char text[2048];
|
||||
|
||||
if (Cmd_Argc () < 2 && !arg0) return;
|
||||
|
||||
com.sprintf (text, "%s: ", "all");
|
||||
|
||||
if (arg0)
|
||||
{
|
||||
strcat (text, Cmd_Argv(0));
|
||||
strcat (text, " ");
|
||||
strcat (text, Cmd_Args());
|
||||
}
|
||||
else
|
||||
{
|
||||
p = Cmd_Args();
|
||||
|
||||
if (*p == '"')
|
||||
{
|
||||
p++;
|
||||
p[strlen(p)-1] = 0;
|
||||
}
|
||||
strcat(text, p);
|
||||
}
|
||||
|
||||
// don't let text be too long for malicious reasons
|
||||
if (strlen(text) > 150) text[150] = 0;
|
||||
|
||||
com.strcat(text, "\n");
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
PF_cprintf(NULL, PRINT_CHAT, "%s", text);
|
||||
|
||||
for (j = 1; j <= maxclients->value; j++)
|
||||
{
|
||||
other = PRVM_EDICT_NUM(j);
|
||||
if (other->priv.sv->free) continue;
|
||||
if (!other->priv.sv->client) continue;
|
||||
PF_cprintf(other, PRINT_CHAT, "%s", text);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_ClientCommand
|
||||
=================
|
||||
*/
|
||||
void SV_ClientCommand (edict_t *ent)
|
||||
{
|
||||
char *cmd;
|
||||
char *parm;
|
||||
|
||||
if (!ent->priv.sv->client) return; // not fully in game yet
|
||||
|
||||
cmd = Cmd_Argv(0);
|
||||
|
||||
if(Cmd_Argc() < 2) parm = NULL;
|
||||
else parm = Cmd_Argv(1);
|
||||
|
||||
if (strcasecmp (cmd, "say") == 0)
|
||||
{
|
||||
Cmd_Say_f (ent, false, false);
|
||||
return;
|
||||
}
|
||||
if (strcasecmp (cmd, "say_team") == 0)
|
||||
{
|
||||
Cmd_Say_f (ent, true, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void SV_Transform( sv_edict_t *ed, matrix4x3 transform )
|
||||
{
|
||||
edict_t *edict;
|
||||
vec3_t origin, angles;
|
||||
matrix4x4 objmatrix;
|
||||
|
||||
if(!ed) return;
|
||||
edict = PRVM_EDICT_NUM( ed->serialnumber );
|
||||
|
||||
// save matrix (fourth value will be reset on save\load)
|
||||
VectorCopy( transform[0], edict->progs.sv->m_pmatrix[0] );
|
||||
VectorCopy( transform[1], edict->progs.sv->m_pmatrix[1] );
|
||||
VectorCopy( transform[2], edict->progs.sv->m_pmatrix[2] );
|
||||
VectorCopy( transform[3], edict->progs.sv->m_pmatrix[3] );
|
||||
|
||||
MatrixLoadIdentity( objmatrix );
|
||||
VectorCopy( transform[0], objmatrix[0] );
|
||||
VectorCopy( transform[1], objmatrix[1] );
|
||||
VectorCopy( transform[2], objmatrix[2] );
|
||||
VectorCopy( transform[3], objmatrix[3] );
|
||||
MatrixAngles( objmatrix, origin, angles );
|
||||
|
||||
VectorCopy( origin, edict->progs.sv->origin );
|
||||
VectorCopy( angles, edict->progs.sv->angles );
|
||||
|
||||
// refresh force and torque
|
||||
pe->GetForce( ed->physbody, edict->progs.sv->velocity, edict->progs.sv->avelocity, edict->progs.sv->force, edict->progs.sv->torque );
|
||||
pe->GetMassCentre( ed->physbody, edict->progs.sv->m_pcentre );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CV_ClientMove
|
||||
|
||||
grab user cmd from player_state_t
|
||||
send it to transform callback
|
||||
==============
|
||||
*/
|
||||
void SV_PlayerMove( sv_edict_t *ed )
|
||||
{
|
||||
pmove_t pm;
|
||||
sv_client_t *client;
|
||||
edict_t *player;
|
||||
|
||||
client = ed->client;
|
||||
player = PRVM_PROG_TO_EDICT( ed->serialnumber );
|
||||
memset( &pm, 0, sizeof(pm) );
|
||||
|
||||
if( player->progs.sv->movetype == MOVETYPE_NOCLIP )
|
||||
client->ps.pm_type = PM_SPECTATOR;
|
||||
else client->ps.pm_type = PM_NORMAL;
|
||||
client->ps.gravity = sv_gravity->value;
|
||||
|
||||
if( player->progs.sv->teleport_time )
|
||||
client->ps.pm_flags |= PMF_TIME_TELEPORT;
|
||||
else client->ps.pm_flags &= ~PMF_TIME_TELEPORT;
|
||||
|
||||
pm.ps = client->ps;
|
||||
pm.cmd = client->lastcmd;
|
||||
pm.body = ed->physbody; // member body ptr
|
||||
|
||||
VectorCopy( player->progs.sv->origin, pm.ps.origin );
|
||||
VectorCopy( player->progs.sv->velocity, pm.ps.velocity );
|
||||
|
||||
pe->ServerMove( &pm );
|
||||
|
||||
// save results of pmove
|
||||
client->ps = pm.ps;
|
||||
|
||||
VectorCopy(pm.ps.origin, player->progs.sv->origin);
|
||||
VectorCopy(pm.ps.velocity, player->progs.sv->velocity);
|
||||
VectorCopy(pm.mins, player->progs.sv->mins);
|
||||
VectorCopy(pm.maxs, player->progs.sv->maxs);
|
||||
VectorCopy(pm.ps.viewangles, client->ps.viewangles);
|
||||
}
|
||||
|
||||
void SV_PlaySound( sv_edict_t *ed, float volume, const char *sample )
|
||||
{
|
||||
float vol = bound( 0.0f, volume/255.0f, 255.0f );
|
||||
int sound_idx = SV_SoundIndex( sample );
|
||||
edict_t *ent;
|
||||
if( !ed ) ed = prog->edicts->priv.sv;
|
||||
ent = PRVM_PROG_TO_EDICT( ed->serialnumber );
|
||||
|
||||
//SV_StartSound( ent->progs.sv->origin, ent, CHAN_BODY, sound_idx, vol, 1.0f, 0 );
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2007 ©
|
||||
// sv_studio.c - cm inline studio
|
||||
//=======================================================================
|
||||
|
||||
#include "common.h"
|
||||
#include "server.h"
|
||||
|
||||
// g-cont: my stupid callbacks
|
||||
cmodel_t *SV_GetModelPtr( edict_t *ent )
|
||||
{
|
||||
return pe->RegisterModel( sv.configstrings[CS_MODELS + (int)ent->progs.sv->modelindex] );
|
||||
}
|
||||
|
||||
float *SV_GetModelVerts( sv_edict_t *ed, int *numvertices )
|
||||
{
|
||||
cmodel_t *cmod;
|
||||
edict_t *ent;
|
||||
|
||||
ent = PRVM_EDICT_NUM(ed->serialnumber);
|
||||
cmod = pe->RegisterModel( sv.configstrings[CS_MODELS + (int)ent->progs.sv->modelindex] );
|
||||
if( cmod )
|
||||
{
|
||||
int i = (int)ent->progs.sv->body;
|
||||
i = bound( 0, i, cmod->numbodies ); // make sure what body exist
|
||||
|
||||
if( cmod->physmesh[i].verts )
|
||||
{
|
||||
*numvertices = cmod->physmesh[i].numverts;
|
||||
return (float *)cmod->physmesh[i].verts;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -217,8 +217,8 @@ void SV_LinkEdict( edict_t *ent )
|
|||
}
|
||||
else
|
||||
{ // normal
|
||||
VectorAdd (ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->absmin);
|
||||
VectorAdd (ent->progs.sv->origin, ent->progs.sv->maxs, ent->progs.sv->absmax);
|
||||
VectorAdd( ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->absmin );
|
||||
VectorAdd( ent->progs.sv->origin, ent->progs.sv->maxs, ent->progs.sv->absmax );
|
||||
}
|
||||
|
||||
// because movement is clipped an epsilon away from an actual edge,
|
||||
|
@ -266,7 +266,7 @@ void SV_LinkEdict( edict_t *ent )
|
|||
|
||||
// store as many explicit clusters as we can
|
||||
sv_ent->num_clusters = 0;
|
||||
for (i = 0; i < num_leafs; i++)
|
||||
for( i = 0; i < num_leafs; i++ )
|
||||
{
|
||||
cluster = pe->LeafCluster( leafs[i] );
|
||||
if( cluster )
|
||||
|
@ -281,24 +281,24 @@ void SV_LinkEdict( edict_t *ent )
|
|||
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);
|
||||
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)
|
||||
if( ent->progs.sv->solid == SOLID_NOT || ent->progs.sv->solid >= SOLID_BOX )
|
||||
return;
|
||||
|
||||
// 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)
|
||||
if( node->axis == -1 ) break;
|
||||
if( ent->progs.sv->absmin[node->axis] > node->dist )
|
||||
node = node->children[0];
|
||||
else if (ent->progs.sv->absmax[node->axis] < node->dist)
|
||||
else if( ent->progs.sv->absmax[node->axis] < node->dist )
|
||||
node = node->children[1];
|
||||
else break; // crosses the node
|
||||
}
|
||||
|
@ -372,241 +372,4 @@ int SV_AreaEdicts( const vec3_t mins, const vec3_t maxs, edict_t **list, int max
|
|||
SV_AreaEdicts_r( sv_worldsectors, &ap );
|
||||
|
||||
return ap.count;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
typedef struct
|
||||
{
|
||||
vec3_t boxmins, boxmaxs;// enclose the test object along entire move
|
||||
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 )
|
||||
{
|
||||
int i, num;
|
||||
edict_t **touchlist, *touch;
|
||||
trace_t trace;
|
||||
cmodel_t *cmodel;
|
||||
float *origin, *angles;
|
||||
|
||||
// list of pointers, not data
|
||||
touchlist = Z_Malloc( sizeof(*touchlist) * host.max_edicts );
|
||||
num = SV_AreaEdicts( clip->boxmins, clip->boxmaxs, touchlist, host.max_edicts );
|
||||
|
||||
for( i = 0; i < num; i++ )
|
||||
{
|
||||
if( clip->trace.allsolid ) return;
|
||||
|
||||
touch = touchlist[i];
|
||||
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
|
||||
if (PRVM_PROG_TO_EDICT(clip->passedict->progs.sv->owner) == touch)
|
||||
continue; // don't clip against owner
|
||||
}
|
||||
|
||||
if(!(clip->contentmask & CONTENTS_DEADMONSTER) && ((int)touch->progs.sv->flags & FL_DEADMONSTER))
|
||||
continue;
|
||||
|
||||
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((float *)clip->start, (float *)clip->end, (float *)clip->mins, (float *)clip->maxs, cmodel, clip->contentmask, origin, angles, false );
|
||||
|
||||
if( trace.allsolid )
|
||||
{
|
||||
clip->trace.allsolid = true;
|
||||
trace.ent = touch;
|
||||
}
|
||||
else if( trace.startsolid )
|
||||
{
|
||||
clip->trace.startsolid = true;
|
||||
trace.ent = touch;
|
||||
}
|
||||
if( trace.fraction < clip->trace.fraction )
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
Mem_Free( touchlist );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_Trace
|
||||
|
||||
Moves the given mins/maxs volume through the world from start to end.
|
||||
passEntityNum and entities owned by passEntityNum are explicitly not checked.
|
||||
==================
|
||||
*/
|
||||
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 ));
|
||||
|
||||
// clip to world
|
||||
pe->BoxTrace( start, end, mins, maxs, NULL, &clip.trace, 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;
|
||||
VectorCopy( end, clip.end );
|
||||
clip.mins = mins;
|
||||
clip.maxs = maxs;
|
||||
clip.passedict = passedict;
|
||||
|
||||
// create the bounding box of the entire move
|
||||
// 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 );
|
||||
|
||||
return clip.trace;
|
||||
}
|
||||
|
||||
trace_t SV_TraceToss (edict_t *tossent, edict_t *ignore)
|
||||
{
|
||||
int i;
|
||||
float gravity = 1.0;
|
||||
vec3_t move, end;
|
||||
vec3_t original_origin;
|
||||
vec3_t original_velocity;
|
||||
vec3_t original_angles;
|
||||
vec3_t original_avelocity;
|
||||
trace_t trace;
|
||||
|
||||
VectorCopy(tossent->progs.sv->origin, original_origin);
|
||||
VectorCopy(tossent->progs.sv->velocity, original_velocity);
|
||||
VectorCopy(tossent->progs.sv->angles, original_angles);
|
||||
VectorCopy(tossent->progs.sv->avelocity, original_avelocity);
|
||||
|
||||
gravity *= sv_gravity->value * 0.05;
|
||||
|
||||
for (i = 0; i < 200; i++) // LordHavoc: sanity check; never trace more than 10 seconds
|
||||
{
|
||||
SV_CheckVelocity (tossent);
|
||||
tossent->progs.sv->velocity[2] -= gravity;
|
||||
VectorMA (tossent->progs.sv->angles, 0.05, tossent->progs.sv->avelocity, tossent->progs.sv->angles);
|
||||
VectorScale (tossent->progs.sv->velocity, 0.05, move);
|
||||
VectorAdd (tossent->progs.sv->origin, move, end);
|
||||
trace = SV_Trace(tossent->progs.sv->origin, tossent->progs.sv->mins, tossent->progs.sv->maxs, end, tossent, MASK_SOLID );
|
||||
VectorCopy (trace.endpos, tossent->progs.sv->origin);
|
||||
if (trace.fraction < 1) break;
|
||||
}
|
||||
|
||||
VectorCopy(original_origin, tossent->progs.sv->origin);
|
||||
VectorCopy(original_velocity, tossent->progs.sv->velocity);
|
||||
VectorCopy(original_angles, tossent->progs.sv->angles);
|
||||
VectorCopy(original_avelocity, tossent->progs.sv->avelocity);
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
||||
trace_t SV_ClipMoveToEntity(edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int 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, true );
|
||||
if( trace.fraction < 1.0f ) trace.ent = touch;
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
SV_PointContents
|
||||
=============
|
||||
*/
|
||||
int SV_PointContents( const vec3_t p, edict_t *passedict )
|
||||
{
|
||||
edict_t **touch, *hit;
|
||||
int i, num;
|
||||
int contents, c2;
|
||||
cmodel_t *cmodel;
|
||||
float *angles;
|
||||
|
||||
touch = Z_Malloc( sizeof(*touch) * host.max_edicts );
|
||||
|
||||
// get base contents from world
|
||||
contents = pe->PointContents( p, NULL );
|
||||
|
||||
// or in contents from all the other entities
|
||||
num = SV_AreaEdicts( p, p, touch, host.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;
|
||||
}
|
||||
Mem_Free( touch );
|
||||
|
||||
return contents;
|
||||
}
|
|
@ -10,11 +10,11 @@ byte *zonepool;
|
|||
int app_name = 0;
|
||||
cvar_t *img_resample_lerp;
|
||||
|
||||
void ImageLib_Init ( uint funcname )
|
||||
void ImageLib_Init ( void )
|
||||
{
|
||||
// init pools
|
||||
zonepool = Mem_AllocPool( "ImageLib Pool" );
|
||||
app_name = funcname;
|
||||
app_name = g_Instance;
|
||||
|
||||
img_resample_lerp = Cvar_Get( "img_lerping", "1", CVAR_SYSTEMINFO, "lerping images after resample" );
|
||||
}
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
Base Entry Point
|
||||
=================
|
||||
*/
|
||||
DLLEXPORT int CreateAPI( char *funcname, bool console )
|
||||
DLLEXPORT int CreateAPI( char *hostname, bool console )
|
||||
{
|
||||
// memeber name
|
||||
com_strncpy( Sys.progname, funcname, sizeof(Sys.progname));
|
||||
com_strncpy( Sys.progname, hostname, sizeof(Sys.progname));
|
||||
Sys.hooked_out = console; // set mode
|
||||
|
||||
Sys_Init();
|
||||
|
|
|
@ -27,7 +27,7 @@ static const char *show_credits = "\n\n\n\n\tCopyright XashXT Group 2007
|
|||
All Rights Reserved\n\n\t Visit www.xash.ru\n";
|
||||
|
||||
// stubs
|
||||
void NullInit( uint funcname, int argc, char **argv ) {}
|
||||
void NullInit( int argc, char **argv ) {}
|
||||
void NullFunc( void ) {}
|
||||
void Sys_NullPrint( const char *msg ) {}
|
||||
|
||||
|
@ -382,6 +382,9 @@ void Sys_LookupInstance( void )
|
|||
com_sprintf(Sys.log_path, "%s/source.log", sys_rootdir ); // default
|
||||
com_strcpy(Sys.caption, va("QuakeC Decompiler ver.%g", XASH_VERSION ));
|
||||
}
|
||||
|
||||
// share instance over all system
|
||||
GI.instance = Sys.app_name;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -443,7 +446,7 @@ void Sys_CreateInstance( void )
|
|||
}
|
||||
|
||||
// init our host now!
|
||||
Sys.Init( Sys.app_name, fs_argc, fs_argv );
|
||||
Sys.Init( fs_argc, fs_argv );
|
||||
|
||||
// post initializations
|
||||
switch(Sys.app_name)
|
||||
|
|
|
@ -68,7 +68,7 @@ typedef struct system_s
|
|||
double start, end;
|
||||
|
||||
void (*Con_Print)( const char *msg );
|
||||
void ( *Init ) ( uint funcname, int argc, char **argv );
|
||||
void ( *Init ) ( int argc, char **argv );
|
||||
void ( *Main ) ( void ); // host frame
|
||||
void ( *Free ) ( void ); // close host
|
||||
void (*CPrint)( const char *msg ); // console print
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
{ return CreateMain32()( #prog, FALSE ); }
|
||||
|
||||
// engine entry point format
|
||||
typedef int (*winmain_t)( char *funcname, int console );
|
||||
typedef int (*winmain_t)( char *hostname, int console );
|
||||
char szSearch[ 5 ][ 1024 ];
|
||||
char szFsPath[ 4096 ];
|
||||
HINSTANCE hmain;
|
||||
|
|
|
@ -1364,7 +1364,7 @@ void CM_CollisionClipTrace_Box( trace_t *trace, const vec3_t cmins, const vec3_t
|
|||
|
||||
//===========================================
|
||||
|
||||
void CM_CollisionClipToGenericEntity( trace_t *trace, cmodel_t *model, int frame, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4 matrix, matrix4x4 inversematrix, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask )
|
||||
void CM_CollisionClipToGenericEntity( trace_t *trace, cmodel_t *model, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4 matrix, matrix4x4 inversematrix, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask )
|
||||
{
|
||||
float tempnormal[3];
|
||||
float starttransformed[3];
|
||||
|
|
|
@ -59,9 +59,11 @@ typedef struct cbsp_s
|
|||
typedef struct cnode_s
|
||||
{
|
||||
// this part shared between node and leaf
|
||||
struct cnode_s *parent;
|
||||
cplane_t *plane; // always != NULL
|
||||
vec3_t mins;
|
||||
vec3_t maxs;
|
||||
int contents; // combined contents for node
|
||||
|
||||
// this part unique to node
|
||||
struct cnode_s *children[2];
|
||||
|
@ -70,16 +72,20 @@ typedef struct cnode_s
|
|||
typedef struct cleaf_s
|
||||
{
|
||||
// this part shared between node and leaf
|
||||
struct cnode_s *parent;
|
||||
cplane_t *plane; // always == NULL
|
||||
vec3_t mins;
|
||||
vec3_t maxs;
|
||||
int contents; // combined contents for leaf
|
||||
|
||||
// this part unique to leaf
|
||||
int contents;
|
||||
int cluster;
|
||||
int area;
|
||||
int firstleafbrush;
|
||||
bool havepatches; // leaf have collision patches (triangles)
|
||||
int *firstleafbrush;
|
||||
int numleafbrushes;
|
||||
int numleafsurfaces;
|
||||
int *firstleafsurface;
|
||||
} cleaf_t;
|
||||
|
||||
typedef struct
|
||||
|
@ -146,6 +152,7 @@ typedef struct clipmap_s
|
|||
cplane_t *planes; // 12 extra planes for box hull
|
||||
cleaf_t *leafs; // 1 extra leaf for box hull
|
||||
dword *leafbrushes;
|
||||
dword *leafsurfaces;
|
||||
cnode_t *nodes; // 6 extra planes for box hull
|
||||
dvertex_t *vertices;
|
||||
dedge_t *edges;
|
||||
|
@ -162,23 +169,20 @@ typedef struct clipmap_s
|
|||
carea_t *areas;
|
||||
dareaportal_t *areaportals;
|
||||
|
||||
csurface_t nullsurface;
|
||||
int numbrushsides;
|
||||
int numtexinfo;
|
||||
int numplanes;
|
||||
int numbmodels;
|
||||
int numnodes;
|
||||
int numleafs; // allow leaf funcs to be called without a map
|
||||
int emptyleaf;
|
||||
int solidleaf;
|
||||
int numleafbrushes;
|
||||
int numleafsurfaces;
|
||||
int numbrushes;
|
||||
int numfaces;
|
||||
int numareas;
|
||||
int numareaportals;
|
||||
int numclusters;
|
||||
int floodvalid;
|
||||
int num_models;
|
||||
|
||||
// misc stuff
|
||||
NewtonBody *body;
|
||||
|
@ -189,7 +193,6 @@ typedef struct clipmap_s
|
|||
collide_info_t touch_info; // global info about two touching objects
|
||||
bool loaded; // map is loaded?
|
||||
bool tree_build; // phys tree is created ?
|
||||
bool use_thread; // bsplib use thread
|
||||
vfile_t *world_tree; // pre-calcualated collision tree (worldmodel only)
|
||||
trace_t trace; // contains result of last trace
|
||||
int checkcount;
|
||||
|
@ -211,32 +214,14 @@ typedef struct studio_s
|
|||
matrix3x4 rotmatrix;
|
||||
matrix3x4 bones[MAXSTUDIOBONES];
|
||||
vec3_t vertices[MAXSTUDIOVERTS];
|
||||
vec3_t transform[MAXSTUDIOVERTS];
|
||||
vec3_t indices[MAXSTUDIOVERTS];
|
||||
vec3_t vtransform[MAXSTUDIOVERTS];
|
||||
vec3_t ntransform[MAXSTUDIOVERTS];
|
||||
vec3_t *m_pVerts; // pointer to studio.vertices array
|
||||
uint numtriangles;
|
||||
uint bodycount;
|
||||
} studio_t;
|
||||
|
||||
typedef struct convex_hull_s
|
||||
{
|
||||
vec3_t *m_pVerts; // pointer to studio.vertices array
|
||||
uint numverts;
|
||||
} convex_hull_t;
|
||||
|
||||
typedef struct box_s
|
||||
{
|
||||
cplane_t *planes;
|
||||
cbrush_t *brush;
|
||||
cmodel_t *model;
|
||||
} box_t;
|
||||
|
||||
typedef struct mapleaf_s
|
||||
{
|
||||
int count;
|
||||
int topnode;
|
||||
int maxcount;
|
||||
int *list;
|
||||
float *mins;
|
||||
float *maxs;
|
||||
} mapleaf_t;
|
||||
} studio_t;
|
||||
|
||||
typedef struct leaflist_s
|
||||
{
|
||||
|
@ -249,37 +234,8 @@ typedef struct leaflist_s
|
|||
void (*storeleafs)( struct leaflist_s *ll, cnode_t *node );
|
||||
} leaflist_t;
|
||||
|
||||
typedef struct sphere_s
|
||||
{
|
||||
bool use;
|
||||
float radius;
|
||||
float halfheight;
|
||||
vec3_t offset;
|
||||
} sphere_t;
|
||||
|
||||
typedef struct tracework_s
|
||||
{
|
||||
vec3_t start;
|
||||
vec3_t end;
|
||||
vec3_t mins;
|
||||
vec3_t maxs;
|
||||
vec3_t offsets[8]; // [signbits][x] = either size[0][x] or size[1][x]
|
||||
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; // origin of the model tracing through
|
||||
int contents; // trace contents
|
||||
bool ispoint; // optimized case
|
||||
trace_t result; // returned from trace call
|
||||
sphere_t sphere; // sphere for oriendted capsule collision
|
||||
} tracework_t;
|
||||
|
||||
extern clipmap_t cm;
|
||||
extern studio_t studio;
|
||||
extern convex_hull_t hull;
|
||||
extern box_t box;
|
||||
extern mapleaf_t leaf;
|
||||
extern tracework_t maptrace;
|
||||
extern physic_t ph;
|
||||
|
||||
extern cvar_t *cm_noareas;
|
||||
|
@ -354,13 +310,13 @@ void CM_CollisionTraceLineTriangleFloat( trace_t *trace, const vec3_t linestart,
|
|||
// entities, only colliding with SOLID_BSP entities (doors, lifts)
|
||||
//
|
||||
// passedict is excluded from clipping checks
|
||||
void CM_CollisionClipToGenericEntity( trace_t *trace, cmodel_t *model, int frame, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4 matrix, matrix4x4 inversematrix, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitcontentsmask );
|
||||
void CM_CollisionClipToGenericEntity( trace_t *trace, cmodel_t *model, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4 matrix, matrix4x4 inversematrix, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitcontentsmask );
|
||||
// like above but does not do a transform and does nothing if model is NULL
|
||||
void CM_CollisionClipToWorld( trace_t *trace, cmodel_t *model, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontents );
|
||||
// combines data from two traces:
|
||||
// merges contents flags, startsolid, allsolid, inwater
|
||||
// updates fraction, endpos, plane and surface info if new fraction is shorter
|
||||
void CM_CollisionCombineTraces( trace_t *cliptrace, const trace_t *trace, void *touch, bool is_bmodel );
|
||||
void CM_CollisionCombineTraces( trace_t *cliptrace, const trace_t *trace, edict_t *touch, bool is_bmodel );
|
||||
void CM_CollisionDrawForEachBrush( void );
|
||||
void CM_CollisionInit( void );
|
||||
|
||||
|
|
|
@ -7,10 +7,6 @@
|
|||
|
||||
clipmap_t cm;
|
||||
studio_t studio;
|
||||
convex_hull_t hull;
|
||||
box_t box;
|
||||
mapleaf_t leaf;
|
||||
tracework_t maptrace;
|
||||
|
||||
cvar_t *cm_noareas;
|
||||
cmodel_t *loadmodel;
|
||||
|
@ -86,8 +82,8 @@ CM_FreeModel
|
|||
void CM_FreeModel( cmodel_t *mod )
|
||||
{
|
||||
Mem_FreePool( &mod->mempool );
|
||||
memset(mod->physmesh, 0, MAXSTUDIOMODELS * sizeof(cmesh_t));
|
||||
memset(mod, 0, sizeof(*mod));
|
||||
memset( mod->col, 0, MAXSTUDIOMODELS * sizeof(*mod->col[0]));
|
||||
memset( mod, 0, sizeof(*mod));
|
||||
mod = NULL;
|
||||
}
|
||||
|
||||
|
@ -116,20 +112,26 @@ void BSP_CreateMeshBuffer( int modelnum )
|
|||
int flags;
|
||||
|
||||
// ignore world or bsplib instance
|
||||
if(cm.use_thread || modelnum < 1 || modelnum >= cm.num_models)
|
||||
if( app_name == COMP_BSPLIB || modelnum >= cm.numbmodels )
|
||||
return;
|
||||
|
||||
loadmodel = &cm.bmodels[modelnum];
|
||||
loadmodel->type = mod_brush;
|
||||
hull.m_pVerts = &studio.vertices[0]; // using studio vertex buffer for bmodels too
|
||||
hull.numverts = 0; // clear current count
|
||||
if( modelnum ) loadmodel->type = mod_brush;
|
||||
loadmodel->type = mod_static; // level static geometry
|
||||
loadmodel->TraceBox = CM_TraceBmodel;
|
||||
loadmodel->PointContents = CM_PointContents;
|
||||
|
||||
// because world loading collision tree from LUMP_COLLISION
|
||||
if( modelnum < 1 ) return;
|
||||
studio.m_pVerts = &studio.vertices[0]; // using studio vertex buffer for bmodels too
|
||||
studio.numverts = 0; // clear current count
|
||||
|
||||
for( d = 0, i = loadmodel->firstface; d < loadmodel->numfaces; i++, d++ )
|
||||
{
|
||||
vec3_t *face;
|
||||
|
||||
m_face = cm.surfaces + i;
|
||||
flags = cm.surfdesc[m_face->desc].flags;
|
||||
flags = cm.surfdesc[m_face->desc].surfaceflags;
|
||||
k = m_face->firstedge;
|
||||
|
||||
// sky is noclip for all physobjects
|
||||
|
@ -137,17 +139,19 @@ void BSP_CreateMeshBuffer( int modelnum )
|
|||
face = Mem_Alloc( loadmodel->mempool, m_face->numedges * sizeof(vec3_t));
|
||||
for(j = 0; j < m_face->numedges; j++ )
|
||||
{
|
||||
CM_GetPoint2( k+j, hull.m_pVerts[hull.numverts] );
|
||||
hull.numverts++;
|
||||
// because it's not a collision tree, just triangle mesh
|
||||
CM_GetPoint2( k+j, studio.m_pVerts[studio.numverts] );
|
||||
studio.numverts++;
|
||||
}
|
||||
if( face ) Mem_Free( face ); // faces with 0 edges ?
|
||||
}
|
||||
if( hull.numverts )
|
||||
if( studio.numverts )
|
||||
{
|
||||
// grab vertices
|
||||
loadmodel->physmesh[loadmodel->numbodies].verts = Mem_Alloc( loadmodel->mempool, hull.numverts * sizeof(vec3_t));
|
||||
Mem_Copy( loadmodel->physmesh[loadmodel->numbodies].verts, hull.m_pVerts, hull.numverts * sizeof(vec3_t));
|
||||
loadmodel->physmesh[loadmodel->numbodies].numverts = hull.numverts;
|
||||
loadmodel->col[loadmodel->numbodies] = (cmesh_t *)Mem_Alloc( loadmodel->mempool, sizeof(*loadmodel->col[0]));
|
||||
loadmodel->col[loadmodel->numbodies]->verts = Mem_Alloc( loadmodel->mempool, studio.numverts * sizeof(vec3_t));
|
||||
Mem_Copy( loadmodel->col[loadmodel->numbodies]->verts, studio.m_pVerts, studio.numverts * sizeof(vec3_t));
|
||||
loadmodel->col[loadmodel->numbodies]->numverts = studio.numverts;
|
||||
loadmodel->numbodies++;
|
||||
}
|
||||
}
|
||||
|
@ -159,15 +163,15 @@ void BSP_LoadModels( lump_t *l )
|
|||
int i, j, n, c, count;
|
||||
|
||||
in = (void *)(cm.mod_base + l->fileofs);
|
||||
if (l->filelen % sizeof(*in)) Host_Error("CMod_LoadModels: funny lump size\n");
|
||||
if (l->filelen % sizeof(*in)) Host_Error("BSP_LoadModels: funny lump size\n");
|
||||
count = l->filelen / sizeof(*in);
|
||||
|
||||
if(count < 1) Host_Error("Map %s without models\n", cm.name );
|
||||
if(count > MAX_MODELS ) Host_Error("Map %s has too many models\n", cm.name );
|
||||
cm.numbmodels = cm.num_models = count;
|
||||
cm.numbmodels = count;
|
||||
out = &cm.bmodels[0];
|
||||
|
||||
for ( i = 0; i < count; i++, in++, out++)
|
||||
for ( i = 0; i < count; i++, in++, out++ )
|
||||
{
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
|
@ -175,14 +179,23 @@ void BSP_LoadModels( lump_t *l )
|
|||
out->mins[j] = LittleFloat(in->mins[j]) - 1;
|
||||
out->maxs[j] = LittleFloat(in->maxs[j]) + 1;
|
||||
}
|
||||
|
||||
// FIXME: calc bounding box right
|
||||
VectorCopy( out->mins, out->normalmins );
|
||||
VectorCopy( out->maxs, out->normalmaxs );
|
||||
VectorCopy( out->mins, out->rotatedmins );
|
||||
VectorCopy( out->maxs, out->rotatedmaxs );
|
||||
VectorCopy( out->mins, out->yawmins );
|
||||
VectorCopy( out->maxs, out->yawmaxs );
|
||||
|
||||
out->firstface = n = LittleLong( in->firstface );
|
||||
out->numfaces = c = LittleLong( in->numfaces );
|
||||
if( n < 0 || n + c > cm.numfaces )
|
||||
Host_Error("BSP_LoadModels: invalid face range %i : %i (%i faces)", n, n+c, cm.numfaces );
|
||||
Host_Error("BSP_LoadModels: invalid face range %i : %i (%i faces)\n", n, n+c, cm.numfaces );
|
||||
out->firstbrush = n = LittleLong( in->firstbrush );
|
||||
out->numbrushes = c = LittleLong( in->numbrushes );
|
||||
if( n < 0 || n + c > cm.numbrushes )
|
||||
Host_Error("BSP_LoadModels: invalid brush range %i : %i (%i brushes)", n, n+c, cm.numfaces );
|
||||
Host_Error("BSP_LoadModels: invalid brush range %i : %i (%i brushes)\n", n, n+c, cm.numfaces );
|
||||
com.strncpy( out->name, va("*%i", i ), sizeof(out->name));
|
||||
out->mempool = Mem_AllocPool( out->name );
|
||||
BSP_CreateMeshBuffer( i ); // bsp physic
|
||||
|
@ -209,9 +222,13 @@ void BSP_LoadSurfDesc( lump_t *l )
|
|||
|
||||
for ( i = 0; i < count; i++, in++, out++)
|
||||
{
|
||||
com.strncpy(out->name, CM_GetStringFromTable(LittleLong( in->texid )), MAX_STRING );
|
||||
out->flags = LittleLong( in->flags );
|
||||
com.strncpy( out->name, CM_GetStringFromTable(LittleLong( in->texid )), MAX_STRING );
|
||||
out->surfaceflags = LittleLong( in->flags );
|
||||
out->contentflags = 0;//FIXME: upgrade BSP version, that include contents for all sides
|
||||
out->value = LittleLong( in->value );
|
||||
// currently not used
|
||||
VectorClear( out->mins );
|
||||
VectorClear( out->maxs );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -227,7 +244,7 @@ void BSP_LoadNodes( lump_t *l )
|
|||
int i, j, n, count;
|
||||
|
||||
in = (void *)(cm.mod_base + l->fileofs);
|
||||
if (l->filelen % sizeof(*in)) Host_Error("CMod_LoadNodes: funny lump size\n");
|
||||
if (l->filelen % sizeof(*in)) Host_Error("BSP_LoadNodes: funny lump size\n");
|
||||
count = l->filelen / sizeof(*in);
|
||||
|
||||
if(count < 1) Host_Error("Map %s has no nodes\n", cm.name );
|
||||
|
@ -236,6 +253,7 @@ void BSP_LoadNodes( lump_t *l )
|
|||
|
||||
for (i = 0; i < count; i++, out++, in++)
|
||||
{
|
||||
out->parent = NULL;
|
||||
n = LittleLong( in->planenum );
|
||||
if( n < 0 || n >= cm.numplanes)
|
||||
Host_Error("BSP_LoadNodes: invalid planenum %i (%i planes)\n", n, cm.numplanes );
|
||||
|
@ -246,14 +264,14 @@ void BSP_LoadNodes( lump_t *l )
|
|||
if( n >= 0 )
|
||||
{
|
||||
if( n >= cm.numnodes )
|
||||
Host_Error("BSP_LoadNodes: invalid child node index %i (%i nodes)", n, cm.numnodes );
|
||||
Host_Error("BSP_LoadNodes: invalid child node index %i (%i nodes)\n", n, cm.numnodes );
|
||||
out->children[j] = cm.nodes + n;
|
||||
}
|
||||
else
|
||||
{
|
||||
n = -1 - n;
|
||||
if( n >= cm.numleafs )
|
||||
Host_Error("BSP_LoadNodes: invalid child leaf index %i (%i leafs)", n, cm.numleafs );
|
||||
Host_Error("BSP_LoadNodes: invalid child leaf index %i (%i leafs)\n", n, cm.numleafs );
|
||||
out->children[j] = (cnode_t *)(cm.leafs + n);
|
||||
}
|
||||
}
|
||||
|
@ -281,7 +299,7 @@ void BSP_LoadBrushes( lump_t *l )
|
|||
cplanef_t *planes = NULL;
|
||||
|
||||
in = (void *)(cm.mod_base + l->fileofs);
|
||||
if (l->filelen % sizeof(*in)) Host_Error("CMod_LoadBrushes: funny lump size\n");
|
||||
if (l->filelen % sizeof(*in)) Host_Error("BSP_LoadBrushes: funny lump size\n");
|
||||
count = l->filelen / sizeof(*in);
|
||||
out = cm.brushes = (cbrush_t *)Mem_Alloc( cmappool, (count + 1) * sizeof(*out));
|
||||
cm.numbrushes = count;
|
||||
|
@ -303,7 +321,7 @@ void BSP_LoadBrushes( lump_t *l )
|
|||
{
|
||||
VectorCopy( cm.brushsides[out->firstbrushside + j].plane->normal, planes[j].normal );
|
||||
planes[j].dist = cm.brushsides[out->firstbrushside + j].plane->dist;
|
||||
planes[j].surfaceflags = cm.brushsides[out->firstbrushside + j].surface->flags;
|
||||
planes[j].surfaceflags = cm.brushsides[out->firstbrushside + j].surface->surfaceflags;
|
||||
planes[j].surface = cm.brushsides[out->firstbrushside + j].surface;
|
||||
}
|
||||
// make the colbrush from the planes
|
||||
|
@ -313,85 +331,27 @@ void BSP_LoadBrushes( lump_t *l )
|
|||
|
||||
/*
|
||||
=================
|
||||
BSP_LoadLeafs
|
||||
BSP_LoadLeafFaces
|
||||
=================
|
||||
*/
|
||||
void BSP_LoadLeafs( lump_t *l )
|
||||
void BSP_LoadLeafFaces( lump_t *l )
|
||||
{
|
||||
dleaf_t *in;
|
||||
cleaf_t *out;
|
||||
int i, j, count;
|
||||
dword *in, *out;
|
||||
int i, n, count;
|
||||
|
||||
in = (void *)(cm.mod_base + l->fileofs);
|
||||
if (l->filelen % sizeof(*in)) Host_Error("CMod_LoadLeafs: funny lump size\n");
|
||||
if (l->filelen % sizeof(*in)) Host_Error("BSP_LoadLeafFaces: funny lump size\n");
|
||||
count = l->filelen / sizeof(*in);
|
||||
if( count < 1 ) Host_Error("Map %s with no leafs\n", cm.name );
|
||||
out = cm.leafs = (cleaf_t *)Mem_Alloc( cmappool, (count + 1) * sizeof(*out));
|
||||
cm.numleafs = count;
|
||||
cm.numclusters = 0;
|
||||
|
||||
for ( i = 0; i < count; i++, in++, out++)
|
||||
out = cm.leafsurfaces = (dword *)Mem_Alloc( cmappool, count * sizeof(*out));
|
||||
cm.numleafsurfaces = count;
|
||||
|
||||
for( i = 0; i < count; i++, in++, out++ )
|
||||
{
|
||||
out->plane = NULL;
|
||||
out->firstleafbrush = LittleLong( in->firstleafbrush );
|
||||
out->numleafbrushes = LittleLong( in->numleafbrushes );
|
||||
out->contents = LittleLong( in->contents );
|
||||
out->cluster = LittleLong( in->cluster );
|
||||
out->area = LittleLong( in->area );
|
||||
if( out->cluster >= cm.numclusters )
|
||||
cm.numclusters = out->cluster + 1;
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
// yes the mins/maxs are ints
|
||||
out->mins[j] = LittleLong( in->mins[j] ) - 1;
|
||||
out->maxs[j] = LittleLong( in->maxs[j] ) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// probably any wall it's liquid ?
|
||||
if( cm.leafs[0].contents != CONTENTS_SOLID )
|
||||
Host_Error("Map %s with leaf 0 is not CONTENTS_SOLID\n", cm.name );
|
||||
|
||||
cm.solidleaf = 0;
|
||||
cm.emptyleaf = -1;
|
||||
|
||||
for( i = 1; i < count; i++ )
|
||||
{
|
||||
if(!cm.leafs[i].contents)
|
||||
{
|
||||
cm.emptyleaf = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// stuck into brushes
|
||||
if( cm.emptyleaf == -1 ) Host_Error("Map %s does not have an empty leaf\n", cm.name );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
BSP_LoadPlanes
|
||||
=================
|
||||
*/
|
||||
void BSP_LoadPlanes( lump_t *l )
|
||||
{
|
||||
dplane_t *in;
|
||||
cplane_t *out;
|
||||
int i, j, count;
|
||||
|
||||
in = (void *)(cm.mod_base + l->fileofs);
|
||||
if (l->filelen % sizeof(*in)) Host_Error("CMod_LoadPlanes: funny lump size\n");
|
||||
count = l->filelen / sizeof(*in);
|
||||
if (count < 1) Host_Error("Map %s with no planes\n", cm.name );
|
||||
out = cm.planes = (cplane_t *)Mem_Alloc( cmappool, (count + 12) * sizeof(*out));
|
||||
cm.numplanes = count;
|
||||
|
||||
for ( i = 0; i < count; i++, in++, out++)
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
out->normal[j] = LittleFloat(in->normal[j]);
|
||||
out->dist = LittleFloat( in->dist );
|
||||
PlaneClassify( out ); // automatic plane classify
|
||||
n = LittleShort(*in);
|
||||
if( n < 0 || n >= cm.numfaces )
|
||||
Host_Error("BSP_LoadLeafFaces: invalid face index %i (%i faces)\n", n, cm.numfaces );
|
||||
*out = n;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -410,11 +370,105 @@ void BSP_LoadLeafBrushes( lump_t *l )
|
|||
count = l->filelen / sizeof(*in);
|
||||
|
||||
if( count < 1 ) Host_Error("Map %s with no leaf brushes\n", cm.name );
|
||||
out = cm.leafbrushes = (dword *)Mem_Alloc( cmappool, (count + 1) * sizeof(*out));
|
||||
out = cm.leafbrushes = (dword *)Mem_Alloc( cmappool, count * sizeof(*out));
|
||||
cm.numleafbrushes = count;
|
||||
for ( i = 0; i < count; i++, in++, out++) *out = LittleShort(*in);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
BSP_LoadLeafs
|
||||
=================
|
||||
*/
|
||||
void BSP_LoadLeafs( lump_t *l )
|
||||
{
|
||||
dleaf_t *in;
|
||||
cleaf_t *out;
|
||||
int i, j, n, c, count;
|
||||
int emptyleaf = -1;
|
||||
|
||||
in = (void *)(cm.mod_base + l->fileofs);
|
||||
if (l->filelen % sizeof(*in)) Host_Error("BSP_LoadLeafs: funny lump size\n");
|
||||
count = l->filelen / sizeof(*in);
|
||||
if( count < 1 ) Host_Error("Map %s with no leafs\n", cm.name );
|
||||
out = cm.leafs = (cleaf_t *)Mem_Alloc( cmappool, count * sizeof(*out));
|
||||
cm.numleafs = count;
|
||||
cm.numclusters = 0;
|
||||
|
||||
for ( i = 0; i < count; i++, in++, out++)
|
||||
{
|
||||
out->parent = NULL;
|
||||
out->plane = NULL;
|
||||
out->contents = LittleLong( in->contents );
|
||||
out->cluster = LittleLong( in->cluster );
|
||||
out->area = LittleLong( in->area );
|
||||
if( out->cluster >= cm.numclusters )
|
||||
cm.numclusters = out->cluster + 1;
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
// yes the mins/maxs are ints
|
||||
out->mins[j] = LittleLong( in->mins[j] ) - 1;
|
||||
out->maxs[j] = LittleLong( in->maxs[j] ) + 1;
|
||||
}
|
||||
n = LittleLong( in->firstleafface );
|
||||
c = LittleLong( in->numleaffaces );
|
||||
if( n < 0 || n + c > cm.numleafsurfaces )
|
||||
Host_Error("BSP_LoadLeafs: invalid leafsurface range %i : %i (%i leafsurfaces)\n", n, n + c, cm.numleafsurfaces);
|
||||
out->firstleafsurface = cm.leafsurfaces + n;
|
||||
out->numleafsurfaces = c;
|
||||
n = LittleLong( in->firstleafbrush );
|
||||
c = LittleLong( in->numleafbrushes );
|
||||
if( n < 0 || n + c > cm.numleafbrushes )
|
||||
Host_Error("BSP_LoadLeafs: invalid leafbrush range %i : %i (%i leafbrushes)\n", n, n + c, cm.numleafbrushes);
|
||||
out->firstleafbrush = cm.leafbrushes + n;
|
||||
out->numleafbrushes = c;
|
||||
}
|
||||
|
||||
// probably any wall it's liquid ?
|
||||
if( cm.leafs[0].contents != CONTENTS_SOLID )
|
||||
Host_Error("Map %s with leaf 0 is not CONTENTS_SOLID\n", cm.name );
|
||||
|
||||
for( i = 1; i < count; i++ )
|
||||
{
|
||||
if(!cm.leafs[i].contents)
|
||||
{
|
||||
emptyleaf = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// stuck into brushes
|
||||
if( emptyleaf == -1 ) Host_Error("Map %s does not have an empty leaf\n", cm.name );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
BSP_LoadPlanes
|
||||
=================
|
||||
*/
|
||||
void BSP_LoadPlanes( lump_t *l )
|
||||
{
|
||||
dplane_t *in;
|
||||
cplane_t *out;
|
||||
int i, j, count;
|
||||
|
||||
in = (void *)(cm.mod_base + l->fileofs);
|
||||
if (l->filelen % sizeof(*in)) Host_Error("CMod_LoadPlanes: funny lump size\n");
|
||||
count = l->filelen / sizeof(*in);
|
||||
if (count < 1) Host_Error("Map %s with no planes\n", cm.name );
|
||||
out = cm.planes = (cplane_t *)Mem_Alloc( cmappool, count * sizeof(*out));
|
||||
cm.numplanes = count;
|
||||
|
||||
for ( i = 0; i < count; i++, in++, out++)
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
out->normal[j] = LittleFloat(in->normal[j]);
|
||||
out->dist = LittleFloat( in->dist );
|
||||
PlaneClassify( out ); // automatic plane classify
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
BSP_LoadBrushSides
|
||||
|
@ -429,7 +483,7 @@ void BSP_LoadBrushSides( lump_t *l )
|
|||
in = (void *)(cm.mod_base + l->fileofs);
|
||||
if (l->filelen % sizeof(*in)) Host_Error("CMod_LoadBrushSides: funny lump size\n");
|
||||
count = l->filelen / sizeof(*in);
|
||||
out = cm.brushsides = (cbrushside_t *)Mem_Alloc( cmappool, (count + 6) * sizeof(*out));
|
||||
out = cm.brushsides = (cbrushside_t *)Mem_Alloc( cmappool, count * sizeof(*out));
|
||||
cm.numbrushsides = count;
|
||||
|
||||
for ( i = 0; i < count; i++, in++, out++)
|
||||
|
@ -677,6 +731,58 @@ void BSP_LoadStringTable( lump_t *l )
|
|||
for ( i = 0; i < count; i++ ) out[i] = LittleLong(in[i]);
|
||||
}
|
||||
|
||||
static void BSP_RecursiveFindNumLeafs( cnode_t *node )
|
||||
{
|
||||
int numleafs;
|
||||
|
||||
while( node->plane )
|
||||
{
|
||||
BSP_RecursiveFindNumLeafs( node->children[0] );
|
||||
node = node->children[1];
|
||||
}
|
||||
numleafs = ((cleaf_t *)node - cm.leafs) + 1;
|
||||
if( cm.numleafs < numleafs ) cm.numleafs = numleafs;
|
||||
}
|
||||
|
||||
static void BSP_RecursiveSetParent( cnode_t *node, cnode_t *parent )
|
||||
{
|
||||
node->parent = parent;
|
||||
|
||||
if( node->plane )
|
||||
{
|
||||
// this is a node, recurse to children
|
||||
BSP_RecursiveSetParent( node->children[0], node );
|
||||
BSP_RecursiveSetParent( node->children[1], node );
|
||||
|
||||
// combine contents of children
|
||||
node->contents = node->children[0]->contents | node->children[1]->contents;
|
||||
}
|
||||
else
|
||||
{
|
||||
cleaf_t *leaf = (cleaf_t *)node;
|
||||
int i;
|
||||
|
||||
// if this is a leaf, calculate supercontents mask from all collidable
|
||||
// primitives in the leaf (brushes and collision surfaces)
|
||||
// also flag if the leaf contains any collision surfaces
|
||||
leaf->contents = 0;
|
||||
// combine the supercontents values of all brushes in this leaf
|
||||
for( i = 0; i < leaf->numleafbrushes; i++ )
|
||||
leaf->contents |= cm.brushes[leaf->firstleafbrush[i]].contents;
|
||||
|
||||
// check if this leaf contains any collision surfaces (patches)
|
||||
for( i = 0; i < leaf->numleafsurfaces; i++ )
|
||||
{
|
||||
dface_t *m_face = cm.surfaces + leaf->firstleafsurface[i];
|
||||
csurface_t *surface = cm.surfdesc + m_face->desc;
|
||||
if( surface->numtriangles )
|
||||
{
|
||||
leaf->havepatches = true;
|
||||
leaf->contents |= surface->contentflags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
@ -705,7 +811,7 @@ void BSP_AddCollisionFace( int facenum )
|
|||
}
|
||||
|
||||
m_face = cm.surfaces + facenum;
|
||||
flags = cm.surfdesc[m_face->desc].flags;
|
||||
flags = cm.surfdesc[m_face->desc].surfaceflags;
|
||||
k = m_face->firstedge;
|
||||
|
||||
// sky is noclip for all physobjects
|
||||
|
@ -734,9 +840,9 @@ void BSP_AddCollisionFace( int facenum )
|
|||
|
||||
void BSP_EndBuildTree( void )
|
||||
{
|
||||
if( cm.use_thread ) Msg("Optimize collision tree..." );
|
||||
if( app_name == COMP_BSPLIB ) Msg("Optimize collision tree..." );
|
||||
NewtonTreeCollisionEndBuild( cm.collision, true );
|
||||
if( cm.use_thread ) Msg(" done\n");
|
||||
if( app_name == COMP_BSPLIB ) Msg(" done\n");
|
||||
}
|
||||
|
||||
static void BSP_LoadTree( vfile_t* handle, void* buffer, size_t size )
|
||||
|
@ -751,19 +857,15 @@ void CM_LoadBSP( const void *buffer )
|
|||
header = *(dheader_t *)buffer;
|
||||
cm.mod_base = (byte *)buffer;
|
||||
|
||||
// loading level
|
||||
// bsplib uses light version of loading
|
||||
BSP_LoadVerts(&header.lumps[LUMP_VERTEXES]);
|
||||
BSP_LoadEdges(&header.lumps[LUMP_EDGES]);
|
||||
BSP_LoadSurfedges(&header.lumps[LUMP_SURFEDGES]);
|
||||
BSP_LoadFaces(&header.lumps[LUMP_FACES]);
|
||||
BSP_LoadSurfDesc(&header.lumps[LUMP_SURFDESC]);
|
||||
BSP_LoadFaces(&header.lumps[LUMP_FACES]);
|
||||
BSP_LoadModels(&header.lumps[LUMP_MODELS]);
|
||||
BSP_LoadCollision(&header.lumps[LUMP_COLLISION]);
|
||||
cm.loaded = true;
|
||||
cm.use_thread = true;
|
||||
|
||||
// keep bspdata because we want create bsp models
|
||||
// as kinematic objects: doors, fans, pendulums etc
|
||||
}
|
||||
|
||||
void CM_FreeBSP( void )
|
||||
|
@ -776,13 +878,14 @@ void CM_MakeCollisionTree( void )
|
|||
int i, world = 0; // world index
|
||||
|
||||
if(!cm.loaded) Host_Error("CM_MakeCollisionTree: map not loaded\n");
|
||||
if(cm.collision) return; // already generated
|
||||
if(cm.use_thread) Msg("Building collision tree...\n" );
|
||||
if( cm.collision ) return; // already generated
|
||||
if( app_name == COMP_BSPLIB ) Msg("Building collision tree...\n" );
|
||||
|
||||
BSP_BeginBuildTree();
|
||||
|
||||
// world firstface index always equal 0
|
||||
if(cm.use_thread) RunThreadsOnIndividual( cm.bmodels[world].numfaces, true, BSP_AddCollisionFace );
|
||||
if( app_name == COMP_BSPLIB )
|
||||
RunThreadsOnIndividual( cm.bmodels[world].numfaces, true, BSP_AddCollisionFace );
|
||||
else for( i = 0; i < cm.bmodels[world].numfaces; i++ ) BSP_AddCollisionFace( i );
|
||||
|
||||
BSP_EndBuildTree();
|
||||
|
@ -806,11 +909,8 @@ void CM_LoadWorld( const void *buffer )
|
|||
vec3_t boxP0, boxP1;
|
||||
vec3_t extra = { 10.0f, 10.0f, 10.0f };
|
||||
|
||||
CM_LoadBSP( buffer ); // loading bspdata
|
||||
|
||||
cm.use_thread = false;
|
||||
if(cm.world_tree) CM_LoadCollisionTree();
|
||||
else CM_MakeCollisionTree(); // can be used for old maps
|
||||
if( cm.world_tree ) CM_LoadCollisionTree();
|
||||
else CM_MakeCollisionTree(); // can be used for old maps or for product of alternative map compiler
|
||||
|
||||
cm.body = NewtonCreateBody( gWorld, cm.collision );
|
||||
NewtonBodyGetMatrix( cm.body, &cm.matrix[0][0] ); // set the global position of this body
|
||||
|
@ -833,7 +933,11 @@ void CM_FreeWorld( void )
|
|||
// free old stuff
|
||||
if( cm.loaded ) Mem_EmptyPool( cmappool );
|
||||
cm.numplanes = cm.numnodes = cm.numleafs = 0;
|
||||
cm.num_models = cm.numfaces = cm.numbmodels = 0;
|
||||
cm.numleafbrushes = cm.numfaces = cm.numbmodels = 0;
|
||||
cm.floodvalid = cm.numbrushsides = cm.numtexinfo = 0;
|
||||
cm.numbrushes = cm.numleafsurfaces = cm.numareas = 0;
|
||||
cm.numareaportals = cm.numclusters = 0;
|
||||
|
||||
cm.name[0] = 0;
|
||||
memset( cm.matrix, 0, sizeof(matrix4x4));
|
||||
|
||||
|
@ -844,6 +948,7 @@ void CM_FreeWorld( void )
|
|||
if(mod->registration_sequence != registration_sequence)
|
||||
CM_FreeModel( mod );
|
||||
}
|
||||
cm.numbmodels = 0;
|
||||
|
||||
if( cm.body )
|
||||
{
|
||||
|
@ -907,18 +1012,32 @@ cmodel_t *CM_BeginRegistration( const char *name, bool clientload, uint *checksu
|
|||
// load into heap
|
||||
BSP_LoadStringData(&hdr->lumps[LUMP_STRINGDATA]);
|
||||
BSP_LoadStringTable(&hdr->lumps[LUMP_STRINGTABLE]);
|
||||
BSP_LoadEntityString(&hdr->lumps[LUMP_ENTITIES]);
|
||||
BSP_LoadSurfDesc(&hdr->lumps[LUMP_SURFDESC]);
|
||||
BSP_LoadLeafs(&hdr->lumps[LUMP_LEAFS]);
|
||||
BSP_LoadLeafBrushes(&hdr->lumps[LUMP_LEAFBRUSHES]);
|
||||
BSP_LoadPlanes(&hdr->lumps[LUMP_PLANES]);
|
||||
BSP_LoadBrushSides(&hdr->lumps[LUMP_BRUSHSIDES]);
|
||||
BSP_LoadBrushes(&hdr->lumps[LUMP_BRUSHES]);
|
||||
BSP_LoadVerts(&hdr->lumps[LUMP_VERTEXES]);
|
||||
BSP_LoadEdges(&hdr->lumps[LUMP_EDGES]);
|
||||
BSP_LoadSurfedges(&hdr->lumps[LUMP_SURFEDGES]);
|
||||
BSP_LoadFaces(&hdr->lumps[LUMP_FACES]); // used only for generate NewtonCollisionTree
|
||||
BSP_LoadLeafBrushes(&hdr->lumps[LUMP_LEAFBRUSHES]);
|
||||
BSP_LoadLeafFaces(&hdr->lumps[LUMP_LEAFFACES]);
|
||||
BSP_LoadLeafs(&hdr->lumps[LUMP_LEAFS]);
|
||||
BSP_LoadNodes(&hdr->lumps[LUMP_NODES]);
|
||||
BSP_LoadAreas(&hdr->lumps[LUMP_AREAS]);
|
||||
BSP_LoadAreaPortals(&hdr->lumps[LUMP_AREAPORTALS]);
|
||||
BSP_LoadVisibility(&hdr->lumps[LUMP_VISIBILITY]);
|
||||
BSP_LoadEntityString(&hdr->lumps[LUMP_ENTITIES]);
|
||||
|
||||
BSP_LoadModels(&hdr->lumps[LUMP_MODELS]);
|
||||
BSP_LoadCollision(&hdr->lumps[LUMP_COLLISION]);
|
||||
|
||||
|
||||
// test, these probably unneeded
|
||||
Msg("cm.numleafs %i\n", cm.numleafs );
|
||||
BSP_RecursiveFindNumLeafs( cm.nodes );
|
||||
BSP_RecursiveSetParent( cm.nodes, NULL );
|
||||
Msg("cm.numleafs %i\n", cm.numleafs );
|
||||
|
||||
CM_LoadWorld( buf );// load physics collision
|
||||
Mem_Free( buf ); // release map buffer
|
||||
|
||||
|
@ -1049,7 +1168,7 @@ void CM_StudioSetUpTransform ( void )
|
|||
vec3_t mins, maxs;
|
||||
vec3_t modelpos;
|
||||
|
||||
hull.numverts = 0; // clear current count
|
||||
studio.numverts = studio.numtriangles = 0; // clear current count
|
||||
CM_StudioExtractBbox( studio.hdr, 0, mins, maxs );// adjust model center
|
||||
VectorAdd( mins, maxs, modelpos );
|
||||
VectorScale( modelpos, -0.5, modelpos );
|
||||
|
@ -1125,19 +1244,20 @@ void CM_StudioAddMesh( int mesh )
|
|||
{
|
||||
for(i = abs(i); i > 0; i--, ptricmds += 4)
|
||||
{
|
||||
hull.m_pVerts[hull.numverts][0] = INCH2METER(studio.transform[ptricmds[0]][0]);
|
||||
hull.m_pVerts[hull.numverts][1] = INCH2METER(studio.transform[ptricmds[0]][1]);
|
||||
hull.m_pVerts[hull.numverts][2] = INCH2METER(studio.transform[ptricmds[0]][2]);
|
||||
hull.numverts++;
|
||||
studio.m_pVerts[studio.numverts][0] = INCH2METER(studio.vtransform[ptricmds[0]][0]);
|
||||
studio.m_pVerts[studio.numverts][1] = INCH2METER(studio.vtransform[ptricmds[0]][1]);
|
||||
studio.m_pVerts[studio.numverts][2] = INCH2METER(studio.vtransform[ptricmds[0]][2]);
|
||||
studio.numverts++;
|
||||
}
|
||||
}
|
||||
studio.numtriangles += pmesh->numtris;
|
||||
}
|
||||
|
||||
void CM_StudioLookMeshes ( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < studio.submodel->nummesh; i++)
|
||||
for (i = 0; i < studio.submodel->nummesh; i++ )
|
||||
CM_StudioAddMesh( i );
|
||||
}
|
||||
|
||||
|
@ -1145,14 +1265,22 @@ void CM_StudioGetVertices( void )
|
|||
{
|
||||
int i;
|
||||
vec3_t *pstudioverts;
|
||||
vec3_t *pstudionorms;
|
||||
byte *pvertbone;
|
||||
byte *pnormbone;
|
||||
|
||||
pvertbone = ((byte *)studio.hdr + studio.submodel->vertinfoindex);
|
||||
pnormbone = ((byte *)studio.hdr + studio.submodel->norminfoindex);
|
||||
pstudioverts = (vec3_t *)((byte *)studio.hdr + studio.submodel->vertindex);
|
||||
pstudionorms = (vec3_t *)((byte *)studio.hdr + studio.submodel->normindex);
|
||||
|
||||
for (i = 0; i < studio.submodel->numverts; i++)
|
||||
for( i = 0; i < studio.submodel->numverts; i++ )
|
||||
{
|
||||
VectorTransform( pstudioverts[i], studio.bones[pvertbone[i]], studio.transform[i]);
|
||||
VectorTransform( pstudioverts[i], studio.bones[pvertbone[i]], studio.vtransform[i]);
|
||||
}
|
||||
for( i = 0; i < studio.submodel->numnorms; i++ )
|
||||
{
|
||||
VectorTransform( pstudionorms[i], studio.bones[pnormbone[i]], studio.ntransform[i]);
|
||||
}
|
||||
CM_StudioLookMeshes();
|
||||
}
|
||||
|
@ -1163,14 +1291,14 @@ void CM_CreateMeshBuffer( byte *buffer )
|
|||
|
||||
// setup global pointers
|
||||
studio.hdr = (studiohdr_t *)buffer;
|
||||
hull.m_pVerts = &studio.vertices[0];
|
||||
studio.m_pVerts = &studio.vertices[0];
|
||||
|
||||
CM_GetBodyCount();
|
||||
|
||||
for( i = 0; i < studio.bodycount; i++)
|
||||
{
|
||||
// already loaded
|
||||
if( loadmodel->physmesh[i].verts ) continue;
|
||||
if( loadmodel->col[i] ) continue;
|
||||
|
||||
CM_StudioSetUpTransform();
|
||||
CM_StudioSetupBones();
|
||||
|
@ -1181,11 +1309,13 @@ void CM_CreateMeshBuffer( byte *buffer )
|
|||
CM_StudioSetupModel( j, i );
|
||||
CM_StudioGetVertices();
|
||||
}
|
||||
if( hull.numverts )
|
||||
if( studio.numverts )
|
||||
{
|
||||
loadmodel->physmesh[i].verts = Mem_Alloc( loadmodel->mempool, hull.numverts * sizeof(vec3_t));
|
||||
Mem_Copy( loadmodel->physmesh[i].verts, hull.m_pVerts, hull.numverts * sizeof(vec3_t));
|
||||
loadmodel->physmesh[i].numverts = hull.numverts;
|
||||
loadmodel->col[i] = (cmesh_t *)Mem_Alloc( loadmodel->mempool, sizeof(*loadmodel->col[0]));
|
||||
loadmodel->col[i]->verts = Mem_Alloc( loadmodel->mempool, studio.numverts * sizeof(vec3_t));
|
||||
Mem_Copy( loadmodel->col[i]->verts, studio.m_pVerts, studio.numverts * sizeof(vec3_t));
|
||||
loadmodel->col[i]->numtris = studio.numtriangles;
|
||||
loadmodel->col[i]->numverts = studio.numverts;
|
||||
loadmodel->numbodies++;
|
||||
}
|
||||
}
|
||||
|
@ -1212,6 +1342,14 @@ bool CM_StudioModel( byte *buffer, uint filesize )
|
|||
VectorCopy( pseqdesc[0].bbmax, loadmodel->maxs );
|
||||
loadmodel->numframes = pseqdesc[0].numframes; // FIXME: get numframes from current sequence (not first)
|
||||
|
||||
// FIXME: calc bounding box right
|
||||
VectorCopy( loadmodel->mins, loadmodel->normalmins );
|
||||
VectorCopy( loadmodel->maxs, loadmodel->normalmaxs );
|
||||
VectorCopy( loadmodel->mins, loadmodel->rotatedmins );
|
||||
VectorCopy( loadmodel->maxs, loadmodel->rotatedmaxs );
|
||||
VectorCopy( loadmodel->mins, loadmodel->yawmins );
|
||||
VectorCopy( loadmodel->maxs, loadmodel->yawmaxs );
|
||||
|
||||
CM_CreateMeshBuffer( buffer ); // newton collision mesh
|
||||
|
||||
return true;
|
||||
|
@ -1236,6 +1374,15 @@ bool CM_SpriteModel( byte *buffer, uint filesize )
|
|||
loadmodel->maxs[0] = loadmodel->maxs[1] = phdr->bounds[0] / 2;
|
||||
loadmodel->mins[2] = -phdr->bounds[1] / 2;
|
||||
loadmodel->maxs[2] = phdr->bounds[1] / 2;
|
||||
|
||||
// FIXME: calc bounding box right
|
||||
VectorCopy( loadmodel->mins, loadmodel->normalmins );
|
||||
VectorCopy( loadmodel->maxs, loadmodel->normalmaxs );
|
||||
VectorCopy( loadmodel->mins, loadmodel->rotatedmins );
|
||||
VectorCopy( loadmodel->maxs, loadmodel->rotatedmaxs );
|
||||
VectorCopy( loadmodel->mins, loadmodel->yawmins );
|
||||
VectorCopy( loadmodel->maxs, loadmodel->yawmaxs );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
1142
physic/cm_pmove.c
1142
physic/cm_pmove.c
File diff suppressed because it is too large
Load Diff
|
@ -540,7 +540,7 @@ void PM_AddCurrents( vec3_t wishvel )
|
|||
v[2] -= 1;
|
||||
|
||||
s = pm_waterspeed;
|
||||
if ((pm->waterlevel == 1) && (pm->ps.groundentity))
|
||||
if ((pm->waterlevel == 1) && (pm->groundentity))
|
||||
s /= 2;
|
||||
|
||||
VectorMA (wishvel, s, v, wishvel);
|
||||
|
@ -550,7 +550,7 @@ void PM_AddCurrents( vec3_t wishvel )
|
|||
// add conveyor belt velocities
|
||||
//
|
||||
|
||||
if (pm->ps.groundentity)
|
||||
if (pm->groundentity)
|
||||
{
|
||||
VectorClear (v);
|
||||
|
||||
|
@ -567,7 +567,7 @@ void PM_AddCurrents( vec3_t wishvel )
|
|||
if (pml.groundtrace.contents & CONTENTS_CURRENT_DOWN)
|
||||
v[2] -= 1;
|
||||
|
||||
VectorMA (wishvel, 100 /* pm->ps.groundentity->speed */, v, wishvel);
|
||||
VectorMA (wishvel, 100 /* pm->groundentity->speed */, v, wishvel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -624,7 +624,7 @@ static bool PM_CheckJump( void )
|
|||
|
||||
pml.groundplane = false; // jumping away
|
||||
pml.walking = false;
|
||||
pm->ps.groundentity = NULL;
|
||||
pm->groundentity = NULL;
|
||||
pm->ps.pm_flags |= PMF_JUMP_HELD;
|
||||
pm->ps.velocity[2] = JUMP_VELOCITY;
|
||||
|
||||
|
@ -1180,7 +1180,7 @@ static int PM_CorrectAllSolid( trace_t *trace )
|
|||
}
|
||||
}
|
||||
|
||||
pm->ps.groundentity = NULL;
|
||||
pm->groundentity = NULL;
|
||||
pml.groundplane = false;
|
||||
pml.walking = false;
|
||||
return false;
|
||||
|
@ -1198,7 +1198,7 @@ static void PM_GroundTraceMissed( void )
|
|||
trace_t trace;
|
||||
vec3_t point;
|
||||
|
||||
if( pm->ps.groundentity )
|
||||
if( pm->groundentity )
|
||||
{
|
||||
// if they aren't in a jumping animation and the ground is a ways away, force into it
|
||||
// if we didn't do the trace, the player would be backflipping down staircases
|
||||
|
@ -1219,7 +1219,7 @@ static void PM_GroundTraceMissed( void )
|
|||
}
|
||||
}
|
||||
|
||||
pm->ps.groundentity = NULL;
|
||||
pm->groundentity = NULL;
|
||||
pml.groundplane = false;
|
||||
pml.walking = false;
|
||||
}
|
||||
|
@ -1270,7 +1270,7 @@ static void PM_GroundTrace( void )
|
|||
// anim jump backward
|
||||
}
|
||||
|
||||
pm->ps.groundentity = NULL;
|
||||
pm->groundentity = NULL;
|
||||
pml.groundplane = false;
|
||||
pml.walking = false;
|
||||
return;
|
||||
|
@ -1281,7 +1281,7 @@ static void PM_GroundTrace( void )
|
|||
{
|
||||
// FIXME: if they can't slide down the slope, let them
|
||||
// walk (sharp crevices)
|
||||
pm->ps.groundentity = NULL;
|
||||
pm->groundentity = NULL;
|
||||
pml.groundplane = true;
|
||||
pml.walking = false;
|
||||
return;
|
||||
|
@ -1297,7 +1297,7 @@ static void PM_GroundTrace( void )
|
|||
pm->ps.pm_time = 0;
|
||||
}
|
||||
|
||||
if( !pm->ps.groundentity )
|
||||
if( !pm->groundentity )
|
||||
{
|
||||
PM_CrashLand();
|
||||
|
||||
|
@ -1310,7 +1310,7 @@ static void PM_GroundTrace( void )
|
|||
}
|
||||
}
|
||||
|
||||
pm->ps.groundentity = trace.ent;
|
||||
pm->groundentity = trace.ent;
|
||||
PM_AddTouchEnt( trace.ent );
|
||||
}
|
||||
|
||||
|
@ -1441,7 +1441,7 @@ This can be used as another entry point when only the viewangles
|
|||
are being updated isntead of a full move
|
||||
================
|
||||
*/
|
||||
void PM_UpdateViewAngles( player_state_t *ps, const usercmd_t *cmd )
|
||||
void PM_UpdateViewAngles( entity_state_t *ps, const usercmd_t *cmd )
|
||||
{
|
||||
short temp;
|
||||
int i;
|
||||
|
|
239
physic/cm_test.c
239
physic/cm_test.c
|
@ -4,7 +4,6 @@
|
|||
//=======================================================================
|
||||
|
||||
#include "cm_local.h"
|
||||
#include "matrixlib.h"
|
||||
|
||||
static float RayCastPlacement(const NewtonBody* body, const float* normal, int collisionID, void* userData, float intersetParam )
|
||||
{
|
||||
|
@ -156,7 +155,7 @@ CM_PointContents
|
|||
*/
|
||||
int CM_PointContents( const vec3_t p, cmodel_t *model )
|
||||
{
|
||||
int i, num, contents = 0;
|
||||
int i, contents = 0;
|
||||
cbrush_t *brush;
|
||||
|
||||
if( !cm.numnodes ) return 0; // map not loaded
|
||||
|
@ -174,14 +173,14 @@ int CM_PointContents( const vec3_t p, cmodel_t *model )
|
|||
cnode_t *node = cm.nodes;
|
||||
cleaf_t *leaf;
|
||||
|
||||
leaf = &cm.leafs[CM_PointLeafnum_r( p, cm.nodes )];
|
||||
|
||||
// find which leaf the point is in
|
||||
while( node->plane )
|
||||
node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p, node->plane->normal)) < node->plane->dist];
|
||||
leaf = (cleaf_t *)node;
|
||||
// now check the brushes in the leaf
|
||||
for( i = 0; i < leaf->numleafbrushes; i++ )
|
||||
{
|
||||
num = cm.leafbrushes[leaf->firstleafbrush + i];
|
||||
brush = &cm.brushes[num];
|
||||
|
||||
brush = cm.brushes + leaf->firstleafbrush[i];
|
||||
if( brush->colbrushf && CM_CollisionPointInsideBrushFloat( p, brush->colbrushf ))
|
||||
contents |= brush->colbrushf->contents;
|
||||
}
|
||||
|
@ -216,230 +215,4 @@ int CM_TransformedPointContents( const vec3_t p, cmodel_t *model, const vec3_t o
|
|||
p_l[2] = DotProduct( temp, up );
|
||||
}
|
||||
return CM_PointContents( p_l, model );
|
||||
}
|
||||
|
||||
static void CM_TracePoint_r( trace_t *trace, cmodel_t *model, cnode_t *node, const vec3_t p, int markframe )
|
||||
{
|
||||
int i;
|
||||
cleaf_t *leaf;
|
||||
cbrushf_t *brush;
|
||||
|
||||
// find which leaf the point is in
|
||||
leaf = &cm.leafs[CM_PointLeafnum_r( p, cm.nodes )];
|
||||
for( i = 0; i < leaf->numleafbrushes; i++ )
|
||||
{
|
||||
brush = cm.brushes[leaf->firstleafbrush + i].colbrushf;
|
||||
if( brush && brush->markframe != markframe && BoxesOverlap( p, p, brush->mins, brush->maxs))
|
||||
{
|
||||
brush->markframe = markframe;
|
||||
CM_CollisionTracePointBrushFloat( trace, p, brush );
|
||||
}
|
||||
}
|
||||
// can't do point traces on curves (they have no thickness)
|
||||
}
|
||||
|
||||
static void CM_TraceLine_r( trace_t *trace, cmodel_t *model, cnode_t *node, const vec3_t start, const vec3_t end, vec_t startfrac, vec_t endfrac, const vec3_t linestart, const vec3_t lineend, int markframe, const vec3_t segmentmins, const vec3_t segmentmaxs )
|
||||
{
|
||||
int i, startside, endside;
|
||||
float dist1, dist2, midfrac, mid[3];
|
||||
float nodesegmentmins[3], nodesegmentmaxs[3];
|
||||
cleaf_t *leaf;
|
||||
cplane_t *plane;
|
||||
cbrushf_t *brush;
|
||||
|
||||
// walk the tree until we hit a leaf, recursing for any split cases
|
||||
while( node->plane )
|
||||
{
|
||||
// abort if this part of the bsp tree can not be hit by this trace
|
||||
plane = node->plane;
|
||||
// axial planes are much more common than non-axial, so an optimized
|
||||
// axial case pays off here
|
||||
if( plane->type < 3 )
|
||||
{
|
||||
dist1 = start[plane->type] - plane->dist;
|
||||
dist2 = end[plane->type] - plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
dist1 = DotProduct( start, plane->normal ) - plane->dist;
|
||||
dist2 = DotProduct( end, plane->normal ) - plane->dist;
|
||||
}
|
||||
startside = dist1 < 0;
|
||||
endside = dist2 < 0;
|
||||
if( startside == endside )
|
||||
{
|
||||
// most of the time the line fragment is on one side of the plane
|
||||
node = node->children[startside];
|
||||
}
|
||||
else
|
||||
{
|
||||
// line crosses node plane, split the line
|
||||
dist1 = PlaneDiff(linestart, plane);
|
||||
dist2 = PlaneDiff(lineend, plane);
|
||||
midfrac = dist1 / (dist1 - dist2);
|
||||
VectorLerp(linestart, midfrac, lineend, mid);
|
||||
// take the near side first
|
||||
CM_TraceLine_r( trace, model, node->children[startside], start, mid, startfrac, midfrac, linestart, lineend, markframe, segmentmins, segmentmaxs );
|
||||
// if we found an impact on the front side, don't waste time
|
||||
// exploring the far side
|
||||
if( midfrac <= trace->realfraction )
|
||||
CM_TraceLine_r( trace, model, node->children[endside], mid, end, midfrac, endfrac, linestart, lineend, markframe, segmentmins, segmentmaxs );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// hit a leaf
|
||||
nodesegmentmins[0] = min(start[0], end[0]) - 1;
|
||||
nodesegmentmins[1] = min(start[1], end[1]) - 1;
|
||||
nodesegmentmins[2] = min(start[2], end[2]) - 1;
|
||||
nodesegmentmaxs[0] = max(start[0], end[0]) + 1;
|
||||
nodesegmentmaxs[1] = max(start[1], end[1]) + 1;
|
||||
nodesegmentmaxs[2] = max(start[2], end[2]) + 1;
|
||||
|
||||
// line trace the brushes
|
||||
leaf = (cleaf_t *)node;
|
||||
|
||||
for( i = 0; i < leaf->numleafbrushes; i++ )
|
||||
{
|
||||
brush = cm.brushes[leaf->firstleafbrush + i].colbrushf;
|
||||
if( brush && brush->markframe != markframe && BoxesOverlap( nodesegmentmins, nodesegmentmaxs, brush->mins, brush->maxs ))
|
||||
{
|
||||
brush->markframe = markframe;
|
||||
CM_CollisionTraceLineBrushFloat( trace, linestart, lineend, brush, brush );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CM_TraceBrush_r( trace_t *trace, cmodel_t *model, cnode_t *node, const cbrushf_t *thisbrush_start, const cbrushf_t *thisbrush_end, int markframe, const vec3_t segmentmins, const vec3_t segmentmaxs )
|
||||
{
|
||||
int i, sides;
|
||||
cleaf_t *leaf;
|
||||
cbrushf_t *brush;
|
||||
cplane_t *plane;
|
||||
float nodesegmentmins[3], nodesegmentmaxs[3];
|
||||
|
||||
// walk the tree until we hit a leaf, recursing for any split cases
|
||||
while( node->plane )
|
||||
{
|
||||
// abort if this part of the bsp tree can not be hit by this trace
|
||||
plane = node->plane;
|
||||
|
||||
// axial planes are much more common than non-axial, so an optimized
|
||||
// axial case pays off here
|
||||
if( plane->type < 3 )
|
||||
{
|
||||
// this is an axial plane, compare bounding box directly to it and
|
||||
// recurse sides accordingly
|
||||
sides = ((segmentmaxs[plane->type] >= plane->dist) + ((segmentmins[plane->type] < plane->dist) * 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is a non-axial plane, so check if the start and end boxes
|
||||
// are both on one side of the plane to handle 'diagonal' cases
|
||||
sides = BoxOnPlaneSide( thisbrush_start->mins, thisbrush_start->maxs, plane) | BoxOnPlaneSide( thisbrush_end->mins, thisbrush_end->maxs, plane );
|
||||
}
|
||||
if( sides == 3 )
|
||||
{
|
||||
// segment crosses plane
|
||||
CM_TraceBrush_r( trace, model, node->children[0], thisbrush_start, thisbrush_end, markframe, segmentmins, segmentmaxs );
|
||||
sides = 2;
|
||||
}
|
||||
// if sides == 0 then the trace itself is bogus (Not A Number values),
|
||||
// in this case we simply pretend the trace hit nothing
|
||||
if( sides == 0 ) return; // ERROR: NAN bounding box!
|
||||
// take whichever side the segment box is on
|
||||
node = node->children[sides - 1];
|
||||
}
|
||||
// abort if this part of the bsp tree can not be hit by this trace
|
||||
|
||||
nodesegmentmins[0] = max(segmentmins[0], node->mins[0] - 1);
|
||||
nodesegmentmins[1] = max(segmentmins[1], node->mins[1] - 1);
|
||||
nodesegmentmins[2] = max(segmentmins[2], node->mins[2] - 1);
|
||||
nodesegmentmaxs[0] = min(segmentmaxs[0], node->maxs[0] + 1);
|
||||
nodesegmentmaxs[1] = min(segmentmaxs[1], node->maxs[1] + 1);
|
||||
nodesegmentmaxs[2] = min(segmentmaxs[2], node->maxs[2] + 1);
|
||||
|
||||
// hit a leaf
|
||||
leaf = (cleaf_t *)node; //it's right ?
|
||||
|
||||
for( i = 0; i < leaf->numleafbrushes; i++ )
|
||||
{
|
||||
brush = cm.brushes[leaf->firstleafbrush + i].colbrushf;
|
||||
if( brush && brush->markframe != markframe && BoxesOverlap( nodesegmentmins, nodesegmentmaxs, brush->mins, brush->maxs ))
|
||||
{
|
||||
brush->markframe = markframe;
|
||||
CM_CollisionTraceBrushBrushFloat( trace, thisbrush_start, thisbrush_end, brush, brush );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CM_TraceBox( const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, cmodel_t *model, trace_t *trace, int contentsmask )
|
||||
{
|
||||
int i;
|
||||
float segmentmins[3], segmentmaxs[3];
|
||||
static int markframe = 0;
|
||||
cbrush_t *brush;
|
||||
|
||||
memset( trace, 0, sizeof(*trace));
|
||||
trace->fraction = 1;
|
||||
trace->realfraction = 1;
|
||||
trace->contentsmask = contentsmask;
|
||||
|
||||
if((VectorLength2( mins ) + VectorLength2( maxs)) == 0)
|
||||
{
|
||||
if(VectorCompare( start, end ))
|
||||
{
|
||||
// point trace
|
||||
if( model && model->type == mod_brush )
|
||||
{
|
||||
for( i = 0, brush = cm.brushes + model->firstbrush; i < model->numbrushes; i++, brush++ )
|
||||
if( brush->colbrushf ) CM_CollisionTracePointBrushFloat( trace, start, brush->colbrushf );
|
||||
}
|
||||
else CM_TracePoint_r( trace, model, cm.nodes, start, ++markframe );
|
||||
}
|
||||
else
|
||||
{
|
||||
// line trace
|
||||
segmentmins[0] = min(start[0], end[0]) - 1;
|
||||
segmentmins[1] = min(start[1], end[1]) - 1;
|
||||
segmentmins[2] = min(start[2], end[2]) - 1;
|
||||
segmentmaxs[0] = max(start[0], end[0]) + 1;
|
||||
segmentmaxs[1] = max(start[1], end[1]) + 1;
|
||||
segmentmaxs[2] = max(start[2], end[2]) + 1;
|
||||
if( model && model->type == mod_brush )
|
||||
{
|
||||
for( i = 0, brush = cm.brushes + model->firstbrush; i < model->numbrushes; i++, brush++ )
|
||||
if( brush->colbrushf ) CM_CollisionTraceLineBrushFloat( trace, start, end, brush->colbrushf, brush->colbrushf );
|
||||
}
|
||||
else CM_TraceLine_r( trace, model, cm.nodes, start, end, 0, 1, start, end, ++markframe, segmentmins, segmentmaxs );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// box trace, performed as brush trace
|
||||
cbrushf_t *thisbrush_start, *thisbrush_end;
|
||||
vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
|
||||
|
||||
segmentmins[0] = min(start[0], end[0]) + mins[0] - 1;
|
||||
segmentmins[1] = min(start[1], end[1]) + mins[1] - 1;
|
||||
segmentmins[2] = min(start[2], end[2]) + mins[2] - 1;
|
||||
segmentmaxs[0] = max(start[0], end[0]) + maxs[0] + 1;
|
||||
segmentmaxs[1] = max(start[1], end[1]) + maxs[1] + 1;
|
||||
segmentmaxs[2] = max(start[2], end[2]) + maxs[2] + 1;
|
||||
|
||||
VectorAdd(start, mins, boxstartmins);
|
||||
VectorAdd(start, maxs, boxstartmaxs);
|
||||
VectorAdd(end, mins, boxendmins);
|
||||
VectorAdd(end, maxs, boxendmaxs);
|
||||
|
||||
thisbrush_start = CM_CollisionBrushForBox( identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL );
|
||||
thisbrush_end = CM_CollisionBrushForBox( identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL );
|
||||
|
||||
if( model && model->type == mod_brush )
|
||||
{
|
||||
for( i = 0, brush = cm.brushes + model->firstbrush; i < model->numbrushes; i++, brush++ )
|
||||
if( brush->colbrushf ) CM_CollisionTraceBrushBrushFloat( trace, thisbrush_start, thisbrush_end, brush->colbrushf, brush->colbrushf );
|
||||
}
|
||||
else CM_TraceBrush_r( trace, model, cm.nodes, thisbrush_start, thisbrush_end, ++markframe, segmentmins, segmentmaxs);
|
||||
}
|
||||
}
|
|
@ -5,142 +5,7 @@
|
|||
|
||||
#include "cm_local.h"
|
||||
#include "cm_utils.h"
|
||||
|
||||
// keep 1/8 unit away to keep the position valid before network snapping
|
||||
// and to avoid various numeric issues
|
||||
#define DIST_EPSILON (0.125) // 1/8 epsilon to keep floating point happy
|
||||
#define RADIUS_EPSILON 1.0f
|
||||
#define MAX_POSITION_LEAFS 1024
|
||||
#define Square(x) ((x)*(x))
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
CM INTERNAL MATH
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
/*
|
||||
================
|
||||
RotatePoint
|
||||
================
|
||||
*/
|
||||
void RotatePoint(vec3_t point, const vec3_t matrix[3])
|
||||
{
|
||||
vec3_t tvec;
|
||||
|
||||
VectorCopy( point, tvec );
|
||||
point[0] = DotProduct( matrix[0], tvec );
|
||||
point[1] = DotProduct( matrix[1], tvec );
|
||||
point[2] = DotProduct( matrix[2], tvec );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
TransposeMatrix
|
||||
================
|
||||
*/
|
||||
void TransposeMatrix( const vec3_t matrix[3], vec3_t transpose[3])
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for( j = 0; j < 3; j++)
|
||||
transpose[i][j] = matrix[j][i];
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CreateRotationMatrix
|
||||
================
|
||||
*/
|
||||
void CreateRotationMatrix(const vec3_t angles, vec3_t matrix[3])
|
||||
{
|
||||
AngleVectors(angles, matrix[0], matrix[1], matrix[2]);
|
||||
VectorNegate( matrix[1], matrix[1] );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CM_ProjectPointOntoVector
|
||||
================
|
||||
*/
|
||||
void CM_ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vDir, vec3_t vProj )
|
||||
{
|
||||
vec3_t pVec;
|
||||
|
||||
VectorSubtract( point, vStart, pVec );
|
||||
// project onto the directional vector for this segment
|
||||
VectorMA( vStart, DotProduct( pVec, vDir ), vDir, vProj );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CM_DistanceFromLineSquared
|
||||
================
|
||||
*/
|
||||
float CM_DistanceFromLineSquared(vec3_t p, vec3_t lp1, vec3_t lp2, vec3_t dir)
|
||||
{
|
||||
vec3_t proj, t;
|
||||
int j;
|
||||
|
||||
CM_ProjectPointOntoVector( p, lp1, dir, proj );
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
if ((proj[j] > lp1[j] && proj[j] > lp2[j]) || (proj[j] < lp1[j] && proj[j] < lp2[j]))
|
||||
break;
|
||||
}
|
||||
if( j < 3 )
|
||||
{
|
||||
if(fabs(proj[j] - lp1[j]) < fabs(proj[j] - lp2[j]))
|
||||
{
|
||||
VectorSubtract(p, lp1, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorSubtract(p, lp2, t);
|
||||
}
|
||||
return VectorLength2(t);
|
||||
}
|
||||
VectorSubtract(p, proj, t);
|
||||
return VectorLength2(t);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CM_VectorDistanceSquared
|
||||
================
|
||||
*/
|
||||
float CM_VectorDistanceSquared( vec3_t p1, vec3_t p2 )
|
||||
{
|
||||
vec3_t dir;
|
||||
|
||||
VectorSubtract(p2, p1, dir);
|
||||
return VectorLength2(dir);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SquareRootFloat
|
||||
================
|
||||
*/
|
||||
float SquareRootFloat( float number )
|
||||
{
|
||||
long i;
|
||||
float x, y;
|
||||
const float f = 1.5F;
|
||||
|
||||
x = number * 0.5F;
|
||||
y = number;
|
||||
i = *(long*)&y;
|
||||
i = 0x5f3759df - (i>>1);
|
||||
y = *(float *)&i;
|
||||
y = y*(f-(x*y*y));
|
||||
y = y*(f-(x*y*y));
|
||||
|
||||
return number*y;
|
||||
}
|
||||
#include "matrixlib.h"
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
@ -148,93 +13,316 @@ float SquareRootFloat( float number )
|
|||
TRACING
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
PUBLIC FUNCTIONS
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
/*
|
||||
==================
|
||||
CM_BoxTrace
|
||||
==================
|
||||
*/
|
||||
void CM_BoxTrace( const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, cmodel_t *model, trace_t *tr, int brushmask )
|
||||
*/
|
||||
static void CM_TracePoint_r( trace_t *trace, cmodel_t *model, cnode_t *node, const vec3_t p, int markframe )
|
||||
{
|
||||
CM_TraceBox( start, end, mins, maxs, model, tr, brushmask );
|
||||
int i;
|
||||
cleaf_t *leaf;
|
||||
cbrushf_t *brush;
|
||||
|
||||
// find which leaf the point is in
|
||||
while( node->plane )
|
||||
node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p, node->plane->normal)) < node->plane->dist];
|
||||
// point trace the brushes
|
||||
leaf = (cleaf_t *)node;
|
||||
for( i = 0; i < leaf->numleafbrushes; i++ )
|
||||
{
|
||||
brush = cm.brushes[leaf->firstleafbrush[i]].colbrushf;
|
||||
if( brush && brush->markframe != markframe && BoxesOverlap( p, p, brush->mins, brush->maxs))
|
||||
{
|
||||
brush->markframe = markframe;
|
||||
CM_CollisionTracePointBrushFloat( trace, p, brush );
|
||||
}
|
||||
}
|
||||
// can't do point traces on curves (they have no thickness)
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_TransformedBoxTrace
|
||||
|
||||
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, cmodel_t *model, int brushmask, vec3_t origin, vec3_t angles, int capsule )
|
||||
static void CM_TraceLine_r( trace_t *trace, cmodel_t *model, cnode_t *node, const vec3_t start, const vec3_t end, vec_t startfrac, vec_t endfrac, const vec3_t linestart, const vec3_t lineend, int markframe, const vec3_t segmentmins, const vec3_t segmentmaxs )
|
||||
{
|
||||
vec3_t start_l, end_l;
|
||||
vec3_t offset;
|
||||
vec3_t symetricSize[2];
|
||||
vec3_t matrix[3], transpose[3];
|
||||
bool rotated;
|
||||
int i;
|
||||
|
||||
if( !mins ) mins = vec3_origin;
|
||||
if( !maxs ) maxs = vec3_origin;
|
||||
|
||||
// adjust so that mins and maxs are always symetric, which
|
||||
// avoids some complications with plane expanding of rotated
|
||||
// bmodels
|
||||
for ( i = 0 ; i < 3 ; i++ )
|
||||
int i, startside, endside;
|
||||
float dist1, dist2, midfrac, mid[3];
|
||||
float nodesegmentmins[3], nodesegmentmaxs[3];
|
||||
cleaf_t *leaf;
|
||||
cplane_t *plane;
|
||||
cbrushf_t *brush;
|
||||
csurface_t *surface;
|
||||
|
||||
// walk the tree until we hit a leaf, recursing for any split cases
|
||||
while( node->plane )
|
||||
{
|
||||
offset[i] = ( mins[i] + maxs[i] ) * 0.5f;
|
||||
symetricSize[0][i] = mins[i] - offset[i];
|
||||
symetricSize[1][i] = maxs[i] - offset[i];
|
||||
start_l[i] = start[i] + offset[i];
|
||||
end_l[i] = end[i] + offset[i];
|
||||
// abort if this part of the bsp tree can not be hit by this trace
|
||||
plane = node->plane;
|
||||
// axial planes are much more common than non-axial, so an optimized
|
||||
// axial case pays off here
|
||||
if( plane->type < 3 )
|
||||
{
|
||||
dist1 = start[plane->type] - plane->dist;
|
||||
dist2 = end[plane->type] - plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
dist1 = DotProduct( start, plane->normal ) - plane->dist;
|
||||
dist2 = DotProduct( end, plane->normal ) - plane->dist;
|
||||
}
|
||||
startside = dist1 < 0;
|
||||
endside = dist2 < 0;
|
||||
if( startside == endside )
|
||||
{
|
||||
// most of the time the line fragment is on one side of the plane
|
||||
node = node->children[startside];
|
||||
}
|
||||
else
|
||||
{
|
||||
// line crosses node plane, split the line
|
||||
dist1 = PlaneDiff(linestart, plane);
|
||||
dist2 = PlaneDiff(lineend, plane);
|
||||
midfrac = dist1 / (dist1 - dist2);
|
||||
VectorLerp(linestart, midfrac, lineend, mid);
|
||||
// take the near side first
|
||||
CM_TraceLine_r( trace, model, node->children[startside], start, mid, startfrac, midfrac, linestart, lineend, markframe, segmentmins, segmentmaxs );
|
||||
// if we found an impact on the front side, don't waste time
|
||||
// exploring the far side
|
||||
if( midfrac <= trace->realfraction )
|
||||
CM_TraceLine_r( trace, model, node->children[endside], mid, end, midfrac, endfrac, linestart, lineend, markframe, segmentmins, segmentmaxs );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// subtract origin offset
|
||||
VectorSubtract( start_l, origin, start_l );
|
||||
VectorSubtract( end_l, origin, end_l );
|
||||
// hit a leaf
|
||||
nodesegmentmins[0] = min(start[0], end[0]) - 1;
|
||||
nodesegmentmins[1] = min(start[1], end[1]) - 1;
|
||||
nodesegmentmins[2] = min(start[2], end[2]) - 1;
|
||||
nodesegmentmaxs[0] = max(start[0], end[0]) + 1;
|
||||
nodesegmentmaxs[1] = max(start[1], end[1]) + 1;
|
||||
nodesegmentmaxs[2] = max(start[2], end[2]) + 1;
|
||||
|
||||
// rotate start and end into the models frame of reference
|
||||
if(com.strcmp( model->name, "*4095" ) && !VectorIsNull( angles )) rotated = true;
|
||||
else rotated = false;
|
||||
// line trace the brushes
|
||||
leaf = (cleaf_t *)node;
|
||||
|
||||
if( rotated )
|
||||
for( i = 0; i < leaf->numleafbrushes; i++ )
|
||||
{
|
||||
// rotation on trace line (start-end) instead of rotating the bmodel
|
||||
// NOTE: This is still incorrect for bounding boxes because the actual bounding
|
||||
// box that is swept through the model is not rotated. We cannot rotate
|
||||
// the bounding box or the bmodel because that would make all the brush
|
||||
// bevels invalid.
|
||||
// However this is correct for capsules since a capsule itself is rotated too.
|
||||
CreateRotationMatrix( angles, matrix );
|
||||
RotatePoint( start_l, matrix );
|
||||
RotatePoint( end_l, matrix );
|
||||
brush = cm.brushes[leaf->firstleafbrush[i]].colbrushf;
|
||||
if( brush && brush->markframe != markframe && BoxesOverlap( nodesegmentmins, nodesegmentmaxs, brush->mins, brush->maxs ))
|
||||
{
|
||||
brush->markframe = markframe;
|
||||
CM_CollisionTraceLineBrushFloat( trace, linestart, lineend, brush, brush );
|
||||
}
|
||||
}
|
||||
|
||||
// sweep the box through the model
|
||||
CM_TraceBox( start_l, end_l, symetricSize[0], symetricSize[1], model, &cm.trace, brushmask );
|
||||
|
||||
// if the bmodel was rotated and there was a collision
|
||||
if( rotated && cm.trace.fraction != 1.0 )
|
||||
// can't do point traces on curves (they have no thickness)
|
||||
if( leaf->havepatches && !VectorCompare( start, end ))
|
||||
{
|
||||
// rotation of bmodel collision plane
|
||||
TransposeMatrix( matrix, transpose );
|
||||
RotatePoint( cm.trace.plane.normal, transpose );
|
||||
// line trace the curves
|
||||
for( i = 0; i < leaf->numleafsurfaces; i++ )
|
||||
{
|
||||
surface = cm.surfdesc + cm.surfaces[leaf->firstleafsurface[i]].desc;
|
||||
if( surface->numtriangles && surface->markframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, surface->mins, surface->maxs))
|
||||
{
|
||||
surface->markframe = markframe;
|
||||
CM_CollisionTraceLineTriangleMeshFloat( trace, linestart, lineend, surface->numtriangles, surface->indices, surface->vertices, surface->contentflags, surface->surfaceflags, surface, segmentmins, segmentmaxs );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// re-calculate the end position of the trace because the trace.endpos
|
||||
// calculated by CM_Trace could be rotated and have an offset
|
||||
cm.trace.endpos[0] = start[0] + cm.trace.fraction * (end[0] - start[0]);
|
||||
cm.trace.endpos[1] = start[1] + cm.trace.fraction * (end[1] - start[1]);
|
||||
cm.trace.endpos[2] = start[2] + cm.trace.fraction * (end[2] - start[2]);
|
||||
static void CM_TraceBrush_r( trace_t *trace, cmodel_t *model, cnode_t *node, const cbrushf_t *thisbrush_start, const cbrushf_t *thisbrush_end, int markframe, const vec3_t segmentmins, const vec3_t segmentmaxs )
|
||||
{
|
||||
int i, sides;
|
||||
cleaf_t *leaf;
|
||||
cbrushf_t *brush;
|
||||
cplane_t *plane;
|
||||
csurface_t *surface;
|
||||
vec3_t nodesegmentmins;
|
||||
vec3_t nodesegmentmaxs;
|
||||
|
||||
return cm.trace;
|
||||
// walk the tree until we hit a leaf, recursing for any split cases
|
||||
while( node->plane )
|
||||
{
|
||||
// abort if this part of the bsp tree can not be hit by this trace
|
||||
plane = node->plane;
|
||||
|
||||
// axial planes are much more common than non-axial, so an optimized
|
||||
// axial case pays off here
|
||||
if( plane->type < 3 )
|
||||
{
|
||||
// this is an axial plane, compare bounding box directly to it and
|
||||
// recurse sides accordingly
|
||||
sides = ((segmentmaxs[plane->type] >= plane->dist) + ((segmentmins[plane->type] < plane->dist) * 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is a non-axial plane, so check if the start and end boxes
|
||||
// are both on one side of the plane to handle 'diagonal' cases
|
||||
sides = BoxOnPlaneSide( thisbrush_start->mins, thisbrush_start->maxs, plane) | BoxOnPlaneSide( thisbrush_end->mins, thisbrush_end->maxs, plane );
|
||||
}
|
||||
if( sides == 3 )
|
||||
{
|
||||
// segment crosses plane
|
||||
CM_TraceBrush_r( trace, model, node->children[0], thisbrush_start, thisbrush_end, markframe, segmentmins, segmentmaxs );
|
||||
sides = 2;
|
||||
}
|
||||
// if sides == 0 then the trace itself is bogus (Not A Number values),
|
||||
// in this case we simply pretend the trace hit nothing
|
||||
if( sides == 0 ) return; // ERROR: NAN bounding box!
|
||||
// take whichever side the segment box is on
|
||||
node = node->children[sides - 1];
|
||||
}
|
||||
// abort if this part of the bsp tree can not be hit by this trace
|
||||
|
||||
nodesegmentmins[0] = max(segmentmins[0], node->mins[0] - 1);
|
||||
nodesegmentmins[1] = max(segmentmins[1], node->mins[1] - 1);
|
||||
nodesegmentmins[2] = max(segmentmins[2], node->mins[2] - 1);
|
||||
nodesegmentmaxs[0] = min(segmentmaxs[0], node->maxs[0] + 1);
|
||||
nodesegmentmaxs[1] = min(segmentmaxs[1], node->maxs[1] + 1);
|
||||
nodesegmentmaxs[2] = min(segmentmaxs[2], node->maxs[2] + 1);
|
||||
|
||||
// hit a leaf
|
||||
leaf = (cleaf_t *)node;
|
||||
|
||||
for( i = 0; i < leaf->numleafbrushes; i++ )
|
||||
{
|
||||
brush = cm.brushes[leaf->firstleafbrush[i]].colbrushf;
|
||||
if( brush && brush->markframe != markframe && BoxesOverlap( nodesegmentmins, nodesegmentmaxs, brush->mins, brush->maxs ))
|
||||
{
|
||||
brush->markframe = markframe;
|
||||
CM_CollisionTraceBrushBrushFloat( trace, thisbrush_start, thisbrush_end, brush, brush );
|
||||
}
|
||||
}
|
||||
if( leaf->havepatches )
|
||||
{
|
||||
for( i = 0; i < leaf->numleafsurfaces; i++ )
|
||||
{
|
||||
surface = cm.surfdesc + cm.surfaces[leaf->firstleafsurface[i]].desc;
|
||||
if( surface->numtriangles && surface->markframe != markframe && BoxesOverlap( nodesegmentmins, nodesegmentmaxs, surface->mins, surface->maxs ))
|
||||
{
|
||||
surface->markframe = markframe;
|
||||
CM_CollisionTraceBrushTriangleMeshFloat( trace, thisbrush_start, thisbrush_end, surface->numtriangles, surface->indices, surface->vertices, surface->contentflags, surface->surfaceflags, surface, segmentmins, segmentmaxs );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CM_TraceBmodel( const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, cmodel_t *model, trace_t *trace, int contentsmask )
|
||||
{
|
||||
int i, j;
|
||||
float segmentmins[3], segmentmaxs[3];
|
||||
static int markframe = 0;
|
||||
csurface_t *surface;
|
||||
cbrush_t *brush;
|
||||
|
||||
memset( trace, 0, sizeof(*trace));
|
||||
trace->fraction = 1;
|
||||
trace->realfraction = 1;
|
||||
trace->contentsmask = contentsmask;
|
||||
|
||||
if((VectorLength2( mins ) + VectorLength2( maxs)) == 0)
|
||||
{
|
||||
if(VectorCompare( start, end ))
|
||||
{
|
||||
// point trace
|
||||
if( model && model->type == mod_brush )
|
||||
{
|
||||
for( i = 0, brush = cm.brushes + model->firstbrush; i < model->numbrushes; i++, brush++ )
|
||||
if( brush->colbrushf ) CM_CollisionTracePointBrushFloat( trace, start, brush->colbrushf );
|
||||
}
|
||||
else CM_TracePoint_r( trace, model, cm.nodes, start, ++markframe );
|
||||
}
|
||||
else
|
||||
{
|
||||
// line trace
|
||||
segmentmins[0] = min(start[0], end[0]) - 1;
|
||||
segmentmins[1] = min(start[1], end[1]) - 1;
|
||||
segmentmins[2] = min(start[2], end[2]) - 1;
|
||||
segmentmaxs[0] = max(start[0], end[0]) + 1;
|
||||
segmentmaxs[1] = max(start[1], end[1]) + 1;
|
||||
segmentmaxs[2] = max(start[2], end[2]) + 1;
|
||||
if( model && model->type == mod_brush )
|
||||
{
|
||||
for( i = 0, brush = cm.brushes + model->firstbrush; i < model->numbrushes; i++, brush++ )
|
||||
if( brush->colbrushf ) CM_CollisionTraceLineBrushFloat( trace, start, end, brush->colbrushf, brush->colbrushf );
|
||||
for( i = 0, j = model->firstface; i < model->numfaces; i++, j++ )
|
||||
{
|
||||
surface = cm.surfdesc + cm.surfaces[j].desc;
|
||||
if( surface->numtriangles ) CM_CollisionTraceLineTriangleMeshFloat( trace, start, end, surface->numtriangles, surface->indices, surface->vertices, surface->contentflags, surface->surfaceflags, surface, segmentmins, segmentmaxs );
|
||||
}
|
||||
}
|
||||
else CM_TraceLine_r( trace, model, cm.nodes, start, end, 0, 1, start, end, ++markframe, segmentmins, segmentmaxs );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// box trace, performed as brush trace
|
||||
cbrushf_t *thisbrush_start, *thisbrush_end;
|
||||
vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
|
||||
|
||||
segmentmins[0] = min(start[0], end[0]) + mins[0] - 1;
|
||||
segmentmins[1] = min(start[1], end[1]) + mins[1] - 1;
|
||||
segmentmins[2] = min(start[2], end[2]) + mins[2] - 1;
|
||||
segmentmaxs[0] = max(start[0], end[0]) + maxs[0] + 1;
|
||||
segmentmaxs[1] = max(start[1], end[1]) + maxs[1] + 1;
|
||||
segmentmaxs[2] = max(start[2], end[2]) + maxs[2] + 1;
|
||||
|
||||
VectorAdd(start, mins, boxstartmins);
|
||||
VectorAdd(start, maxs, boxstartmaxs);
|
||||
VectorAdd(end, mins, boxendmins);
|
||||
VectorAdd(end, maxs, boxendmaxs);
|
||||
|
||||
thisbrush_start = CM_CollisionBrushForBox( identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL );
|
||||
thisbrush_end = CM_CollisionBrushForBox( identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL );
|
||||
|
||||
if( model && model->type == mod_brush )
|
||||
{
|
||||
for( i = 0, brush = cm.brushes + model->firstbrush; i < model->numbrushes; i++, brush++ )
|
||||
if( brush->colbrushf ) CM_CollisionTraceBrushBrushFloat( trace, thisbrush_start, thisbrush_end, brush->colbrushf, brush->colbrushf );
|
||||
for( i = 0, j = model->firstface; i < model->numfaces; i++, j++ )
|
||||
{
|
||||
surface = cm.surfdesc + cm.surfaces[j].desc;
|
||||
if( surface->numtriangles ) CM_CollisionTraceLineTriangleMeshFloat( trace, start, end, surface->numtriangles, surface->indices, surface->vertices, surface->contentflags, surface->surfaceflags, surface, segmentmins, segmentmaxs );
|
||||
}
|
||||
}
|
||||
else CM_TraceBrush_r( trace, model, cm.nodes, thisbrush_start, thisbrush_end, ++markframe, segmentmins, segmentmaxs);
|
||||
}
|
||||
}
|
||||
|
||||
void CM_TraceStudio( const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, cmodel_t *mod, trace_t *trace, int contentsmask )
|
||||
{
|
||||
vec3_t segmentmins;
|
||||
vec3_t segmentmaxs;
|
||||
|
||||
memset(trace, 0, sizeof(*trace));
|
||||
trace->fraction = 1;
|
||||
trace->realfraction = 1;
|
||||
trace->contentsmask = contentsmask;
|
||||
|
||||
if( VectorLength2(mins) + VectorLength2(maxs) == 0 )
|
||||
{
|
||||
// line trace
|
||||
segmentmins[0] = min(start[0], end[0]) - 1;
|
||||
segmentmins[1] = min(start[1], end[1]) - 1;
|
||||
segmentmins[2] = min(start[2], end[2]) - 1;
|
||||
segmentmaxs[0] = max(start[0], end[0]) + 1;
|
||||
segmentmaxs[1] = max(start[1], end[1]) + 1;
|
||||
segmentmaxs[2] = max(start[2], end[2]) + 1;
|
||||
CM_CollisionTraceLineTriangleMeshFloat( trace, start, end, mod->col[0]->numtris, mod->col[0]->indices, (const float *)mod->col[0]->verts, CONTENTS_SOLID, 0, NULL, segmentmins, segmentmaxs );
|
||||
}
|
||||
else
|
||||
{
|
||||
// box trace, performed as brush trace
|
||||
cbrushf_t *thisbrush_start, *thisbrush_end;
|
||||
vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
|
||||
|
||||
segmentmins[0] = min(start[0], end[0]) + mins[0] - 1;
|
||||
segmentmins[1] = min(start[1], end[1]) + mins[1] - 1;
|
||||
segmentmins[2] = min(start[2], end[2]) + mins[2] - 1;
|
||||
segmentmaxs[0] = max(start[0], end[0]) + maxs[0] + 1;
|
||||
segmentmaxs[1] = max(start[1], end[1]) + maxs[1] + 1;
|
||||
segmentmaxs[2] = max(start[2], end[2]) + maxs[2] + 1;
|
||||
VectorAdd(start, mins, boxstartmins);
|
||||
VectorAdd(start, maxs, boxstartmaxs);
|
||||
VectorAdd(end, mins, boxendmins);
|
||||
VectorAdd(end, maxs, boxendmaxs);
|
||||
|
||||
thisbrush_start = CM_CollisionBrushForBox( identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL );
|
||||
thisbrush_end = CM_CollisionBrushForBox( identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL );
|
||||
CM_CollisionTraceBrushTriangleMeshFloat( trace, thisbrush_start, thisbrush_end, mod->col[0]->numtris, mod->col[0]->indices, (const float *)mod->col[0]->verts, CONTENTS_SOLID, 0, NULL, segmentmins, segmentmaxs );
|
||||
}
|
||||
}
|
|
@ -55,7 +55,8 @@ const char *CM_EntityString( void );
|
|||
const char *CM_TexName( int index );
|
||||
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 );
|
||||
void CM_TraceBox( const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, cmodel_t *model, trace_t *trace, int brushsmask );
|
||||
void CM_TraceBmodel( const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, cmodel_t *model, trace_t *trace, int contentsmask );
|
||||
void CM_TraceStudio( const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, cmodel_t *model, trace_t *trace, int contentsmask );
|
||||
void CM_BoxTrace( const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, cmodel_t *model, trace_t *trace, int brushsmask );
|
||||
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, bool capsule );
|
||||
byte *CM_ClusterPVS( int cluster );
|
||||
|
|
|
@ -11,6 +11,7 @@ physic_t ph; // physic globalstate
|
|||
byte *physpool;
|
||||
byte *cmappool;
|
||||
NewtonWorld *gWorld;
|
||||
int app_name;
|
||||
|
||||
cvar_t *cm_use_triangles;
|
||||
cvar_t *cm_solver_model;
|
||||
|
@ -25,6 +26,7 @@ bool InitPhysics( void )
|
|||
physpool = Mem_AllocPool("Physics Pool");
|
||||
cmappool = Mem_AllocPool("CM Zone");
|
||||
gWorld = NewtonCreate( Palloc, Pfree ); // alloc world
|
||||
app_name = g_Instance;
|
||||
|
||||
// check developer mode
|
||||
if( FS_GetParmFromCmdLine("-dev", dev_level ))
|
||||
|
@ -88,10 +90,9 @@ physic_exp_t DLLEXPORT *CreateAPI ( stdlib_api_t *input, physic_imp_t *engfuncs
|
|||
Phys.NumBmodels = CM_NumInlineModels;
|
||||
Phys.GetEntityString = CM_EntityString;
|
||||
Phys.GetTextureName = CM_TexName;
|
||||
Phys.PointContents = CM_PointContents;
|
||||
Phys.TransformedPointContents = CM_TransformedPointContents;
|
||||
Phys.BoxTrace = CM_BoxTrace;
|
||||
Phys.TransformedBoxTrace = CM_TransformedBoxTrace;
|
||||
Phys.ClipToGenericEntity = CM_CollisionClipToGenericEntity;
|
||||
Phys.ClipToWorld = CM_CollisionClipToWorld;
|
||||
Phys.CombineTraces = CM_CollisionCombineTraces;
|
||||
|
||||
Phys.ClusterPVS = CM_ClusterPVS;
|
||||
Phys.ClusterPHS = CM_ClusterPHS;
|
||||
|
@ -108,8 +109,6 @@ physic_exp_t DLLEXPORT *CreateAPI ( stdlib_api_t *input, physic_imp_t *engfuncs
|
|||
|
||||
Phys.SetParameters = Phys_SetParameters;
|
||||
Phys.PlayerMove = CM_PlayerMove;
|
||||
Phys.ServerMove = CM_ServerMove;
|
||||
Phys.ClientMove = CM_ClientMove;
|
||||
|
||||
Phys.SetOrigin = CM_SetOrigin;
|
||||
Phys.GetForce = Phys_GetForce;
|
||||
|
|
|
@ -24,6 +24,7 @@ extern stdlib_api_t com;
|
|||
extern byte *physpool;
|
||||
extern byte *cmappool;
|
||||
extern NewtonWorld *gWorld;
|
||||
extern int app_name;
|
||||
|
||||
// cvars
|
||||
extern cvar_t *cm_use_triangles;
|
||||
|
|
|
@ -42,4 +42,264 @@ _inline void Matrix4x4_Transform3x3( const matrix4x4 in, const float v[3], float
|
|||
#endif
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_Invert_Simple( matrix4x4 out, const matrix4x4 in1 )
|
||||
{
|
||||
// we only support uniform scaling, so assume the first row is enough
|
||||
// (note the lack of sqrt here, because we're trying to undo the scaling,
|
||||
// this means multiplying by the inverse scale twice - squaring it, which
|
||||
// makes the sqrt a waste of time)
|
||||
double scale = 1.0 / (in1[0][0] * in1[0][0] + in1[0][1] * in1[0][1] + in1[0][2] * in1[0][2]);
|
||||
|
||||
// invert the rotation by transposing and multiplying by the squared
|
||||
// recipricol of the input matrix scale as described above
|
||||
out[0][0] = in1[0][0] * scale;
|
||||
out[0][1] = in1[1][0] * scale;
|
||||
out[0][2] = in1[2][0] * scale;
|
||||
out[1][0] = in1[0][1] * scale;
|
||||
out[1][1] = in1[1][1] * scale;
|
||||
out[1][2] = in1[2][1] * scale;
|
||||
out[2][0] = in1[0][2] * scale;
|
||||
out[2][1] = in1[1][2] * scale;
|
||||
out[2][2] = in1[2][2] * scale;
|
||||
|
||||
#ifdef OPENGL_STYLE
|
||||
// invert the translate
|
||||
out[3][0] = -(in1[3][0] * out[0][0] + in1[3][1] * out[1][0] + in1[3][2] * out[2][0]);
|
||||
out[3][1] = -(in1[3][0] * out[0][1] + in1[3][1] * out[1][1] + in1[3][2] * out[2][1]);
|
||||
out[3][2] = -(in1[3][0] * out[0][2] + in1[3][1] * out[1][2] + in1[3][2] * out[2][2]);
|
||||
|
||||
// don't know if there's anything worth doing here
|
||||
out[0][3] = 0;
|
||||
out[1][3] = 0;
|
||||
out[2][3] = 0;
|
||||
out[3][3] = 1;
|
||||
#else
|
||||
// invert the translate
|
||||
out[0][3] = -(in1[0][3] * out[0][0] + in1[1][3] * out[0][1] + in1[2][3] * out[0][2]);
|
||||
out[1][3] = -(in1[0][3] * out[1][0] + in1[1][3] * out[1][1] + in1[2][3] * out[1][2]);
|
||||
out[2][3] = -(in1[0][3] * out[2][0] + in1[1][3] * out[2][1] + in1[2][3] * out[2][2]);
|
||||
|
||||
// don't know if there's anything worth doing here
|
||||
out[3][0] = 0;
|
||||
out[3][1] = 0;
|
||||
out[3][2] = 0;
|
||||
out[3][3] = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_CreateTranslate( matrix4x4 out, double x, double y, double z )
|
||||
{
|
||||
#ifdef OPENGL_STYLE
|
||||
out[0][0] = 1.0f;
|
||||
out[1][0] = 0.0f;
|
||||
out[2][0] = 0.0f;
|
||||
out[3][0] = x;
|
||||
out[0][1] = 0.0f;
|
||||
out[1][1] = 1.0f;
|
||||
out[2][1] = 0.0f;
|
||||
out[3][1] = y;
|
||||
out[0][2] = 0.0f;
|
||||
out[1][2] = 0.0f;
|
||||
out[2][2] = 1.0f;
|
||||
out[3][2] = z;
|
||||
out[0][3] = 0.0f;
|
||||
out[1][3] = 0.0f;
|
||||
out[2][3] = 0.0f;
|
||||
out[3][3] = 1.0f;
|
||||
#else
|
||||
out[0][0] = 1.0f;
|
||||
out[0][1] = 0.0f;
|
||||
out[0][2] = 0.0f;
|
||||
out[0][3] = x;
|
||||
out[1][0] = 0.0f;
|
||||
out[1][1] = 1.0f;
|
||||
out[1][2] = 0.0f;
|
||||
out[1][3] = y;
|
||||
out[2][0] = 0.0f;
|
||||
out[2][1] = 0.0f;
|
||||
out[2][2] = 1.0f;
|
||||
out[2][3] = z;
|
||||
out[3][0] = 0.0f;
|
||||
out[3][1] = 0.0f;
|
||||
out[3][2] = 0.0f;
|
||||
out[3][3] = 1.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_CreateFromEntity( matrix4x4 out, double x, double y, double z, double pitch, double yaw, double roll, double scale )
|
||||
{
|
||||
double angle, sr, sp, sy, cr, cp, cy;
|
||||
|
||||
if( roll )
|
||||
{
|
||||
angle = yaw * (M_PI*2 / 360);
|
||||
sy = sin(angle);
|
||||
cy = cos(angle);
|
||||
angle = pitch * (M_PI*2 / 360);
|
||||
sp = sin(angle);
|
||||
cp = cos(angle);
|
||||
angle = roll * (M_PI*2 / 360);
|
||||
sr = sin(angle);
|
||||
cr = cos(angle);
|
||||
#ifdef OPENGL_STYLE
|
||||
out[0][0] = (cp*cy) * scale;
|
||||
out[1][0] = (sr*sp*cy+cr*-sy) * scale;
|
||||
out[2][0] = (cr*sp*cy+-sr*-sy) * scale;
|
||||
out[3][0] = x;
|
||||
out[0][1] = (cp*sy) * scale;
|
||||
out[1][1] = (sr*sp*sy+cr*cy) * scale;
|
||||
out[2][1] = (cr*sp*sy+-sr*cy) * scale;
|
||||
out[3][1] = y;
|
||||
out[0][2] = (-sp) * scale;
|
||||
out[1][2] = (sr*cp) * scale;
|
||||
out[2][2] = (cr*cp) * scale;
|
||||
out[3][2] = z;
|
||||
out[0][3] = 0;
|
||||
out[1][3] = 0;
|
||||
out[2][3] = 0;
|
||||
out[3][3] = 1;
|
||||
#else
|
||||
out[0][0] = (cp*cy) * scale;
|
||||
out[0][1] = (sr*sp*cy+cr*-sy) * scale;
|
||||
out[0][2] = (cr*sp*cy+-sr*-sy) * scale;
|
||||
out[0][3] = x;
|
||||
out[1][0] = (cp*sy) * scale;
|
||||
out[1][1] = (sr*sp*sy+cr*cy) * scale;
|
||||
out[1][2] = (cr*sp*sy+-sr*cy) * scale;
|
||||
out[1][3] = y;
|
||||
out[2][0] = (-sp) * scale;
|
||||
out[2][1] = (sr*cp) * scale;
|
||||
out[2][2] = (cr*cp) * scale;
|
||||
out[2][3] = z;
|
||||
out[3][0] = 0;
|
||||
out[3][1] = 0;
|
||||
out[3][2] = 0;
|
||||
out[3][3] = 1;
|
||||
#endif
|
||||
}
|
||||
else if( pitch )
|
||||
{
|
||||
angle = yaw * (M_PI*2 / 360);
|
||||
sy = sin(angle);
|
||||
cy = cos(angle);
|
||||
angle = pitch * (M_PI*2 / 360);
|
||||
sp = sin(angle);
|
||||
cp = cos(angle);
|
||||
#ifdef OPENGL_STYLE
|
||||
out[0][0] = (cp*cy) * scale;
|
||||
out[1][0] = (-sy) * scale;
|
||||
out[2][0] = (sp*cy) * scale;
|
||||
out[3][0] = x;
|
||||
out[0][1] = (cp*sy) * scale;
|
||||
out[1][1] = (cy) * scale;
|
||||
out[2][1] = (sp*sy) * scale;
|
||||
out[3][1] = y;
|
||||
out[0][2] = (-sp) * scale;
|
||||
out[1][2] = 0;
|
||||
out[2][2] = (cp) * scale;
|
||||
out[3][2] = z;
|
||||
out[0][3] = 0;
|
||||
out[1][3] = 0;
|
||||
out[2][3] = 0;
|
||||
out[3][3] = 1;
|
||||
#else
|
||||
out[0][0] = (cp*cy) * scale;
|
||||
out[0][1] = (-sy) * scale;
|
||||
out[0][2] = (sp*cy) * scale;
|
||||
out[0][3] = x;
|
||||
out[1][0] = (cp*sy) * scale;
|
||||
out[1][1] = (cy) * scale;
|
||||
out[1][2] = (sp*sy) * scale;
|
||||
out[1][3] = y;
|
||||
out[2][0] = (-sp) * scale;
|
||||
out[2][1] = 0;
|
||||
out[2][2] = (cp) * scale;
|
||||
out[2][3] = z;
|
||||
out[3][0] = 0;
|
||||
out[3][1] = 0;
|
||||
out[3][2] = 0;
|
||||
out[3][3] = 1;
|
||||
#endif
|
||||
}
|
||||
else if( yaw )
|
||||
{
|
||||
angle = yaw * (M_PI*2 / 360);
|
||||
sy = sin(angle);
|
||||
cy = cos(angle);
|
||||
#ifdef OPENGL_STYLE
|
||||
out[0][0] = (cy) * scale;
|
||||
out[1][0] = (-sy) * scale;
|
||||
out[2][0] = 0;
|
||||
out[3][0] = x;
|
||||
out[0][1] = (sy) * scale;
|
||||
out[1][1] = (cy) * scale;
|
||||
out[2][1] = 0;
|
||||
out[3][1] = y;
|
||||
out[0][2] = 0;
|
||||
out[1][2] = 0;
|
||||
out[2][2] = scale;
|
||||
out[3][2] = z;
|
||||
out[0][3] = 0;
|
||||
out[1][3] = 0;
|
||||
out[2][3] = 0;
|
||||
out[3][3] = 1;
|
||||
#else
|
||||
out[0][0] = (cy) * scale;
|
||||
out[0][1] = (-sy) * scale;
|
||||
out[0][2] = 0;
|
||||
out[0][3] = x;
|
||||
out[1][0] = (sy) * scale;
|
||||
out[1][1] = (cy) * scale;
|
||||
out[1][2] = 0;
|
||||
out[1][3] = y;
|
||||
out[2][0] = 0;
|
||||
out[2][1] = 0;
|
||||
out[2][2] = scale;
|
||||
out[2][3] = z;
|
||||
out[3][0] = 0;
|
||||
out[3][1] = 0;
|
||||
out[3][2] = 0;
|
||||
out[3][3] = 1;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef OPENGL_STYLE
|
||||
out[0][0] = scale;
|
||||
out[1][0] = 0;
|
||||
out[2][0] = 0;
|
||||
out[3][0] = x;
|
||||
out[0][1] = 0;
|
||||
out[1][1] = scale;
|
||||
out[2][1] = 0;
|
||||
out[3][1] = y;
|
||||
out[0][2] = 0;
|
||||
out[1][2] = 0;
|
||||
out[2][2] = scale;
|
||||
out[3][2] = z;
|
||||
out[0][3] = 0;
|
||||
out[1][3] = 0;
|
||||
out[2][3] = 0;
|
||||
out[3][3] = 1;
|
||||
#else
|
||||
out[0][0] = scale;
|
||||
out[0][1] = 0;
|
||||
out[0][2] = 0;
|
||||
out[0][3] = x;
|
||||
out[1][0] = 0;
|
||||
out[1][1] = scale;
|
||||
out[1][2] = 0;
|
||||
out[1][3] = y;
|
||||
out[2][0] = 0;
|
||||
out[2][1] = 0;
|
||||
out[2][2] = scale;
|
||||
out[2][3] = z;
|
||||
out[3][0] = 0;
|
||||
out[3][1] = 0;
|
||||
out[3][2] = 0;
|
||||
out[3][3] = 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif//BASEMATRIX_H
|
|
@ -518,7 +518,7 @@ Studio models are position independent, so the cache manager can move them.
|
|||
#define STUDIO_NF_FLATSHADE 0x0001
|
||||
#define STUDIO_NF_CHROME 0x0002
|
||||
#define STUDIO_NF_FULLBRIGHT 0x0004
|
||||
#define STUDIO_NF_RESERVED 0x0008 // reserved
|
||||
#define STUDIO_NF_COLORMAP 0x0008 // can changed by colormap command
|
||||
#define STUDIO_NF_BLENDED 0x0010 // rendering as semiblended
|
||||
#define STUDIO_NF_ADDITIVE 0x0020 // rendering with additive mode
|
||||
#define STUDIO_NF_TRANSPARENT 0x0040 // use texture with alpha channel
|
||||
|
@ -651,17 +651,12 @@ typedef struct
|
|||
vec3_t bbmax;
|
||||
} mstudiobbox_t;
|
||||
|
||||
typedef struct cache_user_s
|
||||
{
|
||||
void *data;
|
||||
} cache_user_t;
|
||||
|
||||
// demand loaded sequence groups
|
||||
typedef struct
|
||||
{
|
||||
char label[32]; // textual name
|
||||
char name[64]; // file name
|
||||
void* cache; // cache index pointer
|
||||
void *cache; // cache index pointer (only in memory)
|
||||
int data; // hack for group 0
|
||||
} mstudioseqgroup_t;
|
||||
|
||||
|
@ -720,7 +715,6 @@ typedef struct
|
|||
char options[64];
|
||||
} mstudioevent_t;
|
||||
|
||||
|
||||
// pivots
|
||||
typedef struct
|
||||
{
|
||||
|
@ -785,7 +779,7 @@ typedef struct
|
|||
char name[64];
|
||||
|
||||
int type;
|
||||
float boundingradius;
|
||||
float boundingradius; // software stuff
|
||||
|
||||
int nummesh;
|
||||
int meshindex;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
enum host_state
|
||||
{ // paltform states
|
||||
HOST_OFFLINE = 0, // host_init( funcname *arg ) same much as:
|
||||
HOST_OFFLINE = 0, // host_init( g_Instance ) same much as:
|
||||
HOST_NORMAL, // "normal"
|
||||
HOST_DEDICATED, // "dedicated"
|
||||
HOST_VIEWER, // "viewer"
|
||||
|
@ -41,7 +41,7 @@ enum host_state
|
|||
#define DLLEXPORT __declspec(dllexport)
|
||||
|
||||
|
||||
#define USE_COORD_FRAC //FIXME: disable this
|
||||
//#define USE_COORD_FRAC //FIXME: disable this
|
||||
|
||||
// network precision coords factor
|
||||
#ifdef USE_COORD_FRAC
|
||||
|
@ -64,7 +64,7 @@ typedef struct { byte r; byte g; byte b; byte a; } color32;
|
|||
typedef struct { const char *name; void **func; } dllfunc_t; // Sys_LoadLibrary stuff
|
||||
typedef struct { int ofs; int type; const char *name; } fields_t; // prvm custom fields
|
||||
typedef void (*cmread_t) (void* handle, void* buffer, size_t size);
|
||||
typedef enum { mod_bad, mod_brush, mod_studio, mod_sprite } modtype_t;
|
||||
typedef enum { mod_bad, mod_static, mod_brush, mod_studio, mod_sprite } modtype_t;
|
||||
typedef void (*cmsave_t) (void* handle, const void* buffer, size_t size);
|
||||
typedef void (*cmdraw_t)( int color, int numpoints, const float *points );
|
||||
typedef struct { int numfilenames; char **filenames; char *filenamesbuffer; } search_t;
|
||||
|
@ -110,87 +110,122 @@ typedef struct model_s model_t;
|
|||
|
||||
typedef void (*xcommand_t) (void);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ED_SPAWNED = 0, // this entity requris to set own type with SV_ClassifyEdict
|
||||
ED_STATIC, // this is a logic without model or entity with static model
|
||||
ED_AMBIENT, // this is entity emitted ambient sounds only
|
||||
ED_NORMAL, // normal entity with model (and\or) sound
|
||||
ED_CLIENT, // this is a client entity
|
||||
ED_MONSTER, // monster or bot (generic npc with AI)
|
||||
ED_TEMPENTITY, // this edict will be removed on server when "lifetime" exceeds
|
||||
ED_BEAM, // laser beam (needs to recalculate pvs and frustum)
|
||||
ED_MOVER, // func_train, func_door and another bsp or mdl movers
|
||||
ED_VIEWMODEL, // client or bot viewmodel (for spectating)
|
||||
ED_ITEM, // holdable items
|
||||
ED_RAGDOLL, // dead body with simulated ragdolls
|
||||
ED_RIGIDBODY, // simulated physic
|
||||
ED_TRIGGER, // just for sorting on a server
|
||||
ED_PORTAL, // realtime display, portal or mirror brush or model
|
||||
ED_MISSILE, // greande, rocket e.t.c
|
||||
ED_DECAL, // render will be merge real coords and normal
|
||||
ED_VEHICLE, // controllable vehicle
|
||||
ED_MAXTYPES,
|
||||
} edtype_t;
|
||||
|
||||
// phys movetype
|
||||
typedef enum
|
||||
{
|
||||
MOVETYPE_NONE, // never moves
|
||||
MOVETYPE_NOCLIP, // origin and angles change with no interaction
|
||||
MOVETYPE_PUSH, // no clip to world, push on box contact
|
||||
MOVETYPE_WALK, // gravity
|
||||
MOVETYPE_STEP, // gravity, special edge handling
|
||||
MOVETYPE_FLY,
|
||||
MOVETYPE_TOSS, // gravity
|
||||
MOVETYPE_BOUNCE,
|
||||
MOVETYPE_FOLLOW, // attached models
|
||||
MOVETYPE_CONVEYOR,
|
||||
MOVETYPE_PUSHABLE,
|
||||
MOVETYPE_PHYSIC, // phys simulation
|
||||
} movetype_t;
|
||||
|
||||
// phys collision mode
|
||||
typedef enum
|
||||
{
|
||||
SOLID_NOT = 0, // no interaction with other objects
|
||||
SOLID_TRIGGER, // only touch when inside, after moving
|
||||
SOLID_BBOX, // touch on edge
|
||||
SOLID_BSP, // bsp clip, touch on edge
|
||||
SOLID_BOX, // physbox
|
||||
SOLID_SPHERE, // sphere
|
||||
SOLID_CYLINDER, // cylinder e.g. barrel
|
||||
SOLID_MESH, // custom convex hull
|
||||
} solid_t;
|
||||
|
||||
// model_state_t communication
|
||||
typedef struct model_state_s
|
||||
{
|
||||
int index; // server & client shared modelindex
|
||||
int colormap; // change base color for some textures or sprite frames
|
||||
float scale; // model or sprite scale, affects to physics too
|
||||
float frame; // % playback position in animation sequences (0..255)
|
||||
float animtime; // auto-animating time
|
||||
float framerate; // custom framerate, specified by QC
|
||||
int sequence; // animation sequence (0 - 255)
|
||||
int gaitsequence; // client\nps\bot gaitsequence
|
||||
int skin; // skin for studiomodels
|
||||
int body; // sub-model selection for studiomodels
|
||||
float blending[8]; // studio animation blending
|
||||
float controller[32]; // studio bone controllers
|
||||
vec3_t calcbonepos[128]; // too hard: ragdoll or like it, animated by physic engine
|
||||
} model_state_t;
|
||||
|
||||
// entity_state_t communication
|
||||
typedef struct entity_state_s
|
||||
{
|
||||
// engine specific
|
||||
uint number; // edict index
|
||||
edtype_t ed_type; // edict type
|
||||
int soundindex; // looped ambient sound
|
||||
|
||||
// physics information
|
||||
vec3_t origin;
|
||||
vec3_t angles;
|
||||
vec3_t angles; // entity angles, not viewangles
|
||||
vec3_t velocity; // player velocity
|
||||
vec3_t old_origin; // for lerping animation
|
||||
int modelindex;
|
||||
int soundindex;
|
||||
int weaponmodel;
|
||||
vec3_t old_velocity; // for movement predicting
|
||||
model_state_t model; // general entity model
|
||||
solid_t solidtype; // entity solidtype
|
||||
movetype_t movetype; // entity movetype
|
||||
int gravity; // gravity multiplier
|
||||
int aiment; // attahced entity (not a physic attach, only rendering)
|
||||
int solid; // using for symmetric bboxes
|
||||
vec3_t mins; // not symmetric entity bbox
|
||||
vec3_t maxs;
|
||||
|
||||
int skin; // skin for studiomodels
|
||||
float frame; // % playback position in animation sequences (0..512)
|
||||
int body; // sub-model selection for studiomodels
|
||||
int sequence; // animation sequence (0 - 255)
|
||||
uint effects; // PGM - we're filling it, so it needs to be unsigned
|
||||
int renderfx;
|
||||
int solid; // for client side prediction, 8*(bits 0-4) is x/y radius
|
||||
// 8*(bits 5-9) is z down distance, 8(bits10-15) is z up
|
||||
// gi.linkentity sets this properly
|
||||
float alpha; // alpha value
|
||||
float animtime; // auto-animating time
|
||||
// render information
|
||||
uint effects; // effect flags like q1 and hl1
|
||||
int renderfx; // render effects same as hl1
|
||||
float renderamt; // alpha value or like somewhat
|
||||
vec3_t rendercolor; // hl1 legacy stuff, working, but not needed
|
||||
int rendermode; // hl1 legacy stuff, working, but not needed
|
||||
|
||||
} entity_state_t;
|
||||
|
||||
// viewmodel state
|
||||
typedef struct vmodel_state_s
|
||||
{
|
||||
int index; // client modelindex
|
||||
vec3_t angles; // can be some different with viewangles
|
||||
vec3_t offset; // center offset
|
||||
int sequence; // studio animation sequence
|
||||
float frame; // studio frame
|
||||
int body; // weapon body
|
||||
int skin; // weapon skin
|
||||
} vmodel_state_t;
|
||||
|
||||
// thirdperson model state
|
||||
typedef struct pmodel_state_s
|
||||
{
|
||||
int index; // client modelindex
|
||||
int sequence; // studio animation sequence
|
||||
float frame; // studio frame
|
||||
} pmodel_state_t;
|
||||
|
||||
// player_state_t communication
|
||||
typedef struct player_state_s
|
||||
{
|
||||
int bobcycle; // for view bobbing and footstep generation
|
||||
float bobtime;
|
||||
int pm_type; // player movetype
|
||||
// client specific
|
||||
int pm_type; // client movetype
|
||||
int pm_flags; // ducked, jump_held, etc
|
||||
int pm_time; // each unit = 8 ms
|
||||
#ifdef USE_COORD_FRAC
|
||||
int origin[3];
|
||||
int velocity[3];
|
||||
#else
|
||||
vec3_t origin;
|
||||
vec3_t velocity;
|
||||
#endif
|
||||
vec3_t delta_angles; // add to command angles to get view direction
|
||||
int gravity; // gravity value
|
||||
int speed; // maxspeed
|
||||
edict_t *groundentity; // current ground entity
|
||||
vec3_t delta_angles; // add to command angles to get view direction
|
||||
vec3_t punch_angles; // add to view direction to get render angles
|
||||
vec3_t viewangles; // already calculated view angles on server-side
|
||||
vec3_t viewoffset; // FIXME: replace with viewheight
|
||||
int viewheight; // height over ground
|
||||
int effects; // copied to entity_state_t->effects
|
||||
vec3_t viewangles; // for fixed views
|
||||
vec3_t viewoffset; // add to pmovestate->origin
|
||||
vec3_t kick_angles; // add to view direction to get render angles
|
||||
vec3_t oldviewangles; // for lerping viewmodel position
|
||||
vec4_t blend; // rgba full screen effect
|
||||
int stats[32]; // integer limit
|
||||
int maxspeed; // sv_maxspeed will be duplicate on all clients
|
||||
float health; // client health (other parms can be send by custom messages)
|
||||
float fov; // horizontal field of view
|
||||
|
||||
// player model and viewmodel
|
||||
vmodel_state_t vmodel;
|
||||
pmodel_state_t pmodel;
|
||||
|
||||
} player_state_t;
|
||||
model_state_t vmodel; // viewmodel info
|
||||
model_state_t pmodel; // weaponmodel info
|
||||
} entity_state_t;
|
||||
|
||||
// usercmd_t communication
|
||||
typedef struct usercmd_s
|
||||
|
@ -265,7 +300,8 @@ typedef struct gameinfo_s
|
|||
string source_dir; // default source directory
|
||||
|
||||
char key[16]; // cd-key info
|
||||
char TXcommand; // quark command (get rid of this)
|
||||
char TXcommand; // quark .map comment
|
||||
char instance; // global engine instance
|
||||
} gameinfo_t;
|
||||
|
||||
/*
|
||||
|
@ -658,7 +694,8 @@ typedef struct stdilib_api_s
|
|||
#define Com_SkipToken com.Com_SkipToken
|
||||
#define Com_MatchToken com.Com_MatchToken
|
||||
#define com_token com.com_token
|
||||
#define g_TXcommand com.GameInfo->TXcommand // get rid of this
|
||||
#define g_TXcommand com.GameInfo->TXcommand
|
||||
#define g_Instance com.GameInfo->instance
|
||||
|
||||
/*
|
||||
===========================================
|
||||
|
@ -824,36 +861,6 @@ internal physic data
|
|||
hold linear and angular velocity, current position stored too
|
||||
========================================================================
|
||||
*/
|
||||
// phys movetype
|
||||
typedef enum
|
||||
{
|
||||
MOVETYPE_NONE, // never moves
|
||||
MOVETYPE_NOCLIP, // origin and angles change with no interaction
|
||||
MOVETYPE_PUSH, // no clip to world, push on box contact
|
||||
MOVETYPE_WALK, // gravity
|
||||
MOVETYPE_STEP, // gravity, special edge handling
|
||||
MOVETYPE_FLY,
|
||||
MOVETYPE_TOSS, // gravity
|
||||
MOVETYPE_BOUNCE,
|
||||
MOVETYPE_FOLLOW, // attached models
|
||||
MOVETYPE_CONVEYOR,
|
||||
MOVETYPE_PUSHABLE,
|
||||
MOVETYPE_PHYSIC, // phys simulation
|
||||
} movetype_t;
|
||||
|
||||
// phys collision mode
|
||||
typedef enum
|
||||
{
|
||||
SOLID_NOT = 0, // no interaction with other objects
|
||||
SOLID_TRIGGER, // only touch when inside, after moving
|
||||
SOLID_BBOX, // touch on edge
|
||||
SOLID_BSP, // bsp clip, touch on edge
|
||||
SOLID_BOX, // physbox
|
||||
SOLID_SPHERE, // sphere
|
||||
SOLID_CYLINDER, // cylinder e.g. barrel
|
||||
SOLID_MESH, // custom convex hull
|
||||
} solid_t;
|
||||
|
||||
typedef struct physdata_s
|
||||
{
|
||||
vec3_t origin;
|
||||
|
@ -896,6 +903,7 @@ typedef struct cvar_s
|
|||
#define ROLL 2
|
||||
|
||||
#define MAX_LIGHTSTYLES 256
|
||||
#define MAX_EDICTS 65535 // absolute limit that never be reached
|
||||
|
||||
#define EF_ROTATE (1<<0) // rotate (bonus items)
|
||||
|
||||
|
@ -951,7 +959,7 @@ MAP CONTENTS & SURFACES DESCRIPTION
|
|||
#define CONTENTS_CURRENT_UP 0x400000
|
||||
#define CONTENTS_CURRENT_DOWN 0x800000
|
||||
#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity
|
||||
#define CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game
|
||||
#define CONTENTS_BODY 0x2000000 // should never be on a brush, only in game
|
||||
#define CONTENTS_DEADMONSTER 0x4000000
|
||||
#define CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs
|
||||
#define CONTENTS_TRANSLUCENT 0x10000000// auto set if any surface has trans
|
||||
|
@ -1009,7 +1017,9 @@ typedef struct cplane_s
|
|||
typedef struct cmesh_s
|
||||
{
|
||||
vec3_t *verts;
|
||||
int *indices;
|
||||
uint numverts;
|
||||
uint numtris;
|
||||
} cmesh_t;
|
||||
|
||||
typedef struct cmodel_s
|
||||
|
@ -1026,7 +1036,15 @@ typedef struct cmodel_s
|
|||
int numbrushes;
|
||||
int numframes; // sprite framecount
|
||||
int numbodies; // physmesh numbody
|
||||
cmesh_t physmesh[MAXSTUDIOMODELS]; // max bodies
|
||||
cmesh_t *col[256]; // max bodies
|
||||
|
||||
// g-cont: stupid pushmodel stuff
|
||||
vec3_t normalmins; // bounding box at angles '0 0 0'
|
||||
vec3_t normalmaxs;
|
||||
vec3_t yawmins; // bounding box if yaw angle is not 0, but pitch and roll are
|
||||
vec3_t yawmaxs;
|
||||
vec3_t rotatedmins; // bounding box if pitch or roll are used
|
||||
vec3_t rotatedmaxs;
|
||||
|
||||
// custom traces for various model types
|
||||
void (*TraceBox)( const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, struct cmodel_s *model, struct trace_s *trace, int brushsmask );
|
||||
|
@ -1036,12 +1054,19 @@ typedef struct cmodel_s
|
|||
typedef struct csurface_s
|
||||
{
|
||||
string name;
|
||||
int flags;
|
||||
int surfaceflags;
|
||||
int contentflags;
|
||||
int value;
|
||||
|
||||
// physics stuff
|
||||
int firstedge; // look up in model->surfedges[], negative numbers
|
||||
int numedges; // are backwards edges
|
||||
vec3_t mins;
|
||||
vec3_t maxs;
|
||||
|
||||
// patches support
|
||||
int numtriangles;
|
||||
int numvertices;
|
||||
int *indices;
|
||||
float *vertices;
|
||||
int markframe;
|
||||
} csurface_t;
|
||||
|
||||
typedef struct trace_s
|
||||
|
@ -1066,12 +1091,12 @@ typedef struct trace_s
|
|||
// content masks
|
||||
#define MASK_ALL (-1)
|
||||
#define MASK_SOLID (CONTENTS_SOLID|CONTENTS_WINDOW)
|
||||
#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER)
|
||||
#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_BODY)
|
||||
#define MASK_DEADSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW)
|
||||
#define MASK_MONSTERSOLID (CONTENTS_SOLID|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER)
|
||||
#define MASK_MONSTERSOLID (CONTENTS_SOLID|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_BODY)
|
||||
#define MASK_WATER (CONTENTS_WATER|CONTENTS_LAVA|CONTENTS_SLIME)
|
||||
#define MASK_OPAQUE (CONTENTS_SOLID|CONTENTS_SLIME|CONTENTS_LAVA)
|
||||
#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEADMONSTER)
|
||||
#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_BODY|CONTENTS_WINDOW|CONTENTS_DEADMONSTER)
|
||||
#define MASK_CURRENT (CONTENTS_CURRENT_0|CONTENTS_CURRENT_90|CONTENTS_CURRENT_180|CONTENTS_CURRENT_270|CONTENTS_CURRENT_UP|CONTENTS_CURRENT_DOWN)
|
||||
|
||||
// pmove_state_t is the information necessary for client side movement
|
||||
|
@ -1250,7 +1275,7 @@ typedef struct
|
|||
|
||||
typedef struct pmove_s
|
||||
{
|
||||
player_state_t ps; // state (in / out)
|
||||
entity_state_t ps; // state (in / out)
|
||||
|
||||
// command (in)
|
||||
usercmd_t cmd;
|
||||
|
@ -1260,6 +1285,7 @@ typedef struct pmove_s
|
|||
// results (out)
|
||||
int numtouch;
|
||||
edict_t *touchents[PM_MAXTOUCH]; // max touch
|
||||
edict_t *groundentity;
|
||||
|
||||
vec3_t mins, maxs; // bounding box size
|
||||
int watertype;
|
||||
|
@ -1282,7 +1308,7 @@ typedef struct launch_exp_s
|
|||
// interface validator
|
||||
size_t api_size; // must matched with sizeof(launch_api_t)
|
||||
|
||||
void ( *Init ) ( uint funcname, int argc, char **argv ); // init host
|
||||
void ( *Init ) ( int argc, char **argv ); // init host
|
||||
void ( *Main ) ( void ); // host frame
|
||||
void ( *Free ) ( void ); // close host
|
||||
void (*CPrint) ( const char *msg ); // host print
|
||||
|
@ -1316,8 +1342,8 @@ typedef struct imglib_exp_s
|
|||
// interface validator
|
||||
size_t api_size; // must matched with sizeof(imglib_api_t)
|
||||
|
||||
void ( *Init ) ( uint funcname ); // init host
|
||||
void ( *Free ) ( void ); // close host
|
||||
void ( *Init ) ( void ); // init host
|
||||
void ( *Free ) ( void ); // close host
|
||||
|
||||
// global operations
|
||||
rgbdata_t *(*LoadImage)(const char *path, const byte *data, size_t size ); // extract image into rgba buffer
|
||||
|
@ -1413,10 +1439,6 @@ typedef struct physic_exp_s
|
|||
int (*NumBmodels )( void );
|
||||
const char *(*GetEntityString)( void );
|
||||
const char *(*GetTextureName)( int index );
|
||||
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 );
|
||||
void (*BoxTrace)( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *model, trace_t *tr, 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, bool capsule );
|
||||
byte *(*ClusterPVS)( int cluster );
|
||||
byte *(*ClusterPHS)( int cluster );
|
||||
int (*PointLeafnum)( vec3_t p );
|
||||
|
@ -1426,11 +1448,12 @@ typedef struct physic_exp_s
|
|||
bool (*AreasConnected)( int area1, int area2 );
|
||||
int (*WriteAreaBits)( byte *buffer, int area );
|
||||
|
||||
void (*ClipToGenericEntity)( trace_t *trace, cmodel_t *model, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4 matrix, matrix4x4 inversematrix, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int contentsmask );
|
||||
void (*ClipToWorld)( trace_t *trace, cmodel_t *model, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int contentsmask );
|
||||
void (*CombineTraces)( trace_t *cliptrace, const trace_t *trace, edict_t *touch, bool is_bmodel );
|
||||
|
||||
// player movement code
|
||||
void (*PlayerMove)( pmove_t *pmove, bool clientmove );
|
||||
|
||||
void (*ServerMove)( pmove_t *pmove );
|
||||
void (*ClientMove)( pmove_t *pmove );
|
||||
|
||||
// simple objects
|
||||
physbody_t *(*CreateBody)( sv_edict_t *ed, cmodel_t *mod, matrix4x3 transform, int solid );
|
||||
|
@ -1619,8 +1642,8 @@ typedef struct vprogs_exp_s
|
|||
// interface validator
|
||||
size_t api_size; // must matched with sizeof(vprogs_api_t)
|
||||
|
||||
void ( *Init ) ( uint funcname, int argc, char **argv ); // init host
|
||||
void ( *Free ) ( void ); // close host
|
||||
void ( *Init ) ( int argc, char **argv ); // init host
|
||||
void ( *Free ) ( void ); // close host
|
||||
|
||||
// compiler functions
|
||||
void ( *PrepareDAT )( const char *dir, const char *name );
|
||||
|
|
|
@ -853,8 +853,9 @@ void Mod_SetupSubmodels( model_t *mod )
|
|||
|
||||
starmod->firstmodelsurface = bm->firstface;
|
||||
starmod->nummodelsurfaces = bm->numfaces;
|
||||
starmod->type = mod_brush;
|
||||
starmod->firstnode = bm->headnode;
|
||||
if (starmod->firstnode >= loadmodel->numnodes)
|
||||
if( starmod->firstnode >= loadmodel->numnodes )
|
||||
Host_Error ("Inline model %i has bad firstnode", i);
|
||||
|
||||
VectorCopy (bm->maxs, starmod->maxs);
|
||||
|
@ -877,7 +878,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
|
|||
dheader_t *header;
|
||||
|
||||
|
||||
loadmodel->type = mod_brush;
|
||||
loadmodel->type = mod_static;
|
||||
if (loadmodel != mod_known)
|
||||
{
|
||||
Msg("Warning: loaded a brush model after the world\n");
|
||||
|
|
|
@ -172,7 +172,7 @@ void R_SpriteLoadModel( model_t *mod, void *buffer )
|
|||
pframetype = R_SpriteLoadGroup(mod, pframetype + 1, &psprite->frames[i].frameptr, i );
|
||||
break;
|
||||
}
|
||||
if(pframetype == NULL) break; // technically an error
|
||||
if( pframetype == NULL ) break; // technically an error
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -483,20 +483,17 @@ StudioGetAnim
|
|||
mstudioanim_t *R_StudioGetAnim( model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc )
|
||||
{
|
||||
mstudioseqgroup_t *pseqgroup;
|
||||
cache_user_t *paSequences;
|
||||
byte *buf;
|
||||
int filesize;
|
||||
byte *paSequences;
|
||||
size_t filesize;
|
||||
byte *buf;
|
||||
|
||||
//WARNING! Not tested!!!
|
||||
|
||||
pseqgroup = (mstudioseqgroup_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqgroupindex) + pseqdesc->seqgroup;
|
||||
|
||||
if (pseqdesc->seqgroup == 0)
|
||||
{
|
||||
if( pseqdesc->seqgroup == 0 )
|
||||
return (mstudioanim_t *)((byte *)m_pStudioHeader + pseqgroup->data + pseqdesc->animindex);
|
||||
}
|
||||
|
||||
paSequences = (cache_user_t *)m_pSubModel->submodels;
|
||||
paSequences = (void *)m_pSubModel->submodels;
|
||||
|
||||
if (paSequences == NULL)
|
||||
{
|
||||
|
@ -508,18 +505,18 @@ mstudioanim_t *R_StudioGetAnim( model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc
|
|||
memset (pseqgroup->name, 0, sizeof(pseqgroup->name));
|
||||
return NULL;
|
||||
}
|
||||
if(IDSEQGRPHEADER == LittleLong(*(unsigned *)buf)) //it's sequence group
|
||||
if(IDSEQGRPHEADER == LittleLong(*(uint *)buf)) //it's sequence group
|
||||
{
|
||||
byte *pin = (byte *)buf;
|
||||
mstudioseqgroup_t *pseqhdr = (mstudioseqgroup_t *)pin;
|
||||
|
||||
paSequences = (cache_user_t *)Mem_Alloc(m_pSubModel->mempool, LittleLong(filesize));
|
||||
paSequences = (byte *)Mem_Alloc(m_pSubModel->mempool, filesize );
|
||||
m_pSubModel->submodels = (mmodel_t *)paSequences;
|
||||
|
||||
memcpy((struct cache_user_s *)&paSequences[pseqdesc->seqgroup], buf, LittleLong(filesize));
|
||||
Mem_Copy(&paSequences[pseqdesc->seqgroup], buf, filesize );
|
||||
}
|
||||
}
|
||||
return (mstudioanim_t *)((byte *)paSequences[pseqdesc->seqgroup].data + pseqdesc->animindex);
|
||||
return (mstudioanim_t *)((byte *)paSequences[pseqdesc->seqgroup] + pseqdesc->animindex);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -316,7 +316,7 @@ void R_InitTextures( void )
|
|||
CreateImglib = (void *)imglib_dll.main;
|
||||
Image = CreateImglib( &com, NULL ); // second interface not allowed
|
||||
|
||||
Image->Init( HOST_NORMAL );
|
||||
Image->Init();
|
||||
r_imagepool = Mem_AllocPool("Texture Pool");
|
||||
gl_maxsize = Cvar_Get( "gl_maxsize", "4096", CVAR_ARCHIVE, "texture dimension max size" );
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ idconv.dll needs for some setup operations
|
|||
so do it manually
|
||||
==================
|
||||
*/
|
||||
void InitConvertor ( uint funcname, int argc, char **argv )
|
||||
void InitConvertor ( int argc, char **argv )
|
||||
{
|
||||
launch_t CreateImglib, CreateVprogs;
|
||||
string gamedir;
|
||||
|
@ -121,20 +121,20 @@ void InitConvertor ( uint funcname, int argc, char **argv )
|
|||
// init pools
|
||||
basepool = Mem_AllocPool( "Temp" );
|
||||
zonepool = Mem_AllocPool( "Zone" );
|
||||
app_name = funcname;
|
||||
app_name = g_Instance;
|
||||
|
||||
Sys_LoadLibrary( &imglib_dll ); // load imagelib
|
||||
CreateImglib = (void *)imglib_dll.main;
|
||||
Image = CreateImglib( &com, NULL ); // second interface not allowed
|
||||
|
||||
switch( funcname )
|
||||
switch( app_name )
|
||||
{
|
||||
case RIPP_QCCDEC:
|
||||
Sys_LoadLibrary( &vprogs_dll ); // load qcclib
|
||||
CreateVprogs = (void *)vprogs_dll.main;
|
||||
PRVM = CreateVprogs( &com, NULL ); // second interface not allowed
|
||||
|
||||
PRVM->Init( funcname, argc, argv );
|
||||
PRVM->Init( argc, argv );
|
||||
|
||||
if(!FS_GetParmFromCmdLine("-dir", gamedir ))
|
||||
com.strncpy( gamedir, ".", sizeof(gamedir));
|
||||
|
@ -143,7 +143,7 @@ void InitConvertor ( uint funcname, int argc, char **argv )
|
|||
break;
|
||||
default:
|
||||
FS_InitRootDir(".");
|
||||
Image->Init( funcname ); // initialize image support
|
||||
Image->Init(); // initialize image support
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
2
todo.log
2
todo.log
|
@ -28,6 +28,8 @@ fopen
|
|||
5. Собрать все ресурсы в builtin.h OK
|
||||
6. r_backend.c
|
||||
|
||||
0. Новый сетевой протоколб смена entity_state_t
|
||||
|
||||
Физика игрока:
|
||||
1. Убрать отскоки от стен
|
||||
2. Исправить код деформации хулла
|
||||
|
|
|
@ -448,7 +448,7 @@ void GUI_LoadWndOptions( wnd_options_t *settings )
|
|||
s_gui.height = w_opts.height;
|
||||
}
|
||||
|
||||
bool GUI_LoadPlatfrom( uint funcname, int argc, char **argv )
|
||||
bool GUI_LoadPlatfrom( int argc, char **argv )
|
||||
{
|
||||
FS_ClearSearchPath();
|
||||
FS_AddGameHierarchy( "bin" );
|
||||
|
@ -849,7 +849,7 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM
|
|||
return DefWindowProc (hwnd, uMessage, wParam, lParam);
|
||||
}
|
||||
|
||||
void InitViewer ( uint funcname, int argc, char **argv )
|
||||
void InitViewer ( int argc, char **argv )
|
||||
{
|
||||
HDC hDC;
|
||||
WNDCLASS wc;
|
||||
|
@ -895,7 +895,7 @@ void InitViewer ( uint funcname, int argc, char **argv )
|
|||
GUI_ResetWndOptions(); // load default settings
|
||||
InitCommonControls ();
|
||||
|
||||
if(GUI_LoadPlatfrom( funcname, argc, argv )) //load config
|
||||
if(GUI_LoadPlatfrom( argc, argv )) //load config
|
||||
{
|
||||
wnd_options_t *config_dat;
|
||||
int config_size;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
//=====================================
|
||||
// main editor funcs
|
||||
//=====================================
|
||||
void InitViewer ( uint funcname, int argc, char **argv );
|
||||
void InitViewer ( int argc, char **argv );
|
||||
void ViewerMain ( void );
|
||||
void FreeViewer ( void );
|
||||
|
||||
|
|
|
@ -1214,7 +1214,7 @@ void PRVM_LoadProgs( const char *filename, int numedfunc, char **ed_func, int nu
|
|||
}
|
||||
else if( vm.prog->progs->crc != vm.prog->filecrc )
|
||||
{
|
||||
PRVM_ERROR("%s: %s system vars have been modified, progdefs.h is out of date %d\n", PRVM_NAME, filename );
|
||||
PRVM_ERROR("%s: %s system vars have been modified, progdefs.h is out of date %d\n", PRVM_NAME, vm.prog->filecrc );
|
||||
}
|
||||
else MsgDev(D_LOAD, "%s [^2CRC %d^7]\n", filename, vm.prog->progs->crc );
|
||||
|
||||
|
|
|
@ -255,7 +255,7 @@ void PR_InitDecompile( const char *name )
|
|||
PR_InitTypes();
|
||||
}
|
||||
|
||||
void PRVM_Init( uint funcname, int argc, char **argv )
|
||||
void PRVM_Init( int argc, char **argv )
|
||||
{
|
||||
char dev_level[4];
|
||||
|
||||
|
@ -263,7 +263,7 @@ void PRVM_Init( uint funcname, int argc, char **argv )
|
|||
com_argv = argv;
|
||||
|
||||
qccpool = Mem_AllocPool( "VM progs" );
|
||||
host_instance = funcname;
|
||||
host_instance = g_Instance;
|
||||
|
||||
if(FS_GetParmFromCmdLine("-dev", dev_level ))
|
||||
prvm_developer = com.atoi(dev_level);
|
||||
|
|
|
@ -551,11 +551,11 @@ word PR_WriteProgdefs( void )
|
|||
|
||||
switch( crc )
|
||||
{
|
||||
case 2740:
|
||||
case 61861:
|
||||
PR_Message("Xash3D unmodified server.dat\n");
|
||||
if(!com.strcmp(progsoutname, "unknown.dat")) com.strcpy(progsoutname, "server.dat");
|
||||
break;
|
||||
case 4546:
|
||||
case 3720:
|
||||
PR_Message("Xash3D unmodified client.dat\n");
|
||||
if(!com.strcmp(progsoutname, "unknown.dat")) com.strcpy(progsoutname, "client.dat");
|
||||
break;
|
||||
|
|
|
@ -179,7 +179,7 @@ const char *(_cdecl *palcGetString )( aldevice *device, int param );
|
|||
void (_cdecl *palcGetIntegerv)( aldevice *device, int param, int size, int *dest );
|
||||
int (_cdecl *palcGetError)( aldevice *device );
|
||||
char (_cdecl *palcIsExtensionPresent)( aldevice *device, const char *extname );
|
||||
void *(_cdecl *palcGetProcAddress)( aldevice *device, const char *funcname );
|
||||
void *(_cdecl *palcGetProcAddress)( aldevice *device, const char *function );
|
||||
int (_cdecl *palcGetEnumValue)( aldevice *device, const char *enumname );
|
||||
|
||||
void (_cdecl *palBufferData)( uint bid, int format, const void* data, int size, int freq );
|
||||
|
|
Reference in New Issue