mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-29 07:02:12 +00:00
I'm tweeking pmove.c for the luls.
fixed 8859-1 for non-english hexen2 tweeking my deltaing. cl_demospeed bugs fixed. fixed things being seen through skys. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3990 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
61061c8e71
commit
ee72d0ca0d
29 changed files with 481 additions and 326 deletions
|
@ -502,11 +502,16 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t *
|
|||
Con_Printf("%3i: Update %4i 0x%x\n", msg_readcount, entnum, bits);
|
||||
|
||||
if (bits & UF_RESET)
|
||||
{
|
||||
// Con_Printf("%3i: Reset %i @ %i\n", msg_readcount, entnum, cls.netchan.incoming_sequence);
|
||||
*news = *baseline;
|
||||
}
|
||||
else if (!olds)
|
||||
{
|
||||
Con_DPrintf("New entity without reset\n");
|
||||
*news = *baseline;
|
||||
/*reset got lost, probably the data will be filled in later - FIXME: we should probably ignore this entity*/
|
||||
// Con_DPrintf("New entity without reset\n");
|
||||
memset(news, 0, sizeof(*news));
|
||||
// *news = *baseline;
|
||||
}
|
||||
else
|
||||
*news = *olds;
|
||||
|
@ -600,12 +605,15 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t *
|
|||
news->u.q1.msec = MSG_ReadByte();
|
||||
else
|
||||
news->u.q1.msec = 0;
|
||||
if (predbits & UFP_WEAPONFRAME)
|
||||
{
|
||||
news->u.q1.weaponframe = MSG_ReadByte();
|
||||
if (news->u.q1.weaponframe & 0x80)
|
||||
news->u.q1.weaponframe = (news->u.q1.weaponframe & 127) | (MSG_ReadByte()<<7);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
news->u.q1.pmovetype = 0;
|
||||
news->u.q1.msec = 0;
|
||||
}
|
||||
|
||||
if (bits & UF_MODEL)
|
||||
{
|
||||
|
@ -667,18 +675,12 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t *
|
|||
|
||||
if (bits & UF_FATNESS)
|
||||
news->fatness = MSG_ReadByte();
|
||||
|
||||
|
||||
|
||||
/*update the prediction info if needed*/
|
||||
if ((bits & UF_PREDINFO) && (news->number-1) < cl.allocated_client_slots)
|
||||
{
|
||||
frame_t *fram;
|
||||
fram = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
|
||||
CL_PlayerFrameUpdated(&fram->playerstate[news->number-1], news, cls.netchan.incoming_sequence);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Note: strictly speaking, you don't need multiple frames, just two and flip between them.
|
||||
FTE retains the full 64 frames because its interpolation will go multiple packets back in time to cover packet loss.
|
||||
*/
|
||||
void CLFTE_ParseEntities(void)
|
||||
{
|
||||
int oldpacket, newpacket;
|
||||
|
@ -686,6 +688,7 @@ void CLFTE_ParseEntities(void)
|
|||
unsigned short newnum, oldnum;
|
||||
int oldindex;
|
||||
qboolean isvalid = false;
|
||||
entity_state_t *e;
|
||||
|
||||
// int i;
|
||||
// for (i = cl.validsequence+1; i < cls.netchan.incoming_sequence; i++)
|
||||
|
@ -700,7 +703,7 @@ void CLFTE_ParseEntities(void)
|
|||
cl.frames[newpacket].invalid = true;
|
||||
|
||||
|
||||
if (cls.netchan.incoming_sequence >= cl.validsequence + UPDATE_BACKUP)
|
||||
if (!cl.validsequence || cls.netchan.incoming_sequence-cl.validsequence >= UPDATE_BACKUP-1)
|
||||
{
|
||||
oldp = &nullp;
|
||||
oldp->num_entities = 0;
|
||||
|
@ -738,6 +741,7 @@ void CLFTE_ParseEntities(void)
|
|||
}
|
||||
if (newnum == 0x8000)
|
||||
{
|
||||
/*removal of world - means forget all entities*/
|
||||
if (cl_shownet.ival >= 3)
|
||||
Con_Printf("%3i: Reset all\n", msg_readcount);
|
||||
newp->num_entities = 0;
|
||||
|
@ -763,7 +767,7 @@ void CLFTE_ParseEntities(void)
|
|||
if (newnum & 0x8000)
|
||||
{
|
||||
if (cl_shownet.ival >= 3)
|
||||
Con_Printf("%3i: Remove %i\n", msg_readcount, (newnum&32767));
|
||||
Con_Printf("%3i: Remove %i @ %i\n", msg_readcount, (newnum&32767), cls.netchan.incoming_sequence);
|
||||
if (oldnum == (newnum&0x7fff))
|
||||
oldindex++;
|
||||
continue;
|
||||
|
@ -786,6 +790,21 @@ void CLFTE_ParseEntities(void)
|
|||
}
|
||||
}
|
||||
|
||||
for (oldindex = 0; oldindex < newp->num_entities; oldindex++)
|
||||
{
|
||||
e = newp->entities + oldindex;
|
||||
if (e->number > cl.allocated_client_slots)
|
||||
break;
|
||||
|
||||
/*update the prediction info if needed*/
|
||||
if (e->u.q1.pmovetype)
|
||||
{
|
||||
frame_t *fram;
|
||||
fram = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
|
||||
CL_PlayerFrameUpdated(&fram->playerstate[e->number-1], e, cls.netchan.incoming_sequence);
|
||||
}
|
||||
}
|
||||
|
||||
if (isvalid)
|
||||
{
|
||||
cl.oldvalidsequence = cl.validsequence;
|
||||
|
@ -794,7 +813,10 @@ void CLFTE_ParseEntities(void)
|
|||
cl.frames[newpacket].invalid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
newp->num_entities = 0;
|
||||
cl.validsequence = 0;
|
||||
}
|
||||
|
||||
/*ackedinputsequence is updated when we have new player prediction info*/
|
||||
cl.ackedinputsequence = cls.netchan.incoming_sequence;
|
||||
|
@ -3170,6 +3192,17 @@ void CL_ParsePlayerinfo (void)
|
|||
|
||||
TP_ParsePlayerInfo(oldstate, state, info);
|
||||
|
||||
cl.players[num].stats[STAT_WEAPONFRAME] = state->weaponframe;
|
||||
cl.players[num].statsf[STAT_WEAPONFRAME] = state->weaponframe;
|
||||
for (i = 0; i < cl.splitclients; i++)
|
||||
{
|
||||
if (cl.playernum[i] == num)
|
||||
{
|
||||
cl.stats[i][STAT_WEAPONFRAME] = state->weaponframe;
|
||||
cl.statsf[i][STAT_WEAPONFRAME] = state->weaponframe;
|
||||
}
|
||||
}
|
||||
|
||||
if (cl.splitclients < MAX_SPLITS)
|
||||
{
|
||||
extern cvar_t cl_splitscreen;
|
||||
|
@ -3382,6 +3415,15 @@ guess_pm_type:
|
|||
|
||||
TP_ParsePlayerInfo(oldstate, state, info);
|
||||
|
||||
for (i = 0; i < cl.splitclients; i++)
|
||||
{
|
||||
if (cl.playernum[i] == num)
|
||||
{
|
||||
cl.stats[i][STAT_WEAPONFRAME] = state->weaponframe;
|
||||
cl.statsf[i][STAT_WEAPONFRAME] = state->weaponframe;
|
||||
}
|
||||
}
|
||||
|
||||
if (cl.worldmodel && cl_lerp_players.ival)
|
||||
{
|
||||
player_state_t exact;
|
||||
|
@ -3938,7 +3980,7 @@ void CL_SetSolidEntities (void)
|
|||
if (!state->solid && !state->skinnum)
|
||||
continue;
|
||||
|
||||
if (state->solid == 31)
|
||||
if (state->solid == ES_SOLID_BSP)
|
||||
{ /*bsp model size*/
|
||||
if (state->modelindex <= 0)
|
||||
continue;
|
||||
|
@ -4129,6 +4171,7 @@ void CL_SetSolidPlayers (void)
|
|||
|
||||
memset(pent, 0, sizeof(physent_t));
|
||||
VectorCopy(pplayer->origin, pent->origin);
|
||||
pent->info = j+1;
|
||||
VectorCopy(player_mins, pent->mins);
|
||||
VectorCopy(player_maxs, pent->maxs);
|
||||
if (++pmove.numphysent == MAX_PHYSENTS) //we just hit 88 miles per hour.
|
||||
|
|
|
@ -520,7 +520,7 @@ void CL_AdjustAngles (int pnum, double frametime)
|
|||
quant *= speed;
|
||||
in_rotate -= quant;
|
||||
if (ruleset_allow_frj.ival)
|
||||
cl.viewangles[pnum][YAW] += quant;
|
||||
cl.viewanglechange[pnum][YAW] += quant;
|
||||
}
|
||||
|
||||
if (!(in_strafe.state[pnum] & 1))
|
||||
|
@ -528,9 +528,8 @@ void CL_AdjustAngles (int pnum, double frametime)
|
|||
quant = cl_yawspeed.ival;
|
||||
if (cl.fpd & FPD_LIMIT_YAW || !ruleset_allow_frj.ival)
|
||||
quant = bound(-900, quant, 900);
|
||||
cl.viewangles[pnum][YAW] -= speed*quant * CL_KeyState (&in_right, pnum);
|
||||
cl.viewangles[pnum][YAW] += speed*quant * CL_KeyState (&in_left, pnum);
|
||||
cl.viewangles[pnum][YAW] = anglemod(cl.viewangles[pnum][YAW]);
|
||||
cl.viewanglechange[pnum][YAW] -= speed*quant * CL_KeyState (&in_right, pnum);
|
||||
cl.viewanglechange[pnum][YAW] += speed*quant * CL_KeyState (&in_left, pnum);
|
||||
}
|
||||
if (in_klook.state[pnum] & 1)
|
||||
{
|
||||
|
@ -538,8 +537,8 @@ void CL_AdjustAngles (int pnum, double frametime)
|
|||
quant = cl_pitchspeed.ival;
|
||||
if (cl.fpd & FPD_LIMIT_PITCH || !ruleset_allow_frj.ival)
|
||||
quant = bound(-700, quant, 700);
|
||||
cl.viewangles[pnum][PITCH] -= speed*quant * CL_KeyState (&in_forward, pnum);
|
||||
cl.viewangles[pnum][PITCH] += speed*quant * CL_KeyState (&in_back, pnum);
|
||||
cl.viewanglechange[pnum][PITCH] -= speed*quant * CL_KeyState (&in_forward, pnum);
|
||||
cl.viewanglechange[pnum][PITCH] += speed*quant * CL_KeyState (&in_back, pnum);
|
||||
}
|
||||
|
||||
up = CL_KeyState (&in_lookup, pnum);
|
||||
|
@ -548,19 +547,11 @@ void CL_AdjustAngles (int pnum, double frametime)
|
|||
quant = cl_pitchspeed.ival;
|
||||
if (!ruleset_allow_frj.ival)
|
||||
quant = bound(-700, quant, 700);
|
||||
cl.viewangles[pnum][PITCH] -= speed*cl_pitchspeed.ival * up;
|
||||
cl.viewangles[pnum][PITCH] += speed*cl_pitchspeed.ival * down;
|
||||
cl.viewanglechange[pnum][PITCH] -= speed*cl_pitchspeed.ival * up;
|
||||
cl.viewanglechange[pnum][PITCH] += speed*cl_pitchspeed.ival * down;
|
||||
|
||||
if (up || down)
|
||||
V_StopPitchDrift (pnum);
|
||||
|
||||
CL_ClampPitch(pnum);
|
||||
|
||||
if (cl.viewangles[pnum][ROLL] > 50)
|
||||
cl.viewangles[pnum][ROLL] = 50;
|
||||
if (cl.viewangles[pnum][ROLL] < -50)
|
||||
cl.viewangles[pnum][ROLL] = -50;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -612,10 +603,60 @@ int MakeChar (int i)
|
|||
|
||||
void CL_ClampPitch (int pnum)
|
||||
{
|
||||
vec3_t view[4];
|
||||
vec3_t impact, norm;
|
||||
float mat[16], mat2[16];
|
||||
static float oldtime;
|
||||
float timestep = realtime - oldtime;
|
||||
oldtime = realtime;
|
||||
|
||||
if (1)
|
||||
{
|
||||
AngleVectors(cl.viewangles[pnum], view[0], view[1], view[2]);
|
||||
Matrix4x4_RM_FromVectors(mat, view[0], view[1], view[2], vec3_origin);
|
||||
|
||||
Matrix4_Multiply(Matrix4x4_CM_NewRotation(-cl.viewanglechange[pnum][PITCH], 0, 1, 0), mat, mat2);
|
||||
Matrix4_Multiply(Matrix4x4_CM_NewRotation(cl.viewanglechange[pnum][YAW], 0, 0, 1), mat2, mat);
|
||||
|
||||
Matrix3x4_RM_ToVectors(mat, view[0], view[1], view[2], view[3]);
|
||||
|
||||
VectorMA(cl.simorg[pnum], -48, view[2], view[3]);
|
||||
if (!TraceLineN(cl.simorg[pnum], view[3], impact, norm))
|
||||
{
|
||||
norm[0] = 0;
|
||||
norm[1] = 0;
|
||||
norm[2] = 1;
|
||||
}
|
||||
|
||||
{
|
||||
vec3_t cross;
|
||||
float roll;
|
||||
float dot;
|
||||
/*keep the roll relative to the 'ground'*/
|
||||
CrossProduct(norm, view[2], cross);
|
||||
dot = DotProduct(view[0], cross);
|
||||
roll = timestep * 720/M_PI * -(dot);
|
||||
Con_Printf("%f %f\n", dot, roll);
|
||||
Matrix4_Multiply(Matrix4x4_CM_NewRotation(roll, 1, 0, 0), mat, mat2);
|
||||
Matrix3x4_RM_ToVectors(mat2, view[0], view[1], view[2], view[3]);
|
||||
}
|
||||
|
||||
VectorAngles(view[0], view[2], cl.viewangles[pnum]);
|
||||
cl.viewangles[pnum][PITCH]=360 - cl.viewangles[pnum][PITCH];
|
||||
VectorClear(cl.viewanglechange[pnum]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
cl.viewangles[pnum][PITCH] += cl.viewanglechange[pnum][PITCH];
|
||||
cl.viewangles[pnum][YAW] += cl.viewanglechange[pnum][YAW];
|
||||
cl.viewangles[pnum][ROLL] += cl.viewanglechange[pnum][ROLL];
|
||||
VectorClear(cl.viewanglechange[pnum]);
|
||||
|
||||
#ifdef Q2CLIENT
|
||||
float pitch;
|
||||
if (cls.protocol == CP_QUAKE2)
|
||||
{
|
||||
float pitch;
|
||||
pitch = SHORT2ANGLE(cl.q2frame.playerstate.pmove.delta_angles[PITCH]);
|
||||
if (pitch > 180)
|
||||
pitch -= 360;
|
||||
|
@ -647,6 +688,11 @@ void CL_ClampPitch (int pnum)
|
|||
if (cl.viewangles[pnum][PITCH] < cl.minpitch)
|
||||
cl.viewangles[pnum][PITCH] = cl.minpitch;
|
||||
}
|
||||
|
||||
if (cl.viewangles[pnum][ROLL] > 50)
|
||||
cl.viewangles[pnum][ROLL] = 50;
|
||||
if (cl.viewangles[pnum][ROLL] < -50)
|
||||
cl.viewangles[pnum][ROLL] = -50;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -659,6 +705,8 @@ void CL_FinishMove (usercmd_t *cmd, int msecs, int pnum)
|
|||
int i;
|
||||
int bits;
|
||||
|
||||
CL_ClampPitch(pnum);
|
||||
|
||||
//
|
||||
// always dump the first two message, because it may contain leftover inputs
|
||||
// from the last level
|
||||
|
@ -1375,6 +1423,7 @@ void CL_SendCmd (double frametime, qboolean mainloop)
|
|||
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
|
||||
{
|
||||
extern cvar_t cl_splitscreen;
|
||||
cl.ackedinputsequence = cls.netchan.outgoing_sequence;
|
||||
i = cls.netchan.outgoing_sequence & UPDATE_MASK;
|
||||
cl.frames[i].senttime = realtime; // we haven't gotten a reply yet
|
||||
// cl.frames[i].receivedtime = -1; // we haven't gotten a reply yet
|
||||
|
|
|
@ -2781,7 +2781,7 @@ void CL_ReadPackets (void)
|
|||
// check timeout
|
||||
//
|
||||
if (cls.state >= ca_connected
|
||||
&& realtime - cls.netchan.last_received > cl_timeout.value)
|
||||
&& realtime - cls.netchan.last_received > cl_timeout.value && !cls.demoplayback)
|
||||
{
|
||||
#ifndef CLIENTONLY
|
||||
/*don't timeout when we're the actual server*/
|
||||
|
|
|
@ -24,8 +24,6 @@ cvar_t cl_nopred = SCVAR("cl_nopred","0");
|
|||
extern cvar_t cl_lerp_players;
|
||||
cvar_t cl_pushlatency = SCVAR("pushlatency","-999");
|
||||
|
||||
extern frame_t *view_frame;
|
||||
|
||||
extern float pm_airaccelerate;
|
||||
|
||||
extern usercmd_t independantphysics[MAX_SPLITS];
|
||||
|
@ -768,7 +766,7 @@ static void CL_DecodeStateSize(unsigned short solid, int modelindex, vec3_t mins
|
|||
void CL_PlayerFrameUpdated(player_state_t *plstate, entity_state_t *state, int sequence)
|
||||
{
|
||||
/*update the prediction info*/
|
||||
int pmtype;
|
||||
int pmtype, i;
|
||||
if (state->u.q1.pmovetype == MOVETYPE_NOCLIP)
|
||||
{
|
||||
if (cls.z_ext & Z_EXT_PM_TYPE_NEW)
|
||||
|
@ -790,6 +788,17 @@ void CL_PlayerFrameUpdated(player_state_t *plstate, entity_state_t *state, int s
|
|||
VectorScale(state->u.q1.velocity, 1/8.0, plstate->velocity);
|
||||
plstate->messagenum = sequence;
|
||||
|
||||
cl.players[state->number-1].stats[STAT_WEAPONFRAME] = state->u.q1.weaponframe;
|
||||
cl.players[state->number-1].statsf[STAT_WEAPONFRAME] = state->u.q1.weaponframe;
|
||||
for (i = 0; i < cl.splitclients; i++)
|
||||
{
|
||||
if (cl.playernum[i] == state->number-1)
|
||||
{
|
||||
cl.stats[i][STAT_WEAPONFRAME] = state->u.q1.weaponframe;
|
||||
cl.statsf[i][STAT_WEAPONFRAME] = state->u.q1.weaponframe;
|
||||
}
|
||||
}
|
||||
|
||||
CL_DecodeStateSize(state->solid, state->modelindex, plstate->szmins, plstate->szmaxs);
|
||||
}
|
||||
|
||||
|
@ -891,7 +900,6 @@ void CL_PredictMovePNum (int pnum)
|
|||
{
|
||||
return;
|
||||
}
|
||||
CL_ClampPitch(pnum);
|
||||
if (cls.netchan.outgoing_sequence - cl.ackedinputsequence >= UPDATE_BACKUP-1)
|
||||
{ //lagging like poo.
|
||||
if (!cl.intermission) //keep the angles working though.
|
||||
|
@ -977,7 +985,7 @@ fixedorg:
|
|||
goto fixedorg;
|
||||
}
|
||||
|
||||
to = &cl.frames[cl.ackedinputsequence & UPDATE_MASK];
|
||||
to = &cl.frames[cl.validsequence & UPDATE_MASK];
|
||||
from = &cl.frames[cl.oldvalidsequence & UPDATE_MASK];
|
||||
|
||||
//figure out the lerp factor
|
||||
|
@ -1030,8 +1038,6 @@ fixedorg:
|
|||
CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]]
|
||||
, &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]);
|
||||
|
||||
cl.onground[pnum] = pmove.onground;
|
||||
|
||||
if (to->senttime >= realtime)
|
||||
break;
|
||||
from = to;
|
||||
|
@ -1046,9 +1052,8 @@ fixedorg:
|
|||
to->senttime = realtime;
|
||||
CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]]
|
||||
, &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]);
|
||||
|
||||
cl.onground[pnum] = pmove.onground;
|
||||
}
|
||||
cl.onground[pnum] = pmove.onground;
|
||||
stepheight = to->playerstate[cl.playernum[pnum]].origin[2] - from->playerstate[cl.playernum[pnum]].origin[2];
|
||||
|
||||
if (cl.nolocalplayer[pnum])
|
||||
|
|
|
@ -538,6 +538,7 @@ typedef struct
|
|||
// sent to the server each frame. And only reset at level change
|
||||
// and teleport times
|
||||
vec3_t viewangles[MAX_SPLITS];
|
||||
vec3_t viewanglechange[MAX_SPLITS];
|
||||
|
||||
// the client simulates or interpolates movement to get these values
|
||||
double time; // this is the time value that the client
|
||||
|
|
|
@ -901,10 +901,10 @@ void Con_DrawInput (int left, int right, int y)
|
|||
rhs = x + left;
|
||||
if (cursorframe)
|
||||
{
|
||||
extern cvar_t com_parseutf8;
|
||||
if (com_parseutf8.ival)
|
||||
Font_DrawChar(rhs, y, (*cursor&~(CON_BGMASK|CON_FGMASK)) | (COLOR_BLUE<<CON_BGSHIFT) | CON_NONCLEARBG | CON_WHITEMASK);
|
||||
else
|
||||
// extern cvar_t com_parseutf8;
|
||||
// if (com_parseutf8.ival)
|
||||
// Font_DrawChar(rhs, y, (*cursor&~(CON_BGMASK|CON_FGMASK)) | (COLOR_BLUE<<CON_BGSHIFT) | CON_NONCLEARBG | CON_WHITEMASK);
|
||||
// else
|
||||
Font_DrawChar(rhs, y, 0xe000|11|CON_WHITEMASK);
|
||||
}
|
||||
else if (*cursor)
|
||||
|
|
|
@ -83,7 +83,7 @@ void IN_Move (float *movements, int pnum)
|
|||
}
|
||||
else
|
||||
{
|
||||
cl.viewangles[pnum][YAW] -= m_yaw.value * mouse_x;
|
||||
cl.viewanglechange[pnum][YAW] -= m_yaw.value * mouse_x;
|
||||
}
|
||||
|
||||
if (in_mlook.state[pnum])
|
||||
|
@ -91,8 +91,7 @@ void IN_Move (float *movements, int pnum)
|
|||
|
||||
if (in_mlook.state[pnum] && !(in_strafe.state[pnum] & 1))
|
||||
{
|
||||
cl.viewangles[pnum][PITCH] += m_pitch.value * mouse_y;
|
||||
cl.viewangles[pnum][PITCH] = bound(-70, cl.viewangles[pnum][PITCH], 80);
|
||||
cl.viewanglechange[pnum][PITCH] += m_pitch.value * mouse_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -281,14 +281,13 @@ void IN_Move (float *movements, int pnum)
|
|||
}
|
||||
else
|
||||
{
|
||||
cl.viewangles[pnum][YAW] -= m_yaw.value * mouse_x;
|
||||
cl.viewanglechange[pnum][YAW] -= m_yaw.value * mouse_x;
|
||||
}
|
||||
if (in_mlook.state[pnum] & 1)
|
||||
V_StopPitchDrift (pnum);
|
||||
|
||||
if ( (in_mlook.state[pnum] & 1) && !(in_strafe.state[pnum] & 1)) {
|
||||
cl.viewangles[pnum][PITCH] += m_pitch.value * mouse_y;
|
||||
CL_ClampPitch(pnum);
|
||||
cl.viewanglechange[pnum][PITCH] += m_pitch.value * mouse_y;
|
||||
} else {
|
||||
if (movements)
|
||||
{
|
||||
|
|
|
@ -315,16 +315,14 @@ void IN_Move (float *movements, int pnum) //add mouse movement to cmd
|
|||
if ( (in_strafe.state[pnum] & 1) || (lookstrafe.value && (in_mlook.state[pnum] & 1) ))
|
||||
movements[1] += m_side.value * mouse_x;
|
||||
else
|
||||
cl.viewangles[pnum][YAW] -= m_yaw.value * mouse_x;
|
||||
cl.viewanglechange[pnum][YAW] -= m_yaw.value * mouse_x;
|
||||
|
||||
if (in_mlook.state[pnum] & 1)
|
||||
V_StopPitchDrift (pnum);
|
||||
|
||||
if ( (in_mlook.state[pnum] & 1) && !(in_strafe.state[pnum] & 1))
|
||||
{
|
||||
cl.viewangles[pnum][PITCH] += m_pitch.value * mouse_y;
|
||||
|
||||
CL_ClampPitch(pnum);
|
||||
cl.viewanglechange[pnum][PITCH] += m_pitch.value * mouse_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1389,7 +1389,7 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum)
|
|||
{
|
||||
// if ((int)((cl.viewangles[pnum][PITCH]+89.99)/180) & 1)
|
||||
// mouse_x *= -1;
|
||||
cl.viewangles[pnum][YAW] -= m_yaw.value * mouse_x;
|
||||
cl.viewanglechange[pnum][YAW] -= m_yaw.value * mouse_x;
|
||||
}
|
||||
|
||||
if (in_mlook.state[pnum] & 1)
|
||||
|
@ -1397,9 +1397,7 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum)
|
|||
|
||||
if ( (in_mlook.state[pnum] & 1) && !(in_strafe.state[pnum] & 1))
|
||||
{
|
||||
cl.viewangles[pnum][PITCH] += m_pitch.value * mouse_y;
|
||||
|
||||
CL_ClampPitch(pnum);
|
||||
cl.viewanglechange[pnum][PITCH] += m_pitch.value * mouse_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2152,11 +2150,11 @@ void IN_JoyMove (float *movements, int pnum)
|
|||
// only absolute control support here (joy_advanced is false)
|
||||
if (m_pitch.value < 0.0)
|
||||
{
|
||||
cl.viewangles[pnum][PITCH] -= (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
|
||||
cl.viewanglechange[pnum][PITCH] -= (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
cl.viewangles[pnum][PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
|
||||
cl.viewanglechange[pnum][PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
|
||||
}
|
||||
V_StopPitchDrift(pnum);
|
||||
}
|
||||
|
@ -2203,11 +2201,11 @@ void IN_JoyMove (float *movements, int pnum)
|
|||
{
|
||||
if(dwControlMap[i] == JOY_ABSOLUTE_AXIS)
|
||||
{
|
||||
cl.viewangles[pnum][YAW] += (fAxisValue * joy_yawsensitivity.value) * aspeed * cl_yawspeed.value;
|
||||
cl.viewanglechange[pnum][YAW] += (fAxisValue * joy_yawsensitivity.value) * aspeed * cl_yawspeed.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
cl.viewangles[pnum][YAW] += (fAxisValue * joy_yawsensitivity.value) * speed * 180.0;
|
||||
cl.viewanglechange[pnum][YAW] += (fAxisValue * joy_yawsensitivity.value) * speed * 180.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2222,11 +2220,11 @@ void IN_JoyMove (float *movements, int pnum)
|
|||
// pitch movement detected and pitch movement desired by user
|
||||
if(dwControlMap[i] == JOY_ABSOLUTE_AXIS)
|
||||
{
|
||||
cl.viewangles[pnum][PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
|
||||
cl.viewanglechange[pnum][PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
cl.viewangles[pnum][PITCH] += (fAxisValue * joy_pitchsensitivity.value) * speed * 180.0;
|
||||
cl.viewanglechange[pnum][PITCH] += (fAxisValue * joy_pitchsensitivity.value) * speed * 180.0;
|
||||
}
|
||||
V_StopPitchDrift(pnum);
|
||||
}
|
||||
|
|
|
@ -558,7 +558,7 @@ void Key_Console (unsigned int unicode, int key)
|
|||
if (key_lines[edit_line][key_linepos])
|
||||
{
|
||||
int charlen = 1;
|
||||
if (com_parseutf8.ival &&
|
||||
if (com_parseutf8.ival>0 &&
|
||||
(key_lines[edit_line][key_linepos] & 0xc0) != 0x80)
|
||||
{
|
||||
while((key_lines[edit_line][key_linepos+charlen] & 0xc0) == 0x80)
|
||||
|
@ -577,7 +577,7 @@ void Key_Console (unsigned int unicode, int key)
|
|||
if (key_linepos > 1)
|
||||
{
|
||||
int charlen = 1;
|
||||
if (com_parseutf8.ival)
|
||||
if (com_parseutf8.ival>0)
|
||||
{
|
||||
while (key_linepos > charlen && (key_lines[edit_line][key_linepos-charlen] & 0xc0) == 0x80)
|
||||
charlen++;
|
||||
|
@ -730,10 +730,10 @@ void Key_Console (unsigned int unicode, int key)
|
|||
unsigned char c2;
|
||||
unsigned char c3;
|
||||
|
||||
if (unicode > 127)
|
||||
if (unicode > ((com_parseutf8.ival<0)?255:127))
|
||||
{
|
||||
extern cvar_t com_parseutf8;
|
||||
if (com_parseutf8.ival)
|
||||
if (com_parseutf8.ival>0)
|
||||
{
|
||||
if (unicode > 0xffff)
|
||||
{
|
||||
|
|
|
@ -1113,9 +1113,6 @@ static void QCBUILTIN PF_cs_unproject (progfuncs_t *prinst, struct globalvars_s
|
|||
//clear scene, and set up the default stuff.
|
||||
static void QCBUILTIN PF_R_ClearScene (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
extern frame_t *view_frame;
|
||||
extern player_state_t *view_message;
|
||||
|
||||
if (*prinst->callargc > 0)
|
||||
CSQC_ChangeLocalPlayer(G_FLOAT(OFS_PARM0));
|
||||
|
||||
|
@ -1133,12 +1130,6 @@ static void QCBUILTIN PF_R_ClearScene (progfuncs_t *prinst, struct globalvars_s
|
|||
skel_dodelete(csqcprogs);
|
||||
CL_SwapEntityLists();
|
||||
|
||||
view_frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
|
||||
view_message = &view_frame->playerstate[cl.playernum[csqc_lplayernum]];
|
||||
#ifdef NQPROT
|
||||
if (cls.protocol == CP_NETQUAKE || !view_message->messagenum)
|
||||
view_message->weaponframe = cl.stats[csqc_lplayernum][STAT_WEAPONFRAME];
|
||||
#endif
|
||||
V_CalcRefdef(csqc_lplayernum); //set up the defaults (for player 0)
|
||||
|
||||
csqc_addcrosshair = false;
|
||||
|
@ -4682,9 +4673,11 @@ void CSQC_World_GetFrameState(world_t *w, wedict_t *win, framestate_t *out)
|
|||
|
||||
void CSQC_Shutdown(void)
|
||||
{
|
||||
search_close_progs(csqcprogs, false);
|
||||
if (csqcprogs)
|
||||
{
|
||||
search_close_progs(csqcprogs, false);
|
||||
PR_fclose_progs(csqcprogs);
|
||||
|
||||
CSQC_ForgetThreads();
|
||||
CloseProgs(csqcprogs);
|
||||
}
|
||||
|
|
|
@ -101,7 +101,6 @@ extern cvar_t cl_chasecam;
|
|||
|
||||
float v_dmg_time[MAX_SPLITS], v_dmg_roll[MAX_SPLITS], v_dmg_pitch[MAX_SPLITS];
|
||||
|
||||
frame_t *view_frame;
|
||||
player_state_t *view_message;
|
||||
|
||||
/*
|
||||
|
@ -1111,14 +1110,14 @@ void V_CalcRefdef (int pnum)
|
|||
else if (scr_viewsize.value == 80)
|
||||
view->origin[2] += 0.5;
|
||||
|
||||
if (!view_message || view_message->flags & (PF_GIB|PF_DEAD) || (unsigned int)cl.stats[pnum][STAT_WEAPON] >= MAX_MODELS)
|
||||
if (cl.stats[pnum][STAT_HEALTH] > 0 && (unsigned int)cl.stats[pnum][STAT_WEAPON] >= MAX_MODELS)
|
||||
view->model = NULL;
|
||||
else
|
||||
view->model = cl.model_precache[cl.stats[pnum][STAT_WEAPON]];
|
||||
#ifdef HLCLIENT
|
||||
if (!CLHL_AnimateViewEntity(view))
|
||||
#endif
|
||||
view->framestate.g[FS_REG].frame[0] = view_message?view_message->weaponframe:0;
|
||||
view->framestate.g[FS_REG].frame[0] = cl.stats[pnum][STAT_WEAPONFRAME];
|
||||
|
||||
// set up the refresh position
|
||||
if (v_gunkick.value)
|
||||
|
@ -1309,12 +1308,7 @@ void V_RenderPlayerViews(int plnum)
|
|||
int viewnum;
|
||||
#endif
|
||||
SCR_VRectForPlayer(&r_refdef.vrect, plnum);
|
||||
view_message = &view_frame->playerstate[cl.playernum[plnum]];
|
||||
#ifdef NQPROT
|
||||
if (cls.protocol == CP_NETQUAKE)
|
||||
view_message->weaponframe = cl.stats[0][STAT_WEAPONFRAME];
|
||||
#endif
|
||||
cl.simangles[plnum][ROLL] = 0; // FIXME @@@
|
||||
// cl.simangles[plnum][ROLL] = 0; // FIXME @@@
|
||||
|
||||
|
||||
DropPunchAngle (plnum);
|
||||
|
@ -1485,8 +1479,6 @@ void V_RenderView (void)
|
|||
RSpeedEnd(RSPEED_LINKENTITIES);
|
||||
}
|
||||
|
||||
view_frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
|
||||
|
||||
R_PushDlights ();
|
||||
|
||||
r_secondaryview = 0;
|
||||
|
|
|
@ -95,7 +95,8 @@ cvar_t gameversion_max = CVARD("gameversion_max","", "gamecode version for serve
|
|||
cvar_t fs_gamename = CVARFD("fs_gamename", "", CVAR_NOSET, "The filesystem is trying to run this game");
|
||||
cvar_t com_protocolname = CVARD("com_gamename", "", "The game name used for dpmaster queries");
|
||||
cvar_t com_modname = CVARD("com_modname", "", "dpmaster information");
|
||||
cvar_t com_parseutf8 = CVARD("com_parseutf8", "0", "Interpret console messages/playernames/etc as UTF-8. Requires special fonts."); //1 parse. 2 parse, but stop parsing that string if a char was malformed.
|
||||
cvar_t com_parseutf8 = CVARD("com_parseutf8", "0", "Interpret console messages/playernames/etc as UTF-8. Requires special fonts. -1=iso 8859-1. 0=quakeascii(chat uses high chars). 1=utf8, revert to ascii on decode errors. 2=utf8 ignoring errors"); //1 parse. 2 parse, but stop parsing that string if a char was malformed.
|
||||
cvar_t com_highlightcolor = CVARD("com_highlightcolor", STRINGIFY(COLOR_RED), "ANSI colour to be used for highlighted text, used when com_parseutf8 is active.");
|
||||
|
||||
qboolean com_modified; // set true if using non-id files
|
||||
|
||||
|
@ -1973,7 +1974,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
|
|||
if (*str == 1 || *str == 2)
|
||||
{
|
||||
if (com_parseutf8.ival)
|
||||
defaultflags = (defaultflags&~CON_FGMASK) | (COLOR_MAGENTA<<CON_FGSHIFT);
|
||||
defaultflags = (defaultflags&~CON_FGMASK) | ((com_highlightcolor.ival&15)<<CON_FGSHIFT);
|
||||
else
|
||||
defaultflags |= CON_HIGHCHARSMASK;
|
||||
str++;
|
||||
|
@ -1983,7 +1984,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
|
|||
|
||||
while(*str)
|
||||
{
|
||||
if (*str & 0x80 && utf8)
|
||||
if (*str & 0x80 && utf8 > 0)
|
||||
{ //check for utf-8
|
||||
|
||||
//uc is the output unicode char
|
||||
|
@ -3363,6 +3364,7 @@ void COM_Init (void)
|
|||
Cvar_Register (&gameversion_min, "Gamecode");
|
||||
Cvar_Register (&gameversion_max, "Gamecode");
|
||||
Cvar_Register (&com_parseutf8, "Internationalisation");
|
||||
Cvar_Register (&com_highlightcolor, "Internationalisation");
|
||||
com_parseutf8.ival = 1;
|
||||
|
||||
|
||||
|
|
|
@ -1740,7 +1740,7 @@ void COM_Gamedir (const char *dir)
|
|||
/*some modern non-compat settings*/
|
||||
#define DMFCFG "set com_parseutf8 1\npm_airstep 1\nsv_demoExtensions 1\n"
|
||||
/*set some stuff so our regular qw client appears more like hexen2*/
|
||||
#define HEX2CFG "set_calc cl_playerclass int (random * 5) + 1\nset r_particlesdesc \"spikeset tsshaft h2part\"\nset sv_maxspeed 640\nset watervis 1\nset r_wateralpha 0.5\nset sv_pupglow 1\nset cl_model_bobbing 1\nsv_sound_land \"fx/thngland.wav\"\n"
|
||||
#define HEX2CFG "set com_parseutf8 -1\nset gl_font gfx/hexen2\nset in_builtinkeymap 0\nset_calc cl_playerclass int (random * 5) + 1\nset r_particlesdesc \"spikeset tsshaft h2part\"\nset sv_maxspeed 640\nset watervis 1\nset r_wateralpha 0.5\nset sv_pupglow 1\nset cl_model_bobbing 1\nsv_sound_land \"fx/thngland.wav\"\n"
|
||||
/*Q3's ui doesn't like empty model/headmodel/handicap cvars, even if the gamecode copes*/
|
||||
#define Q3CFG "gl_overbright 2\nseta model sarge\nseta headmodel sarge\nseta handicap 100\n"
|
||||
|
||||
|
|
|
@ -270,11 +270,10 @@ int PM_StepSlideMove (qboolean in_air)
|
|||
if (!(blocked & BLOCKED_STEP))
|
||||
return blocked;
|
||||
|
||||
org = (originalvel[2] < 0) ? pmove.origin : original;
|
||||
VectorCopy (org, dest);
|
||||
dest[2] -= movevars.stepheight;
|
||||
org = (-DotProduct(pmove.gravitydir, originalvel) < 0) ? pmove.origin : original;
|
||||
VectorMA (org, movevars.stepheight, pmove.gravitydir, dest);
|
||||
trace = PM_PlayerTrace (org, dest);
|
||||
if (trace.fraction == 1 || trace.plane.normal[2] < MIN_STEP_NORMAL)
|
||||
if (trace.fraction == 1 || -DotProduct(pmove.gravitydir, trace.plane.normal) < MIN_STEP_NORMAL)
|
||||
return blocked;
|
||||
|
||||
// adjust stepsize, otherwise it would be possible to walk up a
|
||||
|
@ -291,8 +290,7 @@ int PM_StepSlideMove (qboolean in_air)
|
|||
VectorCopy (originalvel, pmove.velocity);
|
||||
|
||||
// move up a stair height
|
||||
VectorCopy (pmove.origin, dest);
|
||||
dest[2] += stepsize;
|
||||
VectorMA (pmove.origin, -stepsize, pmove.gravitydir, dest);
|
||||
trace = PM_PlayerTrace (pmove.origin, dest);
|
||||
if (!trace.startsolid && !trace.allsolid)
|
||||
{
|
||||
|
@ -300,31 +298,32 @@ int PM_StepSlideMove (qboolean in_air)
|
|||
}
|
||||
|
||||
if (in_air && originalvel[2] < 0)
|
||||
pmove.velocity[2] = 0;
|
||||
VectorMA(pmove.velocity, -DotProduct(pmove.velocity, pmove.gravitydir), pmove.gravitydir, pmove.velocity); //z=0
|
||||
|
||||
PM_SlideMove ();
|
||||
|
||||
// press down the stepheight
|
||||
VectorCopy (pmove.origin, dest);
|
||||
dest[2] -= stepsize;
|
||||
VectorMA (pmove.origin, stepsize, pmove.gravitydir, dest);
|
||||
trace = PM_PlayerTrace (pmove.origin, dest);
|
||||
if (trace.fraction != 1 && trace.plane.normal[2] < MIN_STEP_NORMAL)
|
||||
if (trace.fraction != 1 && -DotProduct(pmove.gravitydir, trace.plane.normal) < MIN_STEP_NORMAL)
|
||||
goto usedown;
|
||||
if (!trace.startsolid && !trace.allsolid)
|
||||
{
|
||||
VectorCopy (trace.endpos, pmove.origin);
|
||||
}
|
||||
|
||||
if (pmove.origin[2] < original[2])
|
||||
if (-DotProduct(pmove.gravitydir, pmove.origin) < -DotProduct(pmove.gravitydir, original))
|
||||
goto usedown;
|
||||
|
||||
VectorCopy (pmove.origin, up);
|
||||
|
||||
// decide which one went farther
|
||||
downdist = (down[0] - original[0])*(down[0] - original[0])
|
||||
+ (down[1] - original[1])*(down[1] - original[1]);
|
||||
updist = (up[0] - original[0])*(up[0] - original[0])
|
||||
+ (up[1] - original[1])*(up[1] - original[1]);
|
||||
// decide which one went farther (in the forwards direction regardless of step values)
|
||||
VectorSubtract(down, original, dest);
|
||||
VectorMA(dest, -DotProduct(dest, pmove.gravitydir), pmove.gravitydir, dest); //z=0
|
||||
downdist = DotProduct(dest, dest);
|
||||
VectorSubtract(up, original, dest);
|
||||
VectorMA(dest, -DotProduct(dest, pmove.gravitydir), pmove.gravitydir, dest); //z=0
|
||||
updist = DotProduct(dest, dest);
|
||||
|
||||
if (downdist >= updist)
|
||||
{
|
||||
|
@ -335,13 +334,14 @@ usedown:
|
|||
}
|
||||
|
||||
// copy z value from slide move
|
||||
pmove.velocity[2] = downvel[2];
|
||||
VectorMA(pmove.velocity, DotProduct(downvel, pmove.gravitydir)-DotProduct(pmove.velocity, pmove.gravitydir), pmove.gravitydir, pmove.velocity); //z=downvel
|
||||
|
||||
if (!pmove.onground && pmove.waterlevel < 2 && (blocked & BLOCKED_STEP)) {
|
||||
float scale;
|
||||
// in pm_airstep mode, walking up a 16 unit high step
|
||||
// will kill 16% of horizontal velocity
|
||||
scale = 1 - 0.01*(pmove.origin[2] - original[2]);
|
||||
//FIXME gravitydir
|
||||
pmove.velocity[0] *= scale;
|
||||
pmove.velocity[1] *= scale;
|
||||
}
|
||||
|
@ -517,9 +517,13 @@ void PM_WaterMove (void)
|
|||
wishvel[i] = forward[i]*pmove.cmd.forwardmove + right[i]*pmove.cmd.sidemove;
|
||||
|
||||
if (pmove.pm_type != PM_FLY && !pmove.cmd.forwardmove && !pmove.cmd.sidemove && !pmove.cmd.upmove && !pmove.onladder)
|
||||
wishvel[2] -= 60; // drift towards bottom
|
||||
{
|
||||
VectorMA(wishvel, 60, pmove.gravitydir, wishvel);
|
||||
}
|
||||
else
|
||||
wishvel[2] += pmove.cmd.upmove;
|
||||
{
|
||||
VectorMA(wishvel, -pmove.cmd.upmove, pmove.gravitydir, wishvel);
|
||||
}
|
||||
|
||||
VectorCopy (wishvel, wishdir);
|
||||
wishspeed = VectorNormalize(wishdir);
|
||||
|
@ -551,7 +555,7 @@ void PM_FlyMove (void)
|
|||
for (i=0 ; i<3 ; i++)
|
||||
wishvel[i] = forward[i]*pmove.cmd.forwardmove + right[i]*pmove.cmd.sidemove;
|
||||
|
||||
wishvel[2] += pmove.cmd.upmove;
|
||||
VectorMA(wishvel, -pmove.cmd.upmove, pmove.gravitydir, wishvel);
|
||||
|
||||
VectorCopy (wishvel, wishdir);
|
||||
wishspeed = VectorNormalize(wishdir);
|
||||
|
@ -585,7 +589,9 @@ void PM_LadderMove (void)
|
|||
wishvel[2]*=10;
|
||||
|
||||
if (pmove.cmd.buttons & 2)
|
||||
wishvel[2]+=movevars.maxspeed;
|
||||
{
|
||||
VectorMA(wishvel, -movevars.maxspeed, pmove.gravitydir, wishvel);
|
||||
}
|
||||
|
||||
VectorCopy (wishvel, wishdir);
|
||||
wishspeed = VectorNormalize(wishdir);
|
||||
|
@ -600,8 +606,7 @@ void PM_LadderMove (void)
|
|||
|
||||
// assume it is a stair or a slope, so press down from stepheight above
|
||||
VectorMA (pmove.origin, frametime, pmove.velocity, dest);
|
||||
VectorCopy (dest, start);
|
||||
start[2] += movevars.stepheight + 1;
|
||||
VectorMA(dest, -(movevars.stepheight + 1), pmove.gravitydir, start);
|
||||
trace = PM_PlayerTrace (start, dest);
|
||||
if (!trace.startsolid && !trace.allsolid) // FIXME: check steep slope?
|
||||
{ // walked up the step
|
||||
|
@ -628,15 +633,14 @@ void PM_AirMove (void)
|
|||
|
||||
fmove = pmove.cmd.forwardmove;
|
||||
smove = pmove.cmd.sidemove;
|
||||
|
||||
forward[2] = 0;
|
||||
right[2] = 0;
|
||||
VectorMA(forward, -DotProduct(forward, pmove.gravitydir), pmove.gravitydir, forward); //z=0
|
||||
VectorMA(right, -DotProduct(right, pmove.gravitydir), pmove.gravitydir, right); //z=0
|
||||
VectorNormalize (forward);
|
||||
VectorNormalize (right);
|
||||
|
||||
for (i=0 ; i<2 ; i++)
|
||||
for (i=0 ; i<3 ; i++)
|
||||
wishdir[i] = forward[i]*fmove + right[i]*smove;
|
||||
wishdir[2] = 0;
|
||||
VectorMA(wishdir, -DotProduct(wishdir, pmove.gravitydir), pmove.gravitydir, wishdir); //z=0
|
||||
|
||||
wishspeed = VectorNormalize(wishdir);
|
||||
|
||||
|
@ -655,21 +659,24 @@ void PM_AirMove (void)
|
|||
pmove.velocity[2] = min(pmove.velocity[2], 0); // bound above by 0
|
||||
PM_Accelerate (wishdir, wishspeed, movevars.accelerate);
|
||||
// add gravity
|
||||
pmove.velocity[2] -= movevars.entgravity * movevars.gravity * frametime;
|
||||
VectorMA(pmove.velocity, movevars.entgravity * movevars.gravity * frametime, pmove.gravitydir, pmove.velocity);
|
||||
}
|
||||
else
|
||||
{
|
||||
pmove.velocity[2] = 0;
|
||||
VectorMA(pmove.velocity, -DotProduct(pmove.velocity, pmove.gravitydir), pmove.gravitydir, pmove.velocity); //z=0
|
||||
PM_Accelerate (wishdir, wishspeed, movevars.accelerate);
|
||||
}
|
||||
|
||||
if (!pmove.velocity[0] && !pmove.velocity[1] && !movevars.slidyslopes)
|
||||
//clear the z out, so we can test if we're moving horizontally relative to gravity
|
||||
VectorMA(pmove.velocity, -DotProduct(pmove.velocity, pmove.gravitydir), pmove.gravitydir, wishdir);
|
||||
if (!DotProduct(wishdir, wishdir) && !movevars.slidyslopes)
|
||||
{
|
||||
pmove.velocity[2] = 0;
|
||||
//clear z if we're not moving
|
||||
VectorClear(pmove.velocity);
|
||||
return;
|
||||
}
|
||||
else if (!movevars.slidefix && !movevars.slidyslopes)
|
||||
pmove.velocity[2] = 0;
|
||||
VectorMA(pmove.velocity, -DotProduct(pmove.velocity, pmove.gravitydir), pmove.gravitydir, pmove.velocity); //z=0
|
||||
|
||||
PM_StepSlideMove(false);
|
||||
}
|
||||
|
@ -681,7 +688,7 @@ void PM_AirMove (void)
|
|||
PM_AirAccelerate (wishdir, wishspeed, movevars.accelerate);
|
||||
|
||||
// add gravity
|
||||
pmove.velocity[2] -= movevars.entgravity * movevars.gravity * frametime;
|
||||
VectorMA(pmove.velocity, movevars.entgravity * movevars.gravity * frametime, pmove.gravitydir, pmove.velocity);
|
||||
|
||||
if (movevars.airstep)
|
||||
blocked = PM_StepSlideMove (true);
|
||||
|
@ -698,29 +705,45 @@ cplane_t groundplane;
|
|||
PM_CategorizePosition
|
||||
=============
|
||||
*/
|
||||
trace_t PM_TraceLine (vec3_t start, vec3_t end);
|
||||
void PM_CategorizePosition (void)
|
||||
{
|
||||
vec3_t point;
|
||||
int cont;
|
||||
trace_t trace;
|
||||
|
||||
pmove.gravitydir[0] = 0;
|
||||
pmove.gravitydir[1] = 0;
|
||||
pmove.gravitydir[2] = -1;
|
||||
if (pmove.pm_type == PM_WALLWALK)
|
||||
{
|
||||
vec3_t tmin,tmax;
|
||||
VectorCopy(player_mins, tmin);
|
||||
VectorCopy(player_maxs, tmax);
|
||||
VectorMA(pmove.origin, -48, up, point);
|
||||
trace = PM_TraceLine(pmove.origin, point);
|
||||
VectorCopy(tmin, player_mins);
|
||||
VectorCopy(tmax, player_maxs);
|
||||
|
||||
if (trace.fraction < 1)
|
||||
VectorNegate(trace.plane.normal, pmove.gravitydir);
|
||||
}
|
||||
|
||||
// if the player hull point one unit down is solid, the player
|
||||
// is on ground
|
||||
|
||||
// see if standing on something solid
|
||||
point[0] = pmove.origin[0];
|
||||
point[1] = pmove.origin[1];
|
||||
point[2] = pmove.origin[2] - 1;
|
||||
VectorAdd(pmove.origin, pmove.gravitydir, point);
|
||||
trace.startsolid = trace.allsolid = true;
|
||||
VectorClear(trace.endpos);
|
||||
if (pmove.velocity[2] > 180)
|
||||
if (DotProduct(pmove.gravitydir, pmove.velocity) > 180)
|
||||
{
|
||||
pmove.onground = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
trace = PM_PlayerTrace (pmove.origin, point);
|
||||
if (trace.fraction == 1 || trace.plane.normal[2] < MIN_STEP_NORMAL)
|
||||
if (trace.fraction == 1 || -DotProduct(pmove.gravitydir, trace.plane.normal) < MIN_STEP_NORMAL)
|
||||
pmove.onground = false;
|
||||
else
|
||||
{
|
||||
|
@ -843,14 +866,17 @@ void PM_CheckJump (void)
|
|||
|
||||
if (pmove.waterlevel >= 2)
|
||||
{ // swimming, not jumping
|
||||
float speed;
|
||||
pmove.onground = false;
|
||||
|
||||
if (pmove.watertype == FTECONTENTS_WATER)
|
||||
pmove.velocity[2] = 100;
|
||||
speed = 100;
|
||||
else if (pmove.watertype == FTECONTENTS_SLIME)
|
||||
pmove.velocity[2] = 80;
|
||||
speed = 80;
|
||||
else
|
||||
pmove.velocity[2] = 50;
|
||||
speed = 50;
|
||||
|
||||
VectorMA(pmove.velocity, -speed-DotProduct(pmove.velocity, pmove.gravitydir), pmove.gravitydir, pmove.velocity);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -862,16 +888,16 @@ void PM_CheckJump (void)
|
|||
|
||||
// check for jump bug
|
||||
// groundplane normal was set in the call to PM_CategorizePosition
|
||||
if (pmove.velocity[2] < 0 && DotProduct(pmove.velocity, groundplane.normal) < -0.1)
|
||||
if (-DotProduct(pmove.gravitydir, pmove.velocity) < 0 && DotProduct(pmove.velocity, groundplane.normal) < -0.1)
|
||||
{
|
||||
// pmove.velocity is pointing into the ground, clip it
|
||||
PM_ClipVelocity (pmove.velocity, groundplane.normal, pmove.velocity, 1);
|
||||
}
|
||||
|
||||
pmove.onground = false;
|
||||
pmove.velocity[2] += 270;
|
||||
VectorMA(pmove.velocity, -270, pmove.gravitydir, pmove.velocity);
|
||||
|
||||
if (movevars.ktjump > 0)
|
||||
if (movevars.ktjump > 0 && pmove.pm_type != PM_WALLWALK)
|
||||
{
|
||||
if (movevars.ktjump > 1)
|
||||
movevars.ktjump = 1;
|
||||
|
@ -1064,6 +1090,9 @@ void PM_PlayerMove (float gamespeed)
|
|||
frametime = pmove.cmd.msec * 0.001*gamespeed;
|
||||
pmove.numtouch = 0;
|
||||
|
||||
//TEMP
|
||||
pmove.pm_type = PM_WALLWALK;
|
||||
|
||||
if (pmove.pm_type == PM_NONE || pmove.pm_type == PM_FREEZE) {
|
||||
PM_CategorizePosition ();
|
||||
return;
|
||||
|
|
|
@ -28,7 +28,8 @@ typedef enum {
|
|||
PM_DEAD, // no acceleration
|
||||
PM_FLY, // fly, bump into walls
|
||||
PM_NONE, // can't move
|
||||
PM_FREEZE // can't move or look around (TODO)
|
||||
PM_FREEZE, // can't move or look around (TODO)
|
||||
PM_WALLWALK // sticks to walls. on ground while near one
|
||||
} pmtype_t;
|
||||
|
||||
#define PMF_JUMP_HELD 1
|
||||
|
@ -56,6 +57,7 @@ typedef struct
|
|||
vec3_t angles;
|
||||
vec3_t velocity;
|
||||
vec3_t basevelocity;
|
||||
vec3_t gravitydir;
|
||||
qboolean jump_held;
|
||||
int jump_msec; // msec since last jump
|
||||
float waterjumptime;
|
||||
|
|
|
@ -563,6 +563,7 @@ enum clcq2_ops_e
|
|||
#define UFP_VELOCITYXY (1u<<4)
|
||||
#define UFP_VELOCITYZ (1u<<5)
|
||||
#define UFP_MSEC (1u<<6)
|
||||
#define UFP_WEAPONFRAME (1u<<7)
|
||||
|
||||
#define UF_REMOVE UF_16BIT /*special flag, slightly more compact (we can reuse the 16bit flag as its not important)*/
|
||||
|
||||
|
@ -818,6 +819,7 @@ typedef struct entity_state_s
|
|||
/*info to predict other players, so I don't get yelled at if fte were to stop supporting it*/
|
||||
qbyte pmovetype;
|
||||
qbyte msec;
|
||||
unsigned short weaponframe;
|
||||
short movement[3];
|
||||
short velocity[3]; // 1/8th
|
||||
} q1;
|
||||
|
|
|
@ -751,7 +751,7 @@ static texid_t Font_LoadQuakeConchars(void)
|
|||
return r_nulltex;
|
||||
}
|
||||
|
||||
static texid_t Font_LoadHexen2Conchars(void)
|
||||
static texid_t Font_LoadHexen2Conchars(qboolean iso88591)
|
||||
{
|
||||
//gulp... so it's come to this has it? rework the hexen2 conchars into the q1 system.
|
||||
texid_t tex;
|
||||
|
@ -759,51 +759,52 @@ static texid_t Font_LoadHexen2Conchars(void)
|
|||
unsigned char *tempchars;
|
||||
unsigned char *in, *out, *outbuf;
|
||||
FS_LoadFile("gfx/menu/conchars.lmp", (void**)&tempchars);
|
||||
|
||||
/*hexen2's conchars are arranged 32-wide, 16 high.
|
||||
the upper 8 rows are 256 8859-1 chars
|
||||
the lower 8 rows are a separate set of recoloured 8859-1 chars.
|
||||
|
||||
if we're loading for the fallback then we're loading this data for quake compatibility,
|
||||
so we grab only the first 4 rows of each set of chars (128 low chars, 128 high chars).
|
||||
|
||||
if we're loading a proper charset, then we load only the first set of chars, we can recolour the rest anyway (com_parseutf8 will do so anyway).
|
||||
as a final note, parsing iso8859-1 french/german/etc as utf8 will generally result in decoding errors which can gracefully revert to 8859-1 safely. If this premise fails too much, we can always change the parser for different charsets - the engine always uses unicode and thus 8859-1 internally.
|
||||
*/
|
||||
if (tempchars)
|
||||
{
|
||||
outbuf = BZ_Malloc(8*8*256*8);
|
||||
|
||||
out = outbuf;
|
||||
for (i = 0; i < 8*8; i+=1)
|
||||
/*read the low chars*/
|
||||
for (i = 0; i < 8*8*(iso88591?2:1); i+=1)
|
||||
{
|
||||
if ((i/8)&1)
|
||||
{
|
||||
in = tempchars + ((i)/8)*16*8*8+(i&7)*32*8 - 256*4+128;
|
||||
for (x = 0; x < 16*8; x++)
|
||||
*out++ = *in++;
|
||||
}
|
||||
if (i&(1<<3))
|
||||
in = tempchars + (i>>3)*16*8*8+(i&7)*32*8 - 256*4+128;
|
||||
else
|
||||
{
|
||||
in = tempchars + (i/8)*16*8*8+(i&7)*32*8;
|
||||
for (x = 0; x < 16*8; x++)
|
||||
*out++ = *in++;
|
||||
}
|
||||
in = tempchars + (i>>3)*16*8*8+(i&7)*32*8;
|
||||
for (x = 0; x < 16*8; x++)
|
||||
*out++ = *in++;
|
||||
}
|
||||
for (i = 0; i < 8*8; i+=1)
|
||||
/*read the high chars*/
|
||||
for (; i < 8*8*2; i+=1)
|
||||
{
|
||||
if ((i/8)&1)
|
||||
{
|
||||
in = tempchars+128*128 + ((i)/8)*16*8*8+(i&7)*32*8 - 256*4+128;
|
||||
for (x = 0; x < 16*8; x++)
|
||||
*out++ = *in++;
|
||||
}
|
||||
if (i&(1<<3))
|
||||
in = tempchars+128*128 + ((i>>3)&15)*16*8*8+(i&7)*32*8 - 256*4+128;
|
||||
else
|
||||
{
|
||||
in = tempchars+128*128 + (i/8)*16*8*8+(i&7)*32*8;
|
||||
for (x = 0; x < 16*8; x++)
|
||||
*out++ = *in++;
|
||||
}
|
||||
in = tempchars+128*128 + ((i>>3)&15)*16*8*8+(i&7)*32*8;
|
||||
for (x = 0; x < 16*8; x++)
|
||||
*out++ = *in++;
|
||||
}
|
||||
FS_FreeFile(tempchars);
|
||||
|
||||
// add ocrana leds
|
||||
if (con_ocranaleds.value && con_ocranaleds.value != 2)
|
||||
if (!iso88591 && con_ocranaleds.value && con_ocranaleds.value != 2)
|
||||
AddOcranaLEDsIndexed (outbuf, 128, 128);
|
||||
|
||||
for (i=0 ; i<128*128 ; i++)
|
||||
if (outbuf[i] == 0)
|
||||
outbuf[i] = 255; // proper transparent color
|
||||
tex = R_LoadTexture8 ("charset", 128, 128, outbuf, IF_NOMIPMAP|IF_NOGAMMA, 1);
|
||||
tex = R_LoadTexture8 (iso88591?"gfx/menu/8859-1.lmp":"charset", 128, 128, outbuf, IF_NOMIPMAP|IF_NOGAMMA, 1);
|
||||
Z_Free(outbuf);
|
||||
return tex;
|
||||
}
|
||||
|
@ -844,7 +845,7 @@ static texid_t Font_LoadDefaultConchars(void)
|
|||
tex = Font_LoadQuakeConchars();
|
||||
if (TEXVALID(tex))
|
||||
return tex;
|
||||
tex = Font_LoadHexen2Conchars();
|
||||
tex = Font_LoadHexen2Conchars(false);
|
||||
if (TEXVALID(tex))
|
||||
return tex;
|
||||
tex = Font_LoadFallbackConchars();
|
||||
|
@ -899,6 +900,7 @@ struct font_s *Font_LoadFont(int height, char *fontfilename)
|
|||
{
|
||||
struct font_s *f;
|
||||
int i = 0;
|
||||
int defaultplane;
|
||||
|
||||
f = Z_Malloc(sizeof(*f));
|
||||
f->charheight = height;
|
||||
|
@ -1045,12 +1047,19 @@ struct font_s *Font_LoadFont(int height, char *fontfilename)
|
|||
}
|
||||
}
|
||||
|
||||
defaultplane = BITMAPPLANE;/*assume the bitmap plane - don't use the fallback as people don't think to use com_parseutf8*/
|
||||
if (!TEXVALID(f->singletexture))
|
||||
{
|
||||
if (!TEXVALID(f->singletexture) && !TEXVALID(fontplanes.defaultfont))
|
||||
fontplanes.defaultfont = Font_LoadDefaultConchars();
|
||||
|
||||
f->singletexture = fontplanes.defaultfont;
|
||||
if (!strcmp(fontfilename, "gfx/hexen2"))
|
||||
{
|
||||
f->singletexture = Font_LoadHexen2Conchars(true);
|
||||
defaultplane = DEFAULTPLANE;
|
||||
}
|
||||
if (!TEXVALID(f->singletexture))
|
||||
f->singletexture = fontplanes.defaultfont;
|
||||
}
|
||||
|
||||
for (; i < FONTCHARS; i++)
|
||||
|
@ -1070,7 +1079,7 @@ struct font_s *Font_LoadFont(int height, char *fontfilename)
|
|||
f->chars[i].top = 0;
|
||||
f->chars[i].nextchar = 0; //these chars are not linked in
|
||||
f->chars[i].pad = 0;
|
||||
f->chars[i].texplane = BITMAPPLANE; /*if its a 'raster' font, don't use the default chars, always use the raster images*/
|
||||
f->chars[i].texplane = defaultplane;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
|
|
@ -4155,13 +4155,14 @@ void Shader_Readpass (shader_t *shader, char **ptr)
|
|||
break;
|
||||
}
|
||||
|
||||
if ((shader->flags & SHADER_SKY) && (shader->flags & SHADER_DEPTHWRITE))
|
||||
/*if ((shader->flags & SHADER_SKY) && (shader->flags & SHADER_DEPTHWRITE))
|
||||
{
|
||||
#ifdef warningmsg
|
||||
#pragma warningmsg("is this valid?")
|
||||
#endif
|
||||
pass->shaderbits &= ~SBITS_MISC_DEPTHWRITE;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
static qboolean Shader_Parsetok (shader_t *shader, shaderpass_t *pass, shaderkey_t *keys, char *token, char **ptr)
|
||||
|
@ -5118,6 +5119,7 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args)
|
|||
"map $diffuse\n"
|
||||
"tcmod scale 10 10\n"
|
||||
"tcmod scroll 0.04 0.04\n"
|
||||
"depthwrite\n"
|
||||
"}\n"
|
||||
"{\n"
|
||||
"map $fullbright\n"
|
||||
|
|
|
@ -307,14 +307,14 @@ void IN_Move (float *movements, int pnum)
|
|||
}
|
||||
else
|
||||
{
|
||||
cl.viewangles[pnum][YAW] -= m_yaw.value * mouse_x;
|
||||
cl.viewanglechange[pnum][YAW] -= m_yaw.value * mouse_x;
|
||||
}
|
||||
if (in_mlook.state[pnum] & 1)
|
||||
V_StopPitchDrift (pnum);
|
||||
|
||||
if ( (in_mlook.state[pnum] & 1) && !(in_strafe.state[pnum] & 1)) {
|
||||
cl.viewangles[pnum][PITCH] += m_pitch.value * mouse_y;
|
||||
CL_ClampPitch(pnum);
|
||||
if ( (in_mlook.state[pnum] & 1) && !(in_strafe.state[pnum] & 1))
|
||||
{
|
||||
cl.viewanglechange[pnum][PITCH] += m_pitch.value * mouse_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1149,14 +1149,14 @@ void IN_MouseMove (float *movements, int pnum)
|
|||
if ( (in_strafe.state[pnum] & 1) || (lookstrafe.value && (in_mlook.state[pnum] & 1) ))
|
||||
movements[1] += m_side.value * mouse_x;
|
||||
else
|
||||
cl.viewangles[pnum][YAW] -= m_yaw.value * mouse_x;
|
||||
cl.viewanglechange[pnum][YAW] -= m_yaw.value * mouse_x;
|
||||
|
||||
if (in_mlook.state[pnum] & 1)
|
||||
V_StopPitchDrift (pnum);
|
||||
|
||||
if ( (in_mlook.state[pnum] & 1) && !(in_strafe.state[pnum] & 1))
|
||||
{
|
||||
cl.viewangles[pnum][PITCH] += m_pitch.value * mouse_y;
|
||||
cl.viewanglechange[pnum][PITCH] += m_pitch.value * mouse_y;
|
||||
CL_ClampPitch(pnum);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -247,6 +247,7 @@ and the extension fields are added on the end and can have extra vm-specific stu
|
|||
comfieldfloat(SendFlags)/*EXT_CSQC_1 (one of the DP guys came up with it)*/\
|
||||
comfieldfloat(Version)/*EXT_CSQC (obsolete)*/\
|
||||
comfieldfloat(pvsflags)/*EXT_CSQC_1*/\
|
||||
comfieldfloat(modelflags)\
|
||||
comfieldfloat(uniquespawnid)/*FTE_ENT_UNIQUESPAWNID*/\
|
||||
comfieldfunction(customizeentityforclient, ".float()")
|
||||
|
||||
|
|
|
@ -293,6 +293,7 @@ typedef struct
|
|||
vec3_t playerpositions[MAX_CLIENTS]; //where each player was in this frame, for antilag
|
||||
qboolean playerpresent[MAX_CLIENTS]; //whether the player was actually present
|
||||
packet_entities_t entities; //package containing entity states that were sent in this frame, for deltaing
|
||||
unsigned short *resendentnum; //the number of each entity that was sent in this frame
|
||||
unsigned int *resendentbits; //the bits of each entity that were sent in this frame
|
||||
} client_frame_t;
|
||||
|
||||
|
|
|
@ -399,26 +399,27 @@ void SV_CSQC_DroppedPacket(client_t *client, int sequence)
|
|||
//skip it if we never generated that frame, to avoid pulling in stale data
|
||||
if (client->frameunion.frames[sequence & UPDATE_MASK].sequence != sequence)
|
||||
{
|
||||
Con_Printf("SV: Stale %i\n", sequence);
|
||||
// Con_Printf("SV: Stale %i\n", sequence);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
|
||||
{
|
||||
unsigned int *f = client->frameunion.frames[sequence & UPDATE_MASK].resendentbits;
|
||||
Con_Printf("SV: Resend %i\n", sequence);
|
||||
i = client->max_net_ents;
|
||||
if (i > sv.world.num_edicts)
|
||||
i = sv.world.num_edicts;
|
||||
unsigned short *n = client->frameunion.frames[sequence & UPDATE_MASK].resendentnum;
|
||||
// Con_Printf("SV: Resend %i\n", sequence);
|
||||
i = client->frameunion.frames[sequence & UPDATE_MASK].entities.num_entities;
|
||||
while (i > 0)
|
||||
{
|
||||
if (f[i])
|
||||
{
|
||||
client->pendingentbits[i] |= f[i];
|
||||
f[i] = 0;
|
||||
}
|
||||
i--;
|
||||
|
||||
// if (f[i] & UF_RESET)
|
||||
// Con_Printf("Resend %i @ %i\n", i, sequence);
|
||||
// if (f[i] & UF_REMOVE)
|
||||
// Con_Printf("Remove %i @ %i\n", i, sequence);
|
||||
client->pendingentbits[n[i]] |= f[i];
|
||||
}
|
||||
client->frameunion.frames[sequence & UPDATE_MASK].entities.num_entities = 0;
|
||||
}
|
||||
|
||||
if (!(client->csqcactive)) //we don't need this, but it might be a little faster.
|
||||
|
@ -714,23 +715,58 @@ void SVQW_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg,
|
|||
}
|
||||
|
||||
/*special flags which are slightly more compact. these are 'wasted' as part of the delta itself*/
|
||||
#define UF_REMOVE UF_16BIT /*special flag, slightly more compact (we can reuse the 16bit flag as its not important)*/
|
||||
#define UF_MOVETYPE UF_EFFECTS2
|
||||
//#define UF_WASTED3 UF_EXTEND1
|
||||
//#define UF_WASTED2 UF_EXTEND2
|
||||
//#define UF_WASTED1 UF_EXTEND3
|
||||
#define UF_REMOVE UF_16BIT /*says we removed the entity in this frame*/
|
||||
#define UF_MOVETYPE UF_EFFECTS2 /*this flag isn't present in the header itself*/
|
||||
#define UF_RESET2 UF_EXTEND1 /*so new ents are reset 3 times to avoid weird baselines*/
|
||||
#define UF_UNUSED UF_EXTEND2 /**/
|
||||
#define UF_WEAPONFRAME UF_EXTEND3
|
||||
|
||||
static unsigned int SVFTE_DeltaPredCalcBits(entity_state_t *from, entity_state_t *to)
|
||||
{
|
||||
unsigned int bits = 0;
|
||||
if (from && from->u.q1.pmovetype != to->u.q1.pmovetype)
|
||||
bits |= UFP_MOVETYPE;
|
||||
|
||||
if (to->u.q1.movement[0])
|
||||
bits |= UFP_FORWARD;
|
||||
if (to->u.q1.movement[1])
|
||||
bits |= UFP_SIDE;
|
||||
if (to->u.q1.movement[2])
|
||||
bits |= UFP_UP;
|
||||
if (to->u.q1.velocity[0])
|
||||
bits |= UFP_VELOCITYXY;
|
||||
if (to->u.q1.velocity[1])
|
||||
bits |= UFP_VELOCITYXY;
|
||||
if (to->u.q1.velocity[2])
|
||||
bits |= UFP_VELOCITYZ;
|
||||
if (to->u.q1.msec)
|
||||
bits |= UFP_MSEC;
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
static unsigned int SVFTE_DeltaCalcBits(entity_state_t *from, entity_state_t *to)
|
||||
{
|
||||
unsigned int bits = 0;
|
||||
|
||||
if (from->u.q1.pmovetype != to->u.q1.pmovetype)
|
||||
bits |= UF_PREDINFO|UF_MOVETYPE;
|
||||
if (from->u.q1.weaponframe != to->u.q1.weaponframe)
|
||||
bits |= UF_PREDINFO|UF_WEAPONFRAME;
|
||||
if (to->u.q1.pmovetype)
|
||||
{
|
||||
bits |= UF_PREDINFO;
|
||||
/*if we've got player movement then always resend this extra stuff to avoid any weird loss*/
|
||||
bits |= UF_ORIGINXY | UF_ORIGINZ | UF_ANGLESXZ | UF_ANGLESY;
|
||||
if (from->u.q1.pmovetype != to->u.q1.pmovetype)
|
||||
bits |= UF_MOVETYPE;
|
||||
if (SVFTE_DeltaPredCalcBits(from, to))
|
||||
bits |= UF_PREDINFO;
|
||||
|
||||
/*moving players get extra data forced upon them which is not deltatracked*/
|
||||
if ((bits & UF_PREDINFO) && (from->u.q1.velocity[0] || from->u.q1.velocity[1] || from->u.q1.velocity[2]))
|
||||
{
|
||||
/*if we've got player movement then write the origin anyway*/
|
||||
bits |= UF_ORIGINXY | UF_ORIGINZ;
|
||||
/*and force angles too, if its not us*/
|
||||
if (host_client != svs.clients + to->number-1)
|
||||
bits |= UF_ANGLESXZ | UF_ANGLESY;
|
||||
}
|
||||
}
|
||||
|
||||
if (to->origin[0] != from->origin[0])
|
||||
|
@ -798,6 +834,11 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_
|
|||
bits &= ~UF_MOVETYPE;
|
||||
predbits |= UFP_MOVETYPE;
|
||||
}
|
||||
if (bits & UF_WEAPONFRAME)
|
||||
{
|
||||
bits &= ~UF_WEAPONFRAME;
|
||||
predbits |= UFP_WEAPONFRAME;
|
||||
}
|
||||
|
||||
/*check if we need more precision*/
|
||||
if ((bits & UF_MODEL) && state->modelindex > 255)
|
||||
|
@ -876,20 +917,7 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_
|
|||
if (bits & UF_PREDINFO)
|
||||
{
|
||||
/*movetype is set above somewhere*/
|
||||
if (state->u.q1.movement[0])
|
||||
predbits |= UFP_FORWARD;
|
||||
if (state->u.q1.movement[1])
|
||||
predbits |= UFP_SIDE;
|
||||
if (state->u.q1.movement[2])
|
||||
predbits |= UFP_UP;
|
||||
if (state->u.q1.velocity[0])
|
||||
predbits |= UFP_VELOCITYXY;
|
||||
if (state->u.q1.velocity[1])
|
||||
predbits |= UFP_VELOCITYXY;
|
||||
if (state->u.q1.velocity[2])
|
||||
predbits |= UFP_VELOCITYZ;
|
||||
if (state->u.q1.msec)
|
||||
predbits |= UFP_MSEC;
|
||||
predbits |= SVFTE_DeltaPredCalcBits(NULL, state);
|
||||
|
||||
MSG_WriteByte(msg, predbits);
|
||||
if (predbits & UFP_FORWARD)
|
||||
|
@ -909,6 +937,16 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_
|
|||
MSG_WriteShort(msg, state->u.q1.velocity[2]);
|
||||
if (predbits & UFP_MSEC)
|
||||
MSG_WriteByte(msg, state->u.q1.msec);
|
||||
if (predbits & UFP_WEAPONFRAME)
|
||||
{
|
||||
if (state->u.q1.weaponframe > 127)
|
||||
{
|
||||
MSG_WriteByte(msg, 128 | (state->u.q1.weaponframe & 127));
|
||||
MSG_WriteByte(msg, state->u.q1.weaponframe>>7);
|
||||
}
|
||||
else
|
||||
MSG_WriteByte(msg, state->u.q1.weaponframe);
|
||||
}
|
||||
}
|
||||
|
||||
if (bits & UF_MODEL)
|
||||
|
@ -980,12 +1018,17 @@ Only what changed is tracked, via bitmask, its previous value is never tracked.
|
|||
*/
|
||||
void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t *msg)
|
||||
{
|
||||
edict_t *e;
|
||||
entity_state_t *o, *n;
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
unsigned int *resend;
|
||||
unsigned int bits;
|
||||
unsigned int *resendbits;
|
||||
unsigned short *resendnum;
|
||||
unsigned int outno, outmax;
|
||||
qboolean reset = (client->delta_sequence == -1) || (client->pendingentbits[0] & UF_REMOVE);
|
||||
|
||||
//if we're clearing the list and starting from scratch, just wipe all lingering state
|
||||
if (reset)
|
||||
{
|
||||
for (j = 0; j < client->sentents.max_entities; j++)
|
||||
|
@ -995,7 +1038,7 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t
|
|||
}
|
||||
}
|
||||
|
||||
j = 0;
|
||||
//expand client's entstate list
|
||||
if (to->num_entities)
|
||||
{
|
||||
j = to->entities[to->num_entities-1].number+1;
|
||||
|
@ -1007,7 +1050,7 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t
|
|||
}
|
||||
}
|
||||
|
||||
/*figure out the bits that changed*/
|
||||
/*figure out the entitys+bits that changed (removed and active)*/
|
||||
for (i = 0, j = 0; i < to->num_entities; i++)
|
||||
{
|
||||
n = &to->entities[i];
|
||||
|
@ -1017,20 +1060,24 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t
|
|||
o = &client->sentents.entities[j];
|
||||
if (o->number)
|
||||
{
|
||||
client->pendingentbits[j] = UF_REMOVE;
|
||||
o->number = 0; /*dead*/
|
||||
e = EDICT_NUM(svprogfuncs, o->number);
|
||||
if (!((int)e->xv->pvsflags & PVSF_NOREMOVE))
|
||||
{
|
||||
client->pendingentbits[j] = UF_REMOVE;
|
||||
o->number = 0; /*dead*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
o = &client->sentents.entities[j];
|
||||
if (!o->number)
|
||||
{
|
||||
/*forget any remove bits*/
|
||||
client->pendingentbits[j] = UF_RESET | SVFTE_DeltaCalcBits(&EDICT_NUM(svprogfuncs, n->number)->baseline, n);
|
||||
/*flag it for reset, we can add the extra bits later once we get around to sending it*/
|
||||
client->pendingentbits[j] = UF_RESET | UF_RESET2;
|
||||
}
|
||||
else
|
||||
{
|
||||
client->pendingentbits[j] |= SVFTE_DeltaCalcBits(o, n);;
|
||||
client->pendingentbits[j] |= SVFTE_DeltaCalcBits(o, n);
|
||||
}
|
||||
*o = *n;
|
||||
j++;
|
||||
|
@ -1041,42 +1088,72 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t
|
|||
o = &client->sentents.entities[j];
|
||||
if (o->number)
|
||||
{
|
||||
client->pendingentbits[j] = UF_REMOVE;
|
||||
o->number = 0; /*dead*/
|
||||
e = EDICT_NUM(svprogfuncs, o->number);
|
||||
if (!((int)e->xv->pvsflags & PVSF_NOREMOVE))
|
||||
{
|
||||
client->pendingentbits[j] = UF_REMOVE;
|
||||
o->number = 0; /*dead*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resend = client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK].resendentbits;
|
||||
/*cache frame info*/
|
||||
resendbits = client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK].resendentbits;
|
||||
resendnum = client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK].resendentnum;
|
||||
outno = 0;
|
||||
outmax = client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK].entities.max_entities;
|
||||
|
||||
/*start writing the packet*/
|
||||
MSG_WriteByte (msg, svcfte_updateentities);
|
||||
MSG_WriteFloat(msg, sv.world.physicstime);
|
||||
if (reset)
|
||||
if (reset) /*if we're resetting, the client will see 'remove world' which should be handled as a special case*/
|
||||
MSG_WriteShort(msg, 0x8000);
|
||||
|
||||
memset(resend, 0, client->sentents.max_entities*sizeof(*resend));
|
||||
|
||||
for(j = 0; j < client->sentents.max_entities; j++)
|
||||
{
|
||||
if (!client->pendingentbits[j])
|
||||
bits = client->pendingentbits[j];
|
||||
if (!(bits & ~UF_RESET2)) //skip while there's nothing to send (skip reset2 if there's no other changes, its only to reduce chances of the client getting 'new' entities containing just an origin)*/
|
||||
continue;
|
||||
if (msg->cursize + 50 > msg->maxsize)
|
||||
break; /*give up if it gets full*/
|
||||
if (outno >= outmax)
|
||||
break;
|
||||
client->pendingentbits[j] = 0;
|
||||
|
||||
if (client->pendingentbits[j] & UF_REMOVE)
|
||||
if (bits & UF_REMOVE)
|
||||
{
|
||||
MSG_WriteShort(msg, j | 0x8000);
|
||||
resend[j] = UF_REMOVE;
|
||||
resendbits[outno] = UF_REMOVE;
|
||||
// Con_Printf("REMOVE %i @ %i\n", j, client->netchan.incoming_sequence);
|
||||
}
|
||||
else
|
||||
else if (client->sentents.entities[j].number) /*only send a new copy of the ent if they actually have one already*/
|
||||
{
|
||||
if (bits & UF_RESET2)
|
||||
{
|
||||
/*if reset2, then this is the second packet sent to the client and should have a forced reset (but which isn't tracked)*/
|
||||
resendbits[outno] = bits & ~UF_RESET2;
|
||||
bits = UF_RESET | SVFTE_DeltaCalcBits(&EDICT_NUM(svprogfuncs, j)->baseline, &client->sentents.entities[j]);
|
||||
// Con_Printf("RESET2 %i @ %i\n", j, client->netchan.incoming_sequence);
|
||||
}
|
||||
else if (bits & UF_RESET)
|
||||
{
|
||||
/*flag the entity for the next packet, so we always get two resets when it appears, to reduce the effects of packetloss on seeing rockets etc*/
|
||||
client->pendingentbits[j] = UF_RESET2;
|
||||
bits = UF_RESET | SVFTE_DeltaCalcBits(&EDICT_NUM(svprogfuncs, j)->baseline, &client->sentents.entities[j]);
|
||||
resendbits[outno] = UF_RESET;
|
||||
// Con_Printf("RESET %i @ %i\n", j, client->netchan.incoming_sequence);
|
||||
}
|
||||
else
|
||||
resendbits[outno] = bits;
|
||||
MSG_WriteShort(msg, j);
|
||||
SVFTE_WriteUpdate(client->pendingentbits[j], &client->sentents.entities[j], msg);
|
||||
resend[j] = client->pendingentbits[j];
|
||||
SVFTE_WriteUpdate(bits, &client->sentents.entities[j], msg);
|
||||
}
|
||||
client->pendingentbits[j] = 0;
|
||||
resendnum[outno++] = j;
|
||||
}
|
||||
|
||||
MSG_WriteShort(msg, 0);
|
||||
|
||||
client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK].entities.num_entities = outno;
|
||||
client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK].sequence = client->netchan.incoming_sequence;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2590,7 +2667,6 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
|
|||
//note that client can be null, for building baselines.
|
||||
|
||||
int i;
|
||||
|
||||
state->number = NUM_FOR_EDICT(svprogfuncs, ent);
|
||||
|
||||
state->u.q1.msec = 0;
|
||||
|
@ -2601,13 +2677,18 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
|
|||
state->u.q1.velocity[0] = 0;
|
||||
state->u.q1.velocity[1] = 0;
|
||||
state->u.q1.velocity[2] = 0;
|
||||
|
||||
if (client == &svs.clients[state->number-1])
|
||||
state->u.q1.weaponframe = ent->v->weaponframe;
|
||||
else
|
||||
state->u.q1.weaponframe = 0;
|
||||
if ((state->number-1) < (unsigned short)sv.allocated_client_slots && ent->v->movetype)
|
||||
{
|
||||
client_t *cl = &svs.clients[state->number-1];
|
||||
if (cl->isindependant)
|
||||
{
|
||||
state->u.q1.pmovetype = ent->v->movetype;
|
||||
if (cl != client)
|
||||
if (cl != client && client)
|
||||
{ /*only generate movement values if the client doesn't already know them...*/
|
||||
state->u.q1.movement[0] = ent->xv->movement[0];
|
||||
state->u.q1.movement[1] = ent->xv->movement[1];
|
||||
|
@ -2662,6 +2743,7 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
|
|||
state->colormap = ent->v->colormap;
|
||||
state->skinnum = ent->v->skin;
|
||||
state->effects = ent->v->effects;
|
||||
state->effects |= (int)ent->xv->modelflags<<24;
|
||||
state->hexen2flags = ent->xv->drawflags;
|
||||
state->abslight = (int)(ent->xv->abslight*255) & 255;
|
||||
state->tagentity = ent->xv->tag_entity;
|
||||
|
@ -2733,9 +2815,18 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
|
|||
i = ent->xv->colormod[1]*(256/8); state->colormod[1] = bound(0, i, 255);
|
||||
i = ent->xv->colormod[2]*(256/8); state->colormod[2] = bound(0, i, 255);
|
||||
}
|
||||
state->glowmod[0] = ent->xv->glowmod[0]*(256/8);
|
||||
state->glowmod[1] = ent->xv->glowmod[1]*(256/8);
|
||||
state->glowmod[2] = ent->xv->glowmod[2]*(256/8);
|
||||
if (!ent->xv->glowmod[0] && !ent->xv->glowmod[1] && !ent->xv->glowmod[2])
|
||||
{
|
||||
state->glowmod[0] = (256/8);
|
||||
state->glowmod[1] = (256/8);
|
||||
state->glowmod[2] = (256/8);
|
||||
}
|
||||
else
|
||||
{
|
||||
state->glowmod[0] = ent->xv->glowmod[0]*(256/8);
|
||||
state->glowmod[1] = ent->xv->glowmod[1]*(256/8);
|
||||
state->glowmod[2] = ent->xv->glowmod[2]*(256/8);
|
||||
}
|
||||
state->glowsize = ent->xv->glow_size*0.25;
|
||||
state->glowcolour = ent->xv->glow_color;
|
||||
if (ent->xv->glow_trail)
|
||||
|
|
|
@ -218,82 +218,7 @@ baseline will be transmitted
|
|||
}
|
||||
*/
|
||||
|
||||
void SV_EdictToEntState (int num, edict_t *ent, entity_state_t *state)
|
||||
{
|
||||
int i;
|
||||
|
||||
state->number = num;
|
||||
state->flags = 0;
|
||||
VectorCopy (ent->v->origin, state->origin);
|
||||
VectorCopy (ent->v->angles, state->angles);
|
||||
state->modelindex = ent->v->modelindex;
|
||||
state->frame = ent->v->frame;
|
||||
state->colormap = ent->v->colormap;
|
||||
state->skinnum = ent->v->skin;
|
||||
state->effects = ent->v->effects;
|
||||
state->hexen2flags = ent->xv->drawflags;
|
||||
state->abslight = (int)(ent->xv->abslight*255) & 255;
|
||||
state->tagentity = ent->xv->tag_entity;
|
||||
state->tagindex = ent->xv->tag_index;
|
||||
|
||||
state->light[0] = ent->xv->color[0]*255;
|
||||
state->light[1] = ent->xv->color[1]*255;
|
||||
state->light[2] = ent->xv->color[2]*255;
|
||||
state->light[3] = ent->xv->light_lev;
|
||||
state->lightstyle = ent->xv->style;
|
||||
state->lightpflags = ent->xv->pflags;
|
||||
|
||||
/* if ((int)ent->v->flags & FL_CLASS_DEPENDENT && client->playerclass) //hexen2 wierdness.
|
||||
{
|
||||
char modname[MAX_QPATH];
|
||||
Q_strncpyz(modname, sv.strings.model_precache[state->modelindex], sizeof(modname));
|
||||
if (strlen(modname)>5)
|
||||
{
|
||||
modname[strlen(modname)-5] = client->playerclass+'0';
|
||||
state->modelindex = SV_ModelIndex(modname);
|
||||
}
|
||||
}*/
|
||||
if (/*progstype == PROG_H2 &&*/ ent->v->solid == SOLID_BSP)
|
||||
state->angles[0]*=-1;
|
||||
|
||||
if (ent->v->solid == SOLID_BSP)
|
||||
state->solid = ES_SOLID_BSP;
|
||||
|
||||
if (state->effects & EF_FULLBRIGHT)
|
||||
{
|
||||
state->hexen2flags |= MLS_FULLBRIGHT;
|
||||
}
|
||||
|
||||
if (!ent->xv->alpha)
|
||||
state->trans = 255;
|
||||
else
|
||||
state->trans = ent->xv->alpha*255;
|
||||
|
||||
if (!ent->xv->colormod[0] && !ent->xv->colormod[1] && !ent->xv->colormod[2])
|
||||
{
|
||||
state->colormod[0] = (256)/8;
|
||||
state->colormod[1] = (256)/8;
|
||||
state->colormod[2] = (256)/8;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = ent->xv->colormod[0]*(256/8); state->colormod[0] = bound(0, i, 255);
|
||||
i = ent->xv->colormod[1]*(256/8); state->colormod[1] = bound(0, i, 255);
|
||||
i = ent->xv->colormod[2]*(256/8); state->colormod[2] = bound(0, i, 255);
|
||||
}
|
||||
state->glowsize = ent->xv->glow_size*0.25;
|
||||
state->glowcolour = ent->xv->glow_color;
|
||||
#define RENDER_GLOWTRAIL 2
|
||||
if (ent->xv->glow_trail)
|
||||
state->dpflags |= RENDER_GLOWTRAIL;
|
||||
|
||||
if (!ent->xv->scale)
|
||||
state->scale = 1*16;
|
||||
else
|
||||
state->scale = ent->xv->scale*16;
|
||||
|
||||
state->fatness = ent->xv->fatness*16;
|
||||
}
|
||||
void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *client);
|
||||
|
||||
void SVNQ_CreateBaseline (void)
|
||||
{
|
||||
|
@ -320,7 +245,7 @@ void SVNQ_CreateBaseline (void)
|
|||
//
|
||||
// create entity baseline
|
||||
//
|
||||
SV_EdictToEntState(entnum, svent, &svent->baseline);
|
||||
SV_Snapshot_BuildStateQ1(&svent->baseline, svent, NULL);
|
||||
|
||||
if (entnum > 0 && entnum <= sv.allocated_client_slots)
|
||||
{
|
||||
|
@ -329,7 +254,10 @@ void SVNQ_CreateBaseline (void)
|
|||
else
|
||||
svent->baseline.colormap = 0; //this would crash NQ.
|
||||
|
||||
svent->baseline.modelindex = playermodel;
|
||||
if (!svent->baseline.solid)
|
||||
svent->baseline.solid = (2 | (3<<5) | (4<<10));
|
||||
if (!svent->baseline.modelindex)
|
||||
svent->baseline.modelindex = playermodel;
|
||||
}
|
||||
svent->baseline.modelindex&=255;
|
||||
}
|
||||
|
|
|
@ -2268,12 +2268,24 @@ client_t *SVC_DirectConnect(void)
|
|||
|
||||
if ((temp.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS))// || ISDPCLIENT(&temp))
|
||||
{
|
||||
temp.frameunion.frames = Z_Malloc(sizeof(client_frame_t)*UPDATE_BACKUP+sizeof(unsigned int)*temp.max_net_ents*UPDATE_BACKUP + sizeof(unsigned int)*temp.max_net_ents);
|
||||
char *ptr;
|
||||
int maxents = maxpacketentities; /*this is the max number of ents updated per frame. we can't track more, so...*/
|
||||
ptr = Z_Malloc( sizeof(client_frame_t)*UPDATE_BACKUP+
|
||||
sizeof(*temp.pendingentbits)*temp.max_net_ents+
|
||||
sizeof(unsigned int)*maxents*UPDATE_BACKUP+
|
||||
sizeof(unsigned short)*maxents*UPDATE_BACKUP);
|
||||
temp.frameunion.frames = (void*)ptr;
|
||||
ptr += sizeof(*temp.frameunion.frames)*UPDATE_BACKUP;
|
||||
temp.pendingentbits = (void*)ptr;
|
||||
ptr += sizeof(*temp.pendingentbits)*temp.max_net_ents;
|
||||
for (i = 0; i < UPDATE_BACKUP; i++)
|
||||
{
|
||||
temp.frameunion.frames[i].resendentbits = (unsigned int*)(temp.frameunion.frames+UPDATE_BACKUP) + i*temp.max_net_ents;
|
||||
temp.frameunion.frames[i].entities.max_entities = maxents;
|
||||
temp.frameunion.frames[i].resendentnum = (void*)ptr;
|
||||
ptr += sizeof(*temp.frameunion.frames[i].resendentnum)*maxents;
|
||||
temp.frameunion.frames[i].resendentbits = (void*)ptr;
|
||||
ptr += sizeof(*temp.frameunion.frames[i].resendentbits)*maxents;
|
||||
}
|
||||
temp.pendingentbits = (unsigned int*)(temp.frameunion.frames+UPDATE_BACKUP) + UPDATE_BACKUP*temp.max_net_ents;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1532,7 +1532,7 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf
|
|||
if (!client->spectator)
|
||||
{
|
||||
statsf[STAT_ACTIVEWEAPON] = ent->v->weapon;
|
||||
if (client->csqcactive || client->protocol != SCP_QUAKEWORLD)
|
||||
if ((client->csqcactive && !(client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)) || client->protocol != SCP_QUAKEWORLD)
|
||||
statsf[STAT_WEAPONFRAME] = ent->v->weaponframe;
|
||||
}
|
||||
|
||||
|
|
|
@ -6193,7 +6193,6 @@ void SV_ExecuteClientMessage (client_t *cl)
|
|||
// save time for ping calculations
|
||||
if (cl->frameunion.frames)
|
||||
{ //split screen doesn't always have frames.
|
||||
cl->frameunion.frames[cl->netchan.outgoing_sequence & UPDATE_MASK].sequence = cl->netchan.outgoing_sequence;
|
||||
cl->frameunion.frames[cl->netchan.outgoing_sequence & UPDATE_MASK].senttime = realtime;
|
||||
cl->frameunion.frames[cl->netchan.outgoing_sequence & UPDATE_MASK].ping_time = -1;
|
||||
cl->frameunion.frames[cl->netchan.outgoing_sequence & UPDATE_MASK].move_msecs = -1;
|
||||
|
|
Loading…
Reference in a new issue