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:
Spoike 2012-02-14 15:50:34 +00:00
parent 61061c8e71
commit ee72d0ca0d
29 changed files with 481 additions and 326 deletions

View file

@ -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.

View file

@ -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

View file

@ -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*/

View file

@ -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])

View file

@ -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

View file

@ -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)

View file

@ -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
{

View file

@ -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)
{

View file

@ -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
{

View file

@ -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);
}

View file

@ -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)
{

View file

@ -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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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"

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;
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;
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,11 +1047,18 @@ 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();
if (!strcmp(fontfilename, "gfx/hexen2"))
{
f->singletexture = Font_LoadHexen2Conchars(true);
defaultplane = DEFAULTPLANE;
}
if (!TEXVALID(f->singletexture))
f->singletexture = fontplanes.defaultfont;
}
@ -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;
}

View file

@ -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"

View file

@ -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
{

View file

@ -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

View file

@ -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()")

View file

@ -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;

View file

@ -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)
{
if (SVFTE_DeltaPredCalcBits(from, to))
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;
/*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];
@ -1016,21 +1059,25 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t
{
o = &client->sentents.entities[j];
if (o->number)
{
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++;
@ -1040,43 +1087,73 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t
{
o = &client->sentents.entities[j];
if (o->number)
{
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 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);
}
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)

View file

@ -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,6 +254,9 @@ void SVNQ_CreateBaseline (void)
else
svent->baseline.colormap = 0; //this would crash NQ.
if (!svent->baseline.solid)
svent->baseline.solid = (2 | (3<<5) | (4<<10));
if (!svent->baseline.modelindex)
svent->baseline.modelindex = playermodel;
}
svent->baseline.modelindex&=255;

View file

@ -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
{

View file

@ -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;
}

View file

@ -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;