20 Jan 2008

This commit is contained in:
g-cont 2008-01-20 00:00:00 +03:00 committed by Alibek Omarov
parent b3fa6d6dbd
commit b83219a1ac
22 changed files with 2706 additions and 1096 deletions

View File

@ -35,7 +35,9 @@ physic.dll
13.Билдер коллижн мешей для бсп-моделей OK
14.Переписать трасинг OK
15.Доделать трасинг OK
16.Переписать pmove
16.Переписать pmove OK
17.Переписать player_state_t (избавиться от pmove_state_t) OK
18.Добавить проверку столкновений со сферой
}
Создание sdk_main

View File

@ -38,7 +38,7 @@ float LerpAngle (float a2, float a1, float frac)
float LerpView(float org1, float org2, float ofs1, float ofs2, float frac)
{
return org1 * CL_COORD_FRAC + ofs1 + frac * (org2 * CL_COORD_FRAC + ofs2 - (org1 * CL_COORD_FRAC + ofs1));
return org1 + ofs1 + frac * (org2 + ofs2 - (org1 + ofs1));
}
@ -297,16 +297,16 @@ void CL_ParsePlayerstate (frame_t *oldframe, frame_t *newframe)
flags = MSG_ReadLong(&net_message);//four bytes
// parse the pmove_state_t
if (flags & PS_M_TYPE) state->pmove.pm_type = MSG_ReadByte (&net_message);
if (flags & PS_M_ORIGIN) MSG_ReadPos32(&net_message, state->pmove.origin );
if (flags & PS_M_VELOCITY) MSG_ReadPos32(&net_message, state->pmove.velocity );
if (flags & PS_M_TIME) state->pmove.pm_time = MSG_ReadByte (&net_message);
if (flags & PS_M_FLAGS) state->pmove.pm_flags = MSG_ReadByte (&net_message);
if (flags & PS_M_GRAVITY) state->pmove.gravity = MSG_ReadShort (&net_message);
if (flags & PS_M_DELTA_ANGLES) MSG_ReadPos32(&net_message, state->pmove.delta_angles );
if (flags & PS_M_TYPE) state->pm_type = MSG_ReadByte (&net_message);
if (flags & PS_M_ORIGIN) MSG_ReadPos32(&net_message, state->origin );
if (flags & PS_M_VELOCITY) MSG_ReadPos32(&net_message, state->velocity );
if (flags & PS_M_TIME) state->pm_time = MSG_ReadByte (&net_message);
if (flags & PS_M_FLAGS) state->pm_flags = MSG_ReadByte (&net_message);
if (flags & PS_M_GRAVITY) state->gravity = MSG_ReadShort (&net_message);
if (flags & PS_M_DELTA_ANGLES) MSG_ReadPos32(&net_message, state->delta_angles );
if(cls.state == ca_cinematic || cl.servercount > 0x10000)
state->pmove.pm_type = PM_FREEZE; // demo or movie playback
state->pm_type = PM_FREEZE; // demo or movie playback
// parse the rest of the player_state_t
if (flags & PS_VIEWOFFSET)
@ -332,33 +332,33 @@ void CL_ParsePlayerstate (frame_t *oldframe, frame_t *newframe)
if (flags & PS_WEAPONINDEX)
{
state->gunindex = MSG_ReadByte (&net_message);
state->vmodel.index = MSG_ReadByte (&net_message);
}
if (flags & PS_WEAPONFRAME)
{
state->gunframe = MSG_ReadByte (&net_message);
state->gunoffset[0] = MSG_ReadChar (&net_message)*0.25;
state->gunoffset[1] = MSG_ReadChar (&net_message)*0.25;
state->gunoffset[2] = MSG_ReadChar (&net_message)*0.25;
state->gunangles[0] = MSG_ReadChar (&net_message)*0.25;
state->gunangles[1] = MSG_ReadChar (&net_message)*0.25;
state->gunangles[2] = MSG_ReadChar (&net_message)*0.25;
state->vmodel.frame = MSG_ReadByte (&net_message);
state->vmodel.offset[0] = MSG_ReadChar (&net_message)*0.25;
state->vmodel.offset[1] = MSG_ReadChar (&net_message)*0.25;
state->vmodel.offset[2] = MSG_ReadChar (&net_message)*0.25;
state->vmodel.angles[0] = MSG_ReadChar (&net_message)*0.25;
state->vmodel.angles[1] = MSG_ReadChar (&net_message)*0.25;
state->vmodel.angles[2] = MSG_ReadChar (&net_message)*0.25;
}
if (flags & PS_WEAPONSEQUENCE)
{
state->sequence = MSG_ReadByte (&net_message);
state->vmodel.sequence = MSG_ReadByte (&net_message);
}
if (flags & PS_WEAPONBODY)
{
state->gunbody = MSG_ReadByte (&net_message);
state->vmodel.body = MSG_ReadByte (&net_message);
}
if (flags & PS_WEAPONSKIN)
{
state->gunskin = MSG_ReadByte (&net_message);
state->vmodel.skin = MSG_ReadByte (&net_message);
}
if (flags & PS_BLEND)
@ -373,7 +373,7 @@ void CL_ParsePlayerstate (frame_t *oldframe, frame_t *newframe)
state->fov = MSG_ReadByte (&net_message);
if (flags & PS_RDFLAGS)
state->rdflags = MSG_ReadByte (&net_message);
state->effects = MSG_ReadByte (&net_message);
// parse stats
statbits = MSG_ReadLong (&net_message);
@ -494,7 +494,7 @@ void CL_ParseFrame (void)
{
cls.state = ca_active;
cl.force_refdef = true;
VectorScale( cl.frame.playerstate.pmove.origin, CL_COORD_FRAC, cl.predicted_origin );
VectorCopy( cl.frame.playerstate.origin, cl.predicted_origin );
VectorCopy( cl.frame.playerstate.viewangles, cl.predicted_angles );
}
// fire entity events
@ -739,14 +739,14 @@ void CL_AddViewWeapon (player_state_t *ps, player_state_t *ops)
memset (&gun, 0, sizeof(gun));
if (gun_model) gun.model = gun_model; // development tool
else gun.model = cl.model_draw[ps->gunindex];
else gun.model = cl.model_draw[ps->vmodel.index];
if (!gun.model) return;
// set up gun position
for (i = 0; i < 3; i++)
{
gun.origin[i] = cl.refdef.vieworg[i] + ops->gunoffset[i] + cl.lerpfrac * (ps->gunoffset[i] - ops->gunoffset[i]);
gun.angles[i] = cl.refdef.viewangles[i] + LerpAngle (ops->gunangles[i], ps->gunangles[i], cl.lerpfrac);
gun.origin[i] = cl.refdef.vieworg[i] + ops->vmodel.offset[i] + cl.lerpfrac * (ps->vmodel.offset[i] - ops->vmodel.offset[i]);
gun.angles[i] = cl.refdef.viewangles[i] + LerpAngle (ops->vmodel.angles[i], ps->vmodel.angles[i], cl.lerpfrac);
}
if (gun_frame)
@ -756,14 +756,14 @@ void CL_AddViewWeapon (player_state_t *ps, player_state_t *ops)
}
else
{
gun.frame = ps->gunframe;
gun.frame = ps->vmodel.frame;
if (gun.frame == 0) gun.prev.frame = 0; // just changed weapons, don't lerp from old
else gun.prev.frame = ops->gunframe;
else gun.prev.frame = ops->vmodel.frame;
}
gun.body = ps->gunbody;
gun.skin = ps->gunskin;
gun.sequence = ps->sequence;
gun.body = ps->vmodel.body;
gun.skin = ps->vmodel.skin;
gun.sequence = ps->vmodel.sequence;
gun.flags = RF_MINLIGHT | RF_DEPTHHACK | RF_WEAPONMODEL;
gun.backlerp = 1.0 - cl.lerpfrac;
@ -796,16 +796,16 @@ void CL_CalcViewValues (void)
ops = &oldframe->playerstate;
// see if the player entity was teleported this frame
if (fabs(ops->pmove.origin[0] - ps->pmove.origin[0]) > 2048
|| fabs(ops->pmove.origin[1] - ps->pmove.origin[1]) > 2048
|| fabs(ops->pmove.origin[2] - ps->pmove.origin[2]) > 2048)
if (fabs(ops->origin[0] - ps->origin[0]) > 2048
|| fabs(ops->origin[1] - ps->origin[1]) > 2048
|| fabs(ops->origin[2] - ps->origin[2]) > 2048)
ops = ps; // don't interpolate
ent = &cl_entities[cl.playernum+1];
lerp = cl.lerpfrac;
// calculate the origin
if ((cl_predict->value) && !(cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
if ((cl_predict->value) && !(cl.frame.playerstate.pm_flags & PMF_NO_PREDICTION))
{
// use predicted values
float delta;
@ -826,11 +826,11 @@ void CL_CalcViewValues (void)
else
{ // just use interpolated values
for (i = 0; i < 3; i++)
cl.refdef.vieworg[i] = LerpView( ops->pmove.origin[i], ps->pmove.origin[i], ops->viewoffset[i], ps->viewoffset[i], lerp );
cl.refdef.vieworg[i] = LerpView( ops->origin[i], ps->origin[i], ops->viewoffset[i], ps->viewoffset[i], lerp );
}
// if not running a demo or on a locked frame, add the local angle movement
if ( cl.frame.playerstate.pmove.pm_type < PM_DEAD )
if ( cl.frame.playerstate.pm_type < PM_DEAD )
{
// use predicted values
for (i = 0; i < 3; i++) cl.refdef.viewangles[i] = cl.predicted_angles[i];

View File

@ -583,7 +583,7 @@ void CL_ClampPitch (void)
{
float pitch;
pitch = SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[PITCH]);
pitch = SHORT2ANGLE(cl.frame.playerstate.delta_angles[PITCH]);
if (pitch > 180) pitch -= 360;
if (cl.viewangles[PITCH] + pitch < -360) cl.viewangles[PITCH] += 360; // wrapped
@ -663,7 +663,7 @@ usercmd_t CL_CreateCmd (void)
void IN_CenterView (void)
{
cl.viewangles[PITCH] = -SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[PITCH]);
cl.viewangles[PITCH] = -SHORT2ANGLE(cl.frame.playerstate.delta_angles[PITCH]);
}
/*

View File

@ -29,10 +29,9 @@ void CL_CheckPredictionError (void)
{
int frame;
int delta[3];
int i;
int len;
if (!cl_predict->value || (cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
if (!cl_predict->value || (cl.frame.playerstate.pm_flags & PMF_NO_PREDICTION))
return;
// calculate the last usercmd_t we sent that the server has processed
@ -40,7 +39,7 @@ void CL_CheckPredictionError (void)
frame &= (CMD_BACKUP-1);
// compare what the server returned with what we had predicted it to be
VectorSubtract (cl.frame.playerstate.pmove.origin, cl.predicted_origins[frame], delta);
VectorSubtract (cl.frame.playerstate.origin, cl.predicted_origins[frame], delta);
// save the prediction error for interpolation
len = abs(delta[0]) + abs(delta[1]) + abs(delta[2]);
@ -53,10 +52,10 @@ void CL_CheckPredictionError (void)
if (cl_showmiss->value && (delta[0] || delta[1] || delta[2]))
Msg ("prediction miss on %i: %i\n", cl.frame.serverframe, delta[0] + delta[1] + delta[2]);
VectorCopy (cl.frame.playerstate.pmove.origin, cl.predicted_origins[frame]);
VectorCopy (cl.frame.playerstate.origin, cl.predicted_origins[frame]);
// save for error itnerpolation
for (i = 0; i < 3; i++) cl.prediction_error[i] = delta[i] * CL_COORD_FRAC;
VectorCopy( delta, cl.prediction_error );
}
}
@ -85,7 +84,7 @@ void CL_ClipMoveToEntities ( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end,
if(!ent->solid) continue;
if(ent->number == cl.playernum + 1) continue;
if( ent->solid == 31 )
if( ent->solid == SOLID_BMODEL )
{
// special value for bmodel
cmodel = cl.model_clip[ent->modelindex];
@ -94,9 +93,9 @@ void CL_ClipMoveToEntities ( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end,
}
else
{ // encoded bbox
x = 8*(ent->solid & 31);
zd = 8*((ent->solid>>5) & 31);
zu = 8*((ent->solid>>10) & 63) - 32;
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;
@ -157,7 +156,7 @@ int CL_PMpointcontents( vec3_t point )
num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
ent = &cl_parse_entities[num];
if (ent->solid != 31) // special value for bmodel
if (ent->solid != SOLID_BMODEL) // special value for bmodel
continue;
cmodel = cl.model_clip[ent->modelindex];
@ -190,12 +189,12 @@ void CL_PredictMovement (void)
if(cls.state != ca_active) return;
if(cl_paused->value) return;
if (!cl_predict->value || (cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
if (!cl_predict->value || (cl.frame.playerstate.pm_flags & PMF_NO_PREDICTION))
{
// just set angles
for (i = 0; i < 3; i++)
{
cl.predicted_angles[i] = cl.viewangles[i] + SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[i]);
cl.predicted_angles[i] = cl.viewangles[i] + SHORT2ANGLE(cl.frame.playerstate.delta_angles[i]);
}
return;
}
@ -218,7 +217,7 @@ void CL_PredictMovement (void)
pm_airaccelerate = atof(cl.configstrings[CS_AIRACCEL]);
pm.s = cl.frame.playerstate.pmove;
pm.ps = cl.frame.playerstate;
// SCR_DebugGraph (current - ack - 1, COLOR_0);
@ -234,19 +233,19 @@ void CL_PredictMovement (void)
Pmove (&pm);
// save for debug checking
VectorCopy (pm.s.origin, cl.predicted_origins[frame]);
VectorCopy (pm.ps.origin, cl.predicted_origins[frame]);
}
oldframe = (ack-2) & (CMD_BACKUP-1);
oldz = cl.predicted_origins[oldframe][2];
step = pm.s.origin[2] - oldz;
if (step > 63 && step < 160 && (pm.s.pm_flags & PMF_ON_GROUND))
step = pm.ps.origin[2] - oldz;
if (step > 63 && step < 160 )//&& (pm.ps.pm_flags & PMF_ON_GROUND))
{
cl.predicted_step = step;
cl.predicted_step_time = cls.realtime - cls.frametime * 0.5f;
}
// copy results out for rendering
VectorScale(pm.s.origin, CL_COORD_FRAC, cl.predicted_origin);
VectorCopy(pm.viewangles, cl.predicted_angles);
VectorCopy(pm.ps.origin, cl.predicted_origin);
VectorCopy(pm.ps.viewangles, cl.predicted_angles);
}

View File

@ -20,7 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// cl_view.c -- player rendering positioning
#include "client.h"
#include "collision.h"
//=============
//
@ -505,7 +504,7 @@ void V_RenderView( void )
cl.refdef.dlights = r_dlights;
cl.refdef.lightstyles = r_lightstyles;
cl.refdef.rdflags = cl.frame.playerstate.rdflags;
cl.refdef.rdflags = cl.frame.playerstate.effects;
// sort entities for better cache locality
qsort( cl.refdef.entities, cl.refdef.num_entities, sizeof( cl.refdef.entities[0] ), (int (*)(const void *, const void *))entitycmpfnc );

View File

@ -20,7 +20,7 @@
#include "net_msg.h"
#include "screen.h"
#include "keycodes.h"
#include "collision.h"
#include "pmove.h"
extern stdlib_api_t com;
extern physic_exp_t *pe;

View File

@ -102,7 +102,7 @@ void _MSG_WriteUnterminatedString (sizebuf_t *sb, const char *s, const char *fil
void _MSG_WriteCoord16(sizebuf_t *sb, float f, const char *filename, int fileline)
{
_MSG_WriteShort(sb, (int)(f * SV_COORD_FRAC), filename, fileline );
_MSG_WriteShort(sb, (int)(f * 8.0f), filename, fileline );
}
void _MSG_WriteAngle16 (sizebuf_t *sb, float f, const char *filename, int fileline)
@ -238,55 +238,67 @@ void _MSG_WriteDeltaEntity (entity_state_t *from, entity_state_t *to, sizebuf_t
if (bits & 0xff000000)
{
_MSG_WriteByte (msg, (bits >> 8 ) & 255, filename, fileline );
_MSG_WriteByte (msg, (bits >> 16) & 255, filename, fileline );
_MSG_WriteByte (msg, (bits >> 24) & 255, filename, fileline );
MSG_WriteByte (msg, (bits >> 8 ) & 255 );
MSG_WriteByte (msg, (bits >> 16) & 255 );
MSG_WriteByte (msg, (bits >> 24) & 255 );
}
else if (bits & 0x00ff0000)
{
_MSG_WriteByte (msg, (bits >> 8 ) & 255, filename, fileline );
_MSG_WriteByte (msg, (bits >> 16) & 255, filename, fileline );
MSG_WriteByte (msg, (bits >> 8 ) & 255 );
MSG_WriteByte (msg, (bits >> 16) & 255 );
}
else if (bits & 0x0000ff00)
{
_MSG_WriteByte (msg, (bits >> 8 ) & 255, filename, fileline );
MSG_WriteByte (msg, (bits >> 8 ) & 255 );
}
//----------
if (bits & U_NUMBER16) _MSG_WriteShort (msg, to->number, filename, fileline );
if (bits & U_NUMBER16)
{
MSG_WriteShort (msg, to->number );
}
else _MSG_WriteByte (msg, to->number, filename, fileline);
if (bits & U_MODEL) _MSG_WriteShort (msg, to->modelindex, filename, fileline);
if (bits & U_MODEL) MSG_WriteShort (msg, to->modelindex );
if (bits & U_WEAPONMODEL) _MSG_WriteShort (msg, to->weaponmodel, filename, fileline);
if (bits & U_FRAME8) _MSG_WriteByte (msg, to->frame, filename, fileline);
if (bits & U_FRAME16) _MSG_WriteShort (msg, to->frame, filename, fileline);
if (bits & U_FRAME16) MSG_WriteShort (msg, to->frame );
if (bits & U_SKIN8 ) _MSG_WriteByte (msg, to->skin, filename, fileline);
if (bits & U_SKIN16) _MSG_WriteShort (msg, to->skin, filename, fileline);
if (bits & U_SKIN16)
{
MSG_WriteShort( msg, to->skin );
}
if ( (bits & (U_EFFECTS8|U_EFFECTS16)) == (U_EFFECTS8|U_EFFECTS16))
_MSG_WriteLong (msg, to->effects, filename, fileline);
else if (bits & U_EFFECTS8) _MSG_WriteByte (msg, to->effects, filename, fileline);
else if (bits & U_EFFECTS16) _MSG_WriteShort (msg, to->effects, filename, fileline);
else if (bits & U_EFFECTS16)
{
MSG_WriteShort( msg, to->effects );
}
if ( (bits & (U_RENDERFX8|U_RENDERFX16)) == (U_RENDERFX8|U_RENDERFX16))
_MSG_WriteLong (msg, to->renderfx, filename, fileline);
else if (bits & U_RENDERFX8) _MSG_WriteByte (msg, to->renderfx, filename, fileline);
else if (bits & U_RENDERFX16) _MSG_WriteShort (msg, to->renderfx, filename, fileline);
else if (bits & U_RENDERFX16)
{
MSG_WriteShort( msg, to->renderfx );
}
if (bits & U_ORIGIN1) _MSG_WriteCoord32(msg, to->origin[0], filename, fileline);
if (bits & U_ORIGIN2) _MSG_WriteCoord32(msg, to->origin[1], filename, fileline);
if (bits & U_ORIGIN3) _MSG_WriteCoord32(msg, to->origin[2], filename, fileline);
if (bits & U_ORIGIN1) MSG_WriteCoord32(msg, to->origin[0]);
if (bits & U_ORIGIN2) MSG_WriteCoord32(msg, to->origin[1]);
if (bits & U_ORIGIN3) MSG_WriteCoord32(msg, to->origin[2]);
if (bits & U_ANGLE1) _MSG_WriteAngle32(msg, to->angles[0], filename, fileline);
if (bits & U_ANGLE2) _MSG_WriteAngle32(msg, to->angles[1], filename, fileline);
if (bits & U_ANGLE3) _MSG_WriteAngle32(msg, to->angles[2], filename, fileline);
if (bits & U_ANGLE1) MSG_WriteAngle32(msg, to->angles[0]);
if (bits & U_ANGLE2) MSG_WriteAngle32(msg, to->angles[1]);
if (bits & U_ANGLE3) MSG_WriteAngle32(msg, to->angles[2]);
if (bits & U_OLDORIGIN) _MSG_WritePos32(msg, to->old_origin, filename, fileline);
if (bits & U_SEQUENCE) _MSG_WriteByte (msg, to->sequence, filename, fileline);
if (bits & U_SOLID) _MSG_WriteShort (msg, to->solid, filename, fileline);
if (bits & U_SOLID)
{
MSG_WriteLong( msg, to->solid );
}
if (bits & U_ALPHA) _MSG_WriteFloat (msg, to->alpha, filename, fileline);
if (bits & U_EVENT) _MSG_WriteByte (msg, to->event, filename, fileline);
if (bits & U_SOUNDIDX) _MSG_WriteByte (msg, to->soundindex, filename, fileline);
@ -434,7 +446,7 @@ char *MSG_ReadStringLine (sizebuf_t *msg_read)
float MSG_ReadCoord16(sizebuf_t *msg_read)
{
return MSG_ReadShort(msg_read) * CL_COORD_FRAC;
return MSG_ReadShort(msg_read) * 0.125f;
}
float MSG_ReadCoord32(sizebuf_t *msg_read)
@ -526,7 +538,7 @@ void MSG_ReadDeltaEntity(entity_state_t *from, entity_state_t *to, int number, i
if (bits & U_OLDORIGIN) MSG_ReadPos32(&net_message, to->old_origin);
if (bits & U_SEQUENCE) to->sequence = MSG_ReadByte(&net_message);
if (bits & U_SOLID) to->solid = MSG_ReadShort(&net_message);
if (bits & U_SOLID) to->solid = MSG_ReadLong(&net_message);
if (bits & U_ALPHA) to->alpha = MSG_ReadFloat(&net_message);
if (bits & U_EVENT) to->event = MSG_ReadByte (&net_message);
if (bits & U_SOUNDIDX) to->soundindex = MSG_ReadByte (&net_message);

View File

@ -55,30 +55,6 @@ typedef enum
MSG_PVS_R,
} msgtype_t;
// pmove_state_t is the information necessary for client side movement
#define PM_NORMAL 0 // can accelerate and turn
#define PM_SPECTATOR 1
#define PM_DEAD 2 // no acceleration or turning
#define PM_GIB 3 // different bounding box
#define PM_FREEZE 4
// this structure needs to be communicated bit-accurate
// from the server to the client to guarantee that
// prediction stays in sync, so no floats are used.
// if any part of the game code modifies this struct, it
// will result in a prediction error of some degree.
typedef struct
{
byte pm_type;
vec3_t origin; //
vec3_t velocity; //
byte pm_flags; // ducked, jump_held, etc
byte pm_time; // each unit = 8 ms
short gravity;
vec3_t delta_angles; // add to command angles to get view direction
// changed by spawns, rotating objects, and teleporters
} pmove_state_t;
#define PS_M_TYPE (1<<0)
#define PS_M_ORIGIN (1<<1)
#define PS_M_VELOCITY (1<<2)
@ -98,33 +74,6 @@ typedef struct
#define PS_WEAPONSKIN (1<<16)
#define PS_RDFLAGS (1<<17)
// player_state_t communication
typedef struct
{
pmove_state_t pmove; // for prediction
// these fields do not need to be communicated bit-precise
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
// set by weapon kicks, pain effects, etc
vec3_t gunangles;
vec3_t gunoffset;
int gunindex;
int gunframe; // studio frame
int sequence; // stuido animation sequence
int gunbody;
int gunskin;
float blend[4]; // rgba full screen effect
float fov; // horizontal field of view
int rdflags; // refdef flags
short stats[32]; // fast status bar updates
} player_state_t;
// ms and light always sent, the others are optional
#define CM_ANGLE1 (1<<0)
#define CM_ANGLE2 (1<<1)
@ -161,17 +110,6 @@ enum player_stats
MAX_STATS = 32,
};
// user_cmd_t communication
typedef struct usercmd_s
{
byte msec;
byte buttons;
short angles[3];
short forwardmove, sidemove, upmove;
byte impulse; // remove?
byte lightlevel; // light level the player is standing on
} usercmd_t;
// dmflags->value flags
#define DF_NO_HEALTH 0x00000001 // 1
#define DF_NO_ITEMS 0x00000002 // 2
@ -191,34 +129,6 @@ typedef struct usercmd_s
#define DF_FIXED_FOV 0x00008000 // 32768
#define DF_QUADFIRE_DROP 0x00010000 // 65536
#define MAXTOUCH 32
typedef struct
{
pmove_state_t s; // state (in / out)
// command (in)
usercmd_t cmd;
bool snapinitial; // if s has been changed outside pmove
// results (out)
int numtouch;
edict_t *touchents[MAXTOUCH];
vec3_t viewangles; // clamped
float viewheight;
vec3_t mins, maxs; // bounding box size
edict_t *groundentity;
int watertype;
int waterlevel;
// callbacks to test the world
trace_t (*trace) (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end);
int (*pointcontents) (vec3_t point);
} pmove_t;
// try to pack the common update flags into the first byte
#define U_ORIGIN1 (1<<0)
#define U_ORIGIN2 (1<<1)

File diff suppressed because it is too large Load Diff

1204
engine/pmove.c.old Normal file

File diff suppressed because it is too large Load Diff

145
engine/pmove.h Normal file
View File

@ -0,0 +1,145 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// pmove.h - base player physic
//=======================================================================
#ifndef COLLISION_H
#define COLLISION_H
// encoded bmodel mask
#define SOLID_BMODEL 0xffffff
// 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_DEADSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW)
#define MASK_MONSTERSOLID (CONTENTS_SOLID|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER)
#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_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
#define PM_NORMAL 0 // can accelerate and turn
#define PM_SPECTATOR 1
#define PM_DEAD 2 // no acceleration or turning
#define PM_GIB 3 // different bounding box
#define PM_FREEZE 4
#define PM_INTERMISSION 5
#define PM_NOCLIP 6
// pmove->pm_flags
#define PMF_DUCKED 1
#define PMF_JUMP_HELD 2
#define PMF_ON_GROUND 4
#define PMF_TIME_WATERJUMP 8 // pm_time is waterjump
#define PMF_TIME_LAND 16 // pm_time is time before rejump
#define PMF_TIME_TELEPORT 32 // pm_time is non-moving time
#define PMF_NO_PREDICTION 64 // temporarily disables prediction (used for grappling hook)
#define PMF_ALL_TIMES (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_TELEPORT)
// viewmodel state
typedef struct
{
int index; // client modelindex
vec3_t angles; // can be some different with viewangles
vec3_t offset; // center offset
int sequence; // studio animation sequence
int frame; // studio frame
int body; // weapon body
int skin; // weapon skin
} vmodel_state_t;
// thirdperson model state
typedef struct
{
int index; // client modelindex
int sequence; // studio animation sequence
int frame; // studio frame
} pmodel_state_t;
// player_state_t communication
typedef struct
{
int bobcycle; // for view bobbing and footstep generation
float bobtime;
byte pm_type; // player movetype
byte pm_flags; // ducked, jump_held, etc
byte pm_time; // each unit = 8 ms
vec3_t origin;
vec3_t velocity;
vec3_t delta_angles; // add to command angles to get view direction
short gravity; // gravity value
short speed; // maxspeed
edict_t *groundentity; // current ground entity
int viewheight; // height over ground
int effects; // copied to entity_state_t->effects
int weapon; // copied to entity_state_t->weapon
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
short stats[MAX_STATS];
float fov; // horizontal field of view
// player model and viewmodel
vmodel_state_t vmodel;
pmodel_state_t pmodel;
} player_state_t;
// user_cmd_t communication
typedef struct usercmd_s
{
byte msec;
byte buttons;
short angles[3];
byte impulse; // remove?
byte lightlevel; // light level the player is standing on
short forwardmove, sidemove, upmove;
} usercmd_t;
#define MAXTOUCH 32
typedef struct
{
player_state_t ps; // state (in / out)
// command (in)
usercmd_t cmd;
// results (out)
int numtouch;
edict_t *touchents[MAXTOUCH];
vec3_t mins, maxs; // bounding box size
int watertype;
int waterlevel;
float xyspeed; // avoid to compute it twice
// callbacks to test the world
trace_t (*trace)( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end );
int (*pointcontents)( vec3_t point );
} pmove_t;
/*
==============================================================
PLAYER MOVEMENT CODE
Common between server and client so prediction matches
==============================================================
*/
// button bits
#define BUTTON_ATTACK 1
#define BUTTON_USE 2
#define BUTTON_ATTACK2 4
#define BUTTONS_ATTACK (BUTTON_ATTACK | BUTTON_ATTACK2)
#define BUTTON_ANY 128 // any key whatsoever
extern float pm_airaccelerate;
void Pmove( pmove_t *pmove );
#endif//COLLISION_H

View File

@ -29,6 +29,7 @@ The code uses void pointers instead.
#ifndef PROGSVM_H
#define PROGSVM_H
#include "pmove.h"
#include "sv_edict.h" // server progs
#include "cl_edict.h" // client progs
#include "ui_edict.h" // uimenu progs

View File

@ -23,7 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "progsvm.h"
#include "net_msg.h"
#include "collision.h"
#include "mathlib.h"
//=============================================================================

View File

@ -22,14 +22,6 @@
#define AI_SPECTATOR (1<<12) // spectator mode for clients
#define AI_WATERJUMP (1<<13) // npc or player take out of water
// link_t is only used for entity area links now
typedef struct link_s
{
struct link_s *prev;
struct link_s *next;
int entnum; // get edict by number
} link_t;
typedef struct worldsector_s
{
int axis; // -1 = leaf node
@ -42,14 +34,6 @@ struct gclient_s
{
player_state_t ps; // communicated by server to clients
int ping;
pmove_state_t old_pmove; // for detecting out-of-pmove changes
vec3_t v_angle; // aiming direction
vec3_t oldviewangles;
vec3_t oldvelocity;
float bobtime; // so off-ground doesn't change it
};
struct sv_edict_s
@ -61,7 +45,6 @@ struct sv_edict_s
// sv_private_edict_t
worldsector_t *worldsector; // member of current wolrdsector
struct sv_edict_s *nextedict; // next edict in world sector
link_t area; // linked to a division node or leaf
int clipmask; // trace info
int lastcluster; // unused if num_clusters != -1
int linkcount;

View File

@ -20,7 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "engine.h"
#include "server.h"
#include "collision.h"
/*
=============================================================================
@ -167,13 +166,13 @@ void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, size
else ops = &from->ps;
// determine what needs to be sent
if (ps->pmove.pm_type != ops->pmove.pm_type) pflags |= PS_M_TYPE;
if(!VectorCompare(ps->pmove.origin, ops->pmove.origin)) pflags |= PS_M_ORIGIN;
if(!VectorCompare(ps->pmove.velocity, ops->pmove.velocity)) pflags |= PS_M_VELOCITY;
if (ps->pmove.pm_time != ops->pmove.pm_time) pflags |= PS_M_TIME;
if (ps->pmove.pm_flags != ops->pmove.pm_flags) pflags |= PS_M_FLAGS;
if (ps->pmove.gravity != ops->pmove.gravity) pflags |= PS_M_GRAVITY;
if(!VectorCompare(ps->pmove.delta_angles, ops->pmove.delta_angles)) pflags |= PS_M_DELTA_ANGLES;
if (ps->pm_type != ops->pm_type) pflags |= PS_M_TYPE;
if(!VectorCompare(ps->origin, ops->origin)) pflags |= PS_M_ORIGIN;
if(!VectorCompare(ps->velocity, ops->velocity)) pflags |= PS_M_VELOCITY;
if (ps->pm_time != ops->pm_time) pflags |= PS_M_TIME;
if (ps->pm_flags != ops->pm_flags) pflags |= PS_M_FLAGS;
if (ps->gravity != ops->gravity) pflags |= PS_M_GRAVITY;
if(!VectorCompare(ps->delta_angles, ops->delta_angles)) pflags |= PS_M_DELTA_ANGLES;
if(!VectorCompare(ps->viewoffset, ops->viewoffset)) pflags |= PS_VIEWOFFSET;
if(!VectorCompare(ps->viewangles, ops->viewangles)) pflags |= PS_VIEWANGLES;
if(!VectorCompare(ps->kick_angles, ops->kick_angles)) pflags |= PS_KICKANGLES;
@ -182,11 +181,11 @@ void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, size
pflags |= PS_BLEND;
if (ps->fov != ops->fov) pflags |= PS_FOV;
if (ps->rdflags != ops->rdflags) pflags |= PS_RDFLAGS;
if (ps->gunframe != ops->gunframe) pflags |= PS_WEAPONFRAME;
if (ps->sequence != ops->sequence) pflags |= PS_WEAPONSEQUENCE;
if (ps->gunbody != ops->gunbody) pflags |= PS_WEAPONBODY;
if (ps->gunskin != ops->gunskin) pflags |= PS_WEAPONSKIN;
if (ps->effects != ops->effects) pflags |= PS_RDFLAGS;
if (ps->vmodel.frame != ops->vmodel.frame) pflags |= PS_WEAPONFRAME;
if (ps->vmodel.sequence != ops->vmodel.sequence) pflags |= PS_WEAPONSEQUENCE;
if (ps->vmodel.body != ops->vmodel.body) pflags |= PS_WEAPONBODY;
if (ps->vmodel.skin != ops->vmodel.skin) pflags |= PS_WEAPONSKIN;
pflags |= PS_WEAPONINDEX;
@ -195,14 +194,14 @@ void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, size
MSG_WriteLong (msg, pflags);
// write the pmove_state_t
if (pflags & PS_M_TYPE) MSG_WriteByte (msg, ps->pmove.pm_type);
if (pflags & PS_M_TYPE) MSG_WriteByte (msg, ps->pm_type);
if (pflags & PS_M_ORIGIN) MSG_WritePos32(msg, ps->pmove.origin);
if (pflags & PS_M_VELOCITY) MSG_WritePos32(msg, ps->pmove.velocity);
if (pflags & PS_M_TIME) MSG_WriteByte (msg, ps->pmove.pm_time);
if (pflags & PS_M_FLAGS) MSG_WriteByte (msg, ps->pmove.pm_flags);
if (pflags & PS_M_GRAVITY) MSG_WriteShort (msg, ps->pmove.gravity);
if (pflags & PS_M_DELTA_ANGLES) MSG_WritePos32(msg, ps->pmove.delta_angles);
if (pflags & PS_M_ORIGIN) MSG_WritePos32(msg, ps->origin);
if (pflags & PS_M_VELOCITY) MSG_WritePos32(msg, ps->velocity);
if (pflags & PS_M_TIME) MSG_WriteByte (msg, ps->pm_time);
if (pflags & PS_M_FLAGS) MSG_WriteByte (msg, ps->pm_flags);
if (pflags & PS_M_GRAVITY) MSG_WriteShort (msg, ps->gravity);
if (pflags & PS_M_DELTA_ANGLES) MSG_WritePos32(msg, ps->delta_angles);
//
// write the rest of the player_state_t
@ -230,33 +229,33 @@ void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, size
if (pflags & PS_WEAPONINDEX)
{
MSG_WriteByte (msg, ps->gunindex);
MSG_WriteByte (msg, ps->vmodel.index);
}
if (pflags & PS_WEAPONFRAME)
{
MSG_WriteByte (msg, ps->gunframe);
MSG_WriteChar (msg, ps->gunoffset[0]*4);
MSG_WriteChar (msg, ps->gunoffset[1]*4);
MSG_WriteChar (msg, ps->gunoffset[2]*4);
MSG_WriteChar (msg, ps->gunangles[0]*4);
MSG_WriteChar (msg, ps->gunangles[1]*4);
MSG_WriteChar (msg, ps->gunangles[2]*4);
MSG_WriteByte (msg, ps->vmodel.frame);
MSG_WriteChar (msg, ps->vmodel.offset[0]*4);
MSG_WriteChar (msg, ps->vmodel.offset[1]*4);
MSG_WriteChar (msg, ps->vmodel.offset[2]*4);
MSG_WriteChar (msg, ps->vmodel.angles[0]*4);
MSG_WriteChar (msg, ps->vmodel.angles[1]*4);
MSG_WriteChar (msg, ps->vmodel.angles[2]*4);
}
if (pflags & PS_WEAPONSEQUENCE)
{
MSG_WriteByte (msg, ps->sequence);
MSG_WriteByte (msg, ps->vmodel.sequence);
}
if (pflags & PS_WEAPONBODY)
{
MSG_WriteByte (msg, ps->gunbody);
MSG_WriteByte (msg, ps->vmodel.body);
}
if (pflags & PS_WEAPONSKIN)
{
MSG_WriteByte (msg, ps->gunskin);
MSG_WriteByte (msg, ps->vmodel.skin);
}
if (pflags & PS_BLEND)
@ -269,7 +268,7 @@ void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, size
if (pflags & PS_FOV)
MSG_WriteByte (msg, ps->fov);
if (pflags & PS_RDFLAGS)
MSG_WriteByte (msg, ps->rdflags);
MSG_WriteByte (msg, ps->effects);
// send stats
statbits = 0;
@ -339,55 +338,6 @@ Build a client frame structure
=============================================================================
*/
byte fatpvs[MAX_MAP_LEAFS/8]; // 32767 is MAX_MAP_LEAFS
/*
============
SV_FatPVS
The client will interpolate the view position,
so we can't use a single PVS point
===========
*/
void SV_FatPVS (vec3_t org)
{
int leafs[64];
int i, j, count;
int longs;
byte *src;
vec3_t mins, maxs;
for (i = 0; i < 3; i++)
{
mins[i] = org[i] - SV_COORD_FRAC;
maxs[i] = org[i] + SV_COORD_FRAC;
}
count = pe->BoxLeafnums (mins, maxs, leafs, 64, NULL);
if (count < 1) Host_Error("SV_FatPVS: count < 1\n");
longs = (pe->NumClusters()+31)>>5;
// convert leafs to clusters
for (i = 0; i < count; i++) leafs[i] = pe->LeafCluster(leafs[i]);
Mem_Copy(fatpvs, pe->ClusterPVS(leafs[0]), longs<<2);
// or in all the other leaf bits
for (i = 1; i < count; i++)
{
for (j = 0; j < i; j++)
{
if (leafs[i] == leafs[j])
break;
}
if (j != i) continue; // already have the cluster we want
src = pe->ClusterPVS(leafs[i]);
for (j = 0; j < longs; j++) ((long *)fatpvs)[j] |= ((long *)src)[j];
}
}
/*
=============
SV_BuildClientFrame
@ -421,7 +371,7 @@ void SV_BuildClientFrame (client_state_t *client)
frame->senttime = svs.realtime; // save it for ping calc later
// find the client's PVS
VectorScale( clent->priv.sv->client->ps.pmove.origin, CL_COORD_FRAC, org );
VectorCopy( clent->priv.sv->client->ps.origin, org );
VectorAdd( org, clent->priv.sv->client->ps.viewoffset, org );
leafnum = pe->PointLeafnum (org);

View File

@ -18,9 +18,9 @@ be accurate for client side prediction
*/
void SV_ClampCoord( vec3_t coord )
{
coord[0] -= SV_COORD_FRAC * floor(coord[0] * CL_COORD_FRAC);
coord[1] -= SV_COORD_FRAC * floor(coord[1] * CL_COORD_FRAC);
coord[2] -= SV_COORD_FRAC * floor(coord[2] * CL_COORD_FRAC);
coord[0] -= floor(coord[0]);
coord[1] -= floor(coord[1]);
coord[2] -= floor(coord[2]);
}
void SV_ClampAngle( vec3_t angle )
@ -1219,7 +1219,7 @@ void SV_WalkMove (edict_t *ent)
if (clip & 2)
{
// if move was not trying to move into the step, return
if (fabs(start_velocity[0]) < 0.125 && fabs(start_velocity[1]) < CL_COORD_FRAC)
if (fabs(start_velocity[0]) < 0.125 && fabs(start_velocity[1]) < 0.125)
return;
if (ent->progs.sv->movetype != MOVETYPE_FLY)
@ -1253,7 +1253,7 @@ void SV_WalkMove (edict_t *ent)
// check for stuckness, possibly due to the limited precision of floats
// in the clipping hulls
if (clip && fabs(originalmove_origin[1] - ent->progs.sv->origin[1]) < CL_COORD_FRAC && fabs(originalmove_origin[0] - ent->progs.sv->origin[0]) < CL_COORD_FRAC)
if (clip && fabs(originalmove_origin[1] - ent->progs.sv->origin[1]) < 0.125 && fabs(originalmove_origin[0] - ent->progs.sv->origin[0]) < 0.125)
{
//Msg("wall\n");
// stepping up didn't make any progress, revert to original move
@ -1273,7 +1273,7 @@ void SV_WalkMove (edict_t *ent)
if (clip & 2) SV_WallFriction (ent, stepnormal);
}
// skip out if stepdown is enabled, moving downward, not in water, and the move started onground and ended offground
else if (ent->progs.sv->waterlevel < 2 && start_velocity[2] < CL_COORD_FRAC && oldonground && !((int)ent->progs.sv->aiflags & AI_ONGROUND))
else if (ent->progs.sv->waterlevel < 2 && start_velocity[2] < 0.125 && oldonground && !((int)ent->progs.sv->aiflags & AI_ONGROUND))
return;
// move down

View File

@ -11,6 +11,11 @@ trace_t PM_trace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
return SV_Trace (start, mins, maxs, end, pm_passent, MASK_DEADSOLID);
}
int PM_pointcontents( vec3_t point )
{
return SV_PointContents( point, pm_passent );
}
/*
===========
PutClientInServer
@ -44,11 +49,11 @@ void SV_PutClientInServer (edict_t *ent)
memset (&ent->priv.sv->client->ps, 0, sizeof(client->ps));
// info_player_start
VectorScale(ent->progs.sv->origin, SV_COORD_FRAC, client->ps.pmove.origin);
VectorCopy(ent->progs.sv->origin, client->ps.origin);
client->ps.fov = 90;
client->ps.fov = bound(1, client->ps.fov, 160);
client->ps.gunindex = SV_ModelIndex(PRVM_GetString(ent->progs.sv->weaponmodel));
client->ps.vmodel.index = SV_ModelIndex(PRVM_GetString(ent->progs.sv->weaponmodel));
if(sv.loadgame)
{
@ -64,7 +69,7 @@ void SV_PutClientInServer (edict_t *ent)
// set the delta angle
for (i = 0; i < 3; i++)
{
client->ps.pmove.delta_angles[i] = ANGLE2SHORT(ent->progs.sv->angles[i]);
client->ps.delta_angles[i] = ANGLE2SHORT(ent->progs.sv->angles[i]);
}
if(sv.loadgame)
@ -77,7 +82,6 @@ void SV_PutClientInServer (edict_t *ent)
}
VectorCopy(ent->progs.sv->angles, client->ps.viewangles);
VectorCopy (client->ps.viewangles, client->v_angle);
SV_LinkEdict(ent);
}
@ -237,38 +241,38 @@ void SV_CalcGunOffset (edict_t *ent)
float delta;
// gun angles from bobbing
ent->priv.sv->client->ps.gunangles[ROLL] = xyspeed * bobfracsin * 0.005;
ent->priv.sv->client->ps.gunangles[YAW] = xyspeed * bobfracsin * 0.01;
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.gunangles[ROLL] = -ent->priv.sv->client->ps.gunangles[ROLL];
ent->priv.sv->client->ps.gunangles[YAW] = -ent->priv.sv->client->ps.gunangles[YAW];
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.gunangles[PITCH] = xyspeed * bobfracsin * 0.005;
ent->priv.sv->client->ps.viewoffset[2] = 22;
ent->priv.sv->client->ps.vmodel.angles[PITCH] = xyspeed * bobfracsin * 0.005;
ent->priv.sv->client->ps.viewoffset[2] = ent->priv.sv->client->ps.viewheight;
// gun angles from delta movement
for (i = 0; i < 3; i++)
{
delta = ent->priv.sv->client->oldviewangles[i] - ent->priv.sv->client->ps.viewangles[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.gunangles[ROLL] += 0.1*delta;
ent->priv.sv->client->ps.gunangles[i] += 0.2 * delta;
if (i == YAW) ent->priv.sv->client->ps.vmodel.angles[ROLL] += 0.1*delta;
ent->priv.sv->client->ps.vmodel.angles[i] += 0.2 * delta;
}
// gun height
VectorClear (ent->priv.sv->client->ps.gunoffset);
VectorClear (ent->priv.sv->client->ps.vmodel.offset);
// gun_x / gun_y / gun_z are development tools
for (i = 0; i < 3; i++)
{
ent->priv.sv->client->ps.gunoffset[i] += forward[i];
ent->priv.sv->client->ps.gunoffset[i] += right[i];
ent->priv.sv->client->ps.gunoffset[i] += up[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];
}
}
@ -293,12 +297,12 @@ void SV_CalcViewOffset (edict_t *ent)
// add angles based on bob
delta = bobfracsin * 0.002 * xyspeed;
if (ent->priv.sv->client->ps.pmove.pm_flags & PMF_DUCKED)
if (ent->priv.sv->client->ps.pm_flags & PMF_DUCKED)
delta *= 6; // crouching
angles[PITCH] += delta;
delta = bobfracsin * 0.002 * xyspeed;
if (ent->priv.sv->client->ps.pmove.pm_flags & PMF_DUCKED)
if (ent->priv.sv->client->ps.pm_flags & PMF_DUCKED)
delta *= 6; // crouching
if (bobcycle & 1) delta = -delta;
angles[ROLL] += delta;
@ -344,22 +348,22 @@ void ClientEndServerFrame (edict_t *ent)
// If it wasn't updated here, the view position would lag a frame
// behind the body position when pushed -- "sinking into plats"
//
VectorScale(ent->progs.sv->origin, SV_COORD_FRAC, current_client->ps.pmove.origin );
VectorScale(ent->progs.sv->velocity, SV_COORD_FRAC, current_client->ps.pmove.velocity );
AngleVectors (ent->priv.sv->client->v_angle, forward, right, up);
VectorCopy(ent->progs.sv->origin, current_client->ps.origin );
VectorCopy(ent->progs.sv->velocity, current_client->ps.velocity );
AngleVectors (ent->priv.sv->client->ps.viewangles, forward, right, up);
//
// set model angles from view angles so other things in
// the world can tell which direction you are looking
//
if (ent->priv.sv->client->v_angle[PITCH] > 180)
ent->progs.sv->angles[PITCH] = (-360 + ent->priv.sv->client->v_angle[PITCH])/3;
else ent->progs.sv->angles[PITCH] = ent->priv.sv->client->v_angle[PITCH]/3;
if (ent->priv.sv->client->ps.viewangles[PITCH] > 180)
ent->progs.sv->angles[PITCH] = (-360 + ent->priv.sv->client->ps.viewangles[PITCH])/3;
else ent->progs.sv->angles[PITCH] = ent->priv.sv->client->ps.viewangles[PITCH]/3;
ent->progs.sv->angles[YAW] = ent->priv.sv->client->v_angle[YAW];
ent->progs.sv->angles[YAW] = ent->priv.sv->client->ps.viewangles[YAW];
ent->progs.sv->angles[ROLL] = 0;
ent->progs.sv->angles[ROLL] = SV_CalcRoll (ent->progs.sv->angles, ent->progs.sv->velocity)*4;
ent->priv.sv->client->ps.pmove.pm_time = ent->progs.sv->teleport_time * 1000; //in msecs
ent->priv.sv->client->ps.pm_time = ent->progs.sv->teleport_time * 1000; //in msecs
//
// calculate speed and cycle to be used for
@ -370,7 +374,7 @@ void ClientEndServerFrame (edict_t *ent)
if (xyspeed < 5)
{
bobmove = 0;
current_client->bobtime = 0; // start at beginning of cycle again
current_client->ps.bobtime = 0; // start at beginning of cycle again
}
else if (ent->progs.sv->groundentity)
{
@ -380,9 +384,9 @@ void ClientEndServerFrame (edict_t *ent)
else bobmove = 0.0625;
}
bobtime = (current_client->bobtime += bobmove);
bobtime = (current_client->ps.bobtime += bobmove);
if (current_client->ps.pmove.pm_flags & PMF_DUCKED)
if (current_client->ps.pm_flags & PMF_DUCKED)
bobtime *= 4;
bobcycle = (int)bobtime;
@ -523,7 +527,7 @@ void SV_ClientBegin (edict_t *ent)
// state when the game is saved, so we need to compensate
// with deltaangles
for (i = 0; i < 3; i++)
ent->priv.sv->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(ent->priv.sv->client->ps.viewangles[i]);
ent->priv.sv->client->ps.delta_angles[i] = ANGLE2SHORT(ent->priv.sv->client->ps.viewangles[i]);
}
else
{
@ -565,7 +569,7 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
VectorCopy(ent->progs.sv->origin, oldorigin);
VectorCopy(ent->progs.sv->velocity, oldvelocity);
ent->priv.sv->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION;
ent->priv.sv->client->ps.pm_flags &= ~PMF_NO_PREDICTION;
VectorCopy(ent->progs.sv->origin, view);
@ -574,39 +578,34 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
// set up for pmove
memset (&pm, 0, sizeof(pm));
if (ent->progs.sv->movetype == MOVETYPE_NOCLIP) client->ps.pmove.pm_type = PM_SPECTATOR;
else client->ps.pmove.pm_type = PM_NORMAL;
client->ps.pmove.gravity = sv_gravity->value;
if (ent->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(ent->progs.sv->teleport_time) client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT;
else client->ps.pmove.pm_flags &= ~PMF_TIME_TELEPORT;
if(ent->progs.sv->teleport_time) client->ps.pm_flags |= PMF_TIME_TELEPORT;
else client->ps.pm_flags &= ~PMF_TIME_TELEPORT;
pm.s = client->ps.pmove;
pm.ps = client->ps;
VectorScale(ent->progs.sv->origin, SV_COORD_FRAC, pm.s.origin );
VectorScale(ent->progs.sv->velocity, SV_COORD_FRAC, pm.s.velocity );
if (memcmp(&client->old_pmove, &pm.s, sizeof(pm.s)))
pm.snapinitial = true;
VectorCopy(ent->progs.sv->origin, pm.ps.origin );
VectorCopy(ent->progs.sv->velocity, pm.ps.velocity );
pm.cmd = *ucmd;
pm.trace = PM_trace; // adds default parms
pm.pointcontents = SV_PointContents;
pm.pointcontents = PM_pointcontents;
// perform a pmove
Pmove (&pm);
// save results of pmove
client->ps.pmove = pm.s;
client->old_pmove = pm.s;
client->ps = pm.ps;
VectorScale(pm.s.origin, CL_COORD_FRAC, ent->progs.sv->origin);
VectorScale(pm.s.velocity, CL_COORD_FRAC, ent->progs.sv->velocity);
VectorCopy (pm.mins, ent->progs.sv->mins);
VectorCopy (pm.maxs, ent->progs.sv->maxs);
VectorCopy (pm.viewangles, client->v_angle);
VectorCopy (pm.viewangles, client->ps.viewangles);
VectorCopy(pm.ps.origin, ent->progs.sv->origin);
VectorCopy(pm.ps.velocity, ent->progs.sv->velocity);
VectorCopy(pm.mins, ent->progs.sv->mins);
VectorCopy(pm.maxs, ent->progs.sv->maxs);
VectorCopy(pm.ps.viewangles, client->ps.viewangles);
SV_LinkEdict(ent);

View File

@ -185,24 +185,21 @@ void SV_LinkEdict( edict_t *ent )
if (ent->progs.sv->solid == SOLID_BBOX && !((int)ent->progs.sv->flags & FL_DEADMONSTER))
{
// assume that x/y are equal and symetric
i = ent->progs.sv->maxs[0]/SV_COORD_FRAC;
if( i < 1 ) i = 1;
if( i > 31) i = 31;
i = ent->progs.sv->maxs[0];
i = bound( 1, i, 255 );
// z is not symetric
j = (-ent->progs.sv->mins[2])/SV_COORD_FRAC;
if( j < 1 ) j = 1;
if( j > 31) j = 31;
j = (-ent->progs.sv->mins[2]);
j = bound( 1, j, 255 );
// and z maxs can be negative...
k = (ent->progs.sv->maxs[2]+32)/SV_COORD_FRAC;
if( k < 1 ) k = 1;
if( k > 63) k = 63;
sv_ent->solid = (k<<10) | (j<<5) | i;
k = (ent->progs.sv->maxs[2] + 32);
k = bound( 1, k, 255 );
sv_ent->solid = (k<<16) | (j<<8) | i;
}
else if (ent->progs.sv->solid == SOLID_BSP)
{
sv_ent->solid = 31; // a solid_bbox will never create this value
sv_ent->solid = SOLID_BMODEL; // a solid_bbox will never create this value
}
else sv_ent->solid = 0;
@ -431,7 +428,6 @@ void SV_ClipMoveToEntities( moveclip_t *clip )
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 );
if( trace.allsolid )
@ -572,7 +568,7 @@ trace_t SV_ClipMoveToEntity(edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs
if( !touch->progs.sv->solid == SOLID_BSP ) angles = vec3_origin; // boxes don't rotate
trace = pe->TransformedBoxTrace( start, end, mins, maxs, cmodel, contentsmask, origin, angles );
if( trace.fraction < 1 ) trace.ent = touch;
if( trace.fraction < 1.0f ) trace.ent = touch;
return trace;
}

View File

@ -122,7 +122,7 @@ void BSP_CreateMeshBuffer( int modelnum )
// sky is noclip for all physobjects
if(flags & SURF_SKY) continue;
face = Mem_Alloc( cmappool, m_face->numedges * sizeof(vec3_t));
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] );
@ -133,7 +133,7 @@ void BSP_CreateMeshBuffer( int modelnum )
if( hull.numverts )
{
// grab vertices
loadmodel->physmesh[loadmodel->numbodies].verts = Mem_Alloc( cmappool, hull.numverts * sizeof(vec3_t));
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->numbodies++;
@ -145,9 +145,10 @@ void BSP_LoadModels( lump_t *l )
dmodel_t *in;
cmodel_t *out;
int i, j, count;
short *indexes;
in = (void *)(cm.mod_base + l->fileofs);
if (l->filelen % sizeof(*in)) Host_Error("CMod_LoadSubmodels: funny lump size\n");
if (l->filelen % sizeof(*in)) Host_Error("CMod_LoadModels: funny lump size\n");
count = l->filelen / sizeof(*in);
if(count < 1) Host_Error("Map %s without models\n", cm.name );
@ -167,6 +168,16 @@ void BSP_LoadModels( lump_t *l )
out->numfaces = LittleLong( in->numfaces );
out->firstbrush = LittleLong( in->firstbrush );
out->numbrushes = LittleLong( in->numbrushes );
com.strncpy( out->name, va("*%i", i ), sizeof(out->name));
out->mempool = Mem_AllocPool( out->name );
// make a "leaf" just to hold the model's brushes and surfaces
out->leaf.numleafbrushes = LittleLong( in->numbrushes );
indexes = Mem_Alloc( out->mempool, out->leaf.numleafbrushes * sizeof(short));
out->leaf.firstleafbrush = indexes - cm.leafbrushes;
for( j = 0; j < out->leaf.numleafbrushes; j++ )
indexes[j] = LittleLong( in->firstbrush ) + j;
BSP_CreateMeshBuffer( i ); // bsp physic
}
}
@ -863,7 +874,7 @@ CM_FreeModel
void CM_FreeModel( cmodel_t *mod )
{
Mem_FreePool( &mod->mempool );
memset(mod->physmesh, 0, MAXSTUDIOMODELS*sizeof(cmesh_t));
memset(mod->physmesh, 0, MAXSTUDIOMODELS * sizeof(cmesh_t));
memset(mod, 0, sizeof(*mod));
mod = NULL;
}
@ -880,14 +891,12 @@ void CM_EndRegistration( void )
if(mod->registration_sequence != registration_sequence)
CM_FreeModel( mod );
}
#if 0
for (i = 0, mod = &cm.bmodels[0]; i < cm.numbmodels; i++, mod++)
{
if(!mod->name[0]) continue;
if(mod->registration_sequence != registration_sequence)
CM_FreeModel( mod );
}
#endif
}
int CM_LeafContents( int leafnum )

View File

@ -6,8 +6,10 @@
#include "cm_local.h"
#include "cm_utils.h"
#define DIST_EPSILON (0.03125) // 1/32 epsilon to keep floating point happy
#define MAX_POSITION_LEAFS 1024
// 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 MAX_POSITION_LEAFS 1024
/*
===============================================================================
@ -176,7 +178,7 @@ void CM_TraceThroughBrush( tracework_t *tw, cbrush_t *brush )
if( d1 > 0 ) startout = true;
// if completely in front of face, no intersection with the entire brush
if(d1 > 0 && ( d2 >= CL_COORD_FRAC || d2 >= d1 ) )
if(d1 > 0 && ( d2 >= DIST_EPSILON || d2 >= d1 ) )
return;
// if it doesn't cross the plane, the plane isn't relevent
@ -186,7 +188,7 @@ void CM_TraceThroughBrush( tracework_t *tw, cbrush_t *brush )
if( d1 > d2 )
{
// enter
f = (d1-CL_COORD_FRAC) / (d1-d2);
f = (d1 - DIST_EPSILON) / (d1-d2);
if( f < 0 ) f = 0;
if( f > enterFrac )
{
@ -198,7 +200,7 @@ void CM_TraceThroughBrush( tracework_t *tw, cbrush_t *brush )
else
{
// leave
f = (d1+CL_COORD_FRAC) / (d1-d2);
f = (d1 + DIST_EPSILON) / (d1-d2);
if( f > 1 ) f = 1;
if( f < leaveFrac )
{
@ -230,6 +232,7 @@ void CM_TraceThroughBrush( tracework_t *tw, cbrush_t *brush )
tw->result.fraction = enterFrac;
tw->result.plane = *clipplane;
tw->result.flags = leadside->surface->flags;
tw->result.surface = leadside->surface;
tw->result.contents = brush->contents;
}
}
@ -367,20 +370,20 @@ void CM_TraceThroughTree( tracework_t *tw, int num, float p1f, float p2f, vec3_t
return;
}
// put the crosspoint CL_COORD_FRAC pixels on the near side
// put the crosspoint DIST_EPSILON pixels on the near side
if( t1 < t2 )
{
idist = 1.0/(t1-t2);
side = 1;
frac2 = (t1 + offset + CL_COORD_FRAC) * idist;
frac = (t1 - offset + CL_COORD_FRAC) * idist;
frac2 = (t1 + offset + DIST_EPSILON) * idist;
frac = (t1 - offset + DIST_EPSILON) * idist;
}
else if( t1 > t2 )
{
idist = 1.0/(t1-t2);
side = 0;
frac2 = (t1 - offset - CL_COORD_FRAC) * idist;
frac = (t1 + offset + CL_COORD_FRAC) * idist;
frac2 = (t1 - offset - DIST_EPSILON) * idist;
frac = (t1 + offset + DIST_EPSILON) * idist;
}
else
{
@ -428,6 +431,7 @@ void CM_Trace( trace_t *results, const vec3_t start, const vec3_t end, vec3_t mi
// fill in a default trace
memset( &tw, 0, sizeof(tw) );
tw.result.fraction = 1; // assume it goes the entire distance until shown otherwise
tw.result.surface = &(cm.nullsurface);
VectorCopy( origin, tw.origin );
if(!cm.numnodes)
@ -579,7 +583,6 @@ 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 )
{
trace_t trace;
vec3_t start_l, end_l;
vec3_t offset;
vec3_t symetricSize[2];
@ -625,22 +628,21 @@ trace_t CM_TransformedBoxTrace( const vec3_t start, const vec3_t end, vec3_t min
}
// sweep the box through the model
CM_Trace( &trace, start_l, end_l, symetricSize[0], symetricSize[1], model, origin, brushmask );
CM_Trace( &cm.trace, start_l, end_l, symetricSize[0], symetricSize[1], model, origin, brushmask );
// if the bmodel was rotated and there was a collision
if( rotated && trace.fraction != 1.0 )
if( rotated && cm.trace.fraction != 1.0 )
{
// rotation of bmodel collision plane
TransposeMatrix( matrix, transpose );
RotatePoint( trace.plane.normal, transpose );
RotatePoint( cm.trace.plane.normal, transpose );
}
// re-calculate the end position of the trace because the trace.endpos
// calculated by CM_Trace could be rotated and have an offset
trace.endpos[0] = start[0] + trace.fraction * (end[0] - start[0]);
trace.endpos[1] = start[1] + trace.fraction * (end[1] - start[1]);
trace.endpos[2] = start[2] + trace.fraction * (end[2] - start[2]);
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]);
Mem_Copy( &cm.trace, &trace, sizeof(trace_t));
return cm.trace;
}

View File

@ -17,8 +17,8 @@
#endif
// network precision coords factor
#define SV_COORD_FRAC (8.0f / 1.0f)
#define CL_COORD_FRAC (1.0f / 8.0f)
#define SV_COORD_FRAC (1.0f)
#define CL_COORD_FRAC (1.0f)
#define SV_ANGLE_FRAC (360.0f / 1.0f )
#define CL_ANGLE_FRAC (1.0f / 360.0f )
@ -218,9 +218,28 @@ _inline vec_t VectorNormalize (vec3_t v)
v[1] *= ilength;
v[2] *= ilength;
}
return length;
}
_inline vec_t VectorNormalize2( const vec3_t v, vec3_t out )
{
float length, ilength;
length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
length = sqrt( length );// FIXME
if (length)
{
ilength = 1/length;
out[0] *= ilength;
out[1] *= ilength;
out[2] *= ilength;
}
else
{
VectorClear( out );
}
return length;
}
_inline void VectorRotate (const vec3_t in1, vec3_t in2[3], vec3_t out)

View File

@ -228,11 +228,11 @@ void EmitWaterPolys (msurface_t *fa)
os = v[3];
ot = v[4];
s = os + r_turbsin[(int)((ot * CL_COORD_FRAC + rdt) * TURBSCALE) & 255];
s = os + r_turbsin[(int)((ot * 0.125f+ rdt) * TURBSCALE) & 255];
s += scroll;
s *= (1.0/64);
t = ot + r_turbsin[(int)((os * CL_COORD_FRAC + rdt) * TURBSCALE) & 255];
t = ot + r_turbsin[(int)((os * 0.125f + rdt) * TURBSCALE) & 255];
t *= (1.0/64);
qglTexCoord2f (s, t);