------------------------------------------------------------------------

r4196 | acceptthis | 2013-02-12 19:06:07 +0000 (Tue, 12 Feb 2013) | 9 lines

split in/out client frames, so that we can cope with separate packet/movement sequences for nq+prediction.
Make default ports a little more explicit.
interpolate input frames. should make things smoother when the input rate does not match video rate.
fix centering of crosshairs
make sure skins are flushed properly on vid_restart, so 24bit skins don't get messed up.
keep sounds ticking even when inaudible.
qc addressable block now has a max of 2gb.
.__variant works as a function argument.
NQ clients now receive player physics consistant with QuakeWorld.
------------------------------------------------------------------------


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4194 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2013-03-12 22:53:23 +00:00
parent 65b6b27a75
commit a77bd67602
61 changed files with 1418 additions and 1269 deletions

View File

@ -420,7 +420,7 @@ void Cam_SelfTrack(int pnum)
void Cam_Track(int pnum, usercmd_t *cmd)
{
player_state_t *player, *self;
frame_t *frame;
inframe_t *frame;
vec3_t vec;
float len;
@ -443,7 +443,7 @@ void Cam_Track(int pnum, usercmd_t *cmd)
return;
}
frame = &cl.frames[cl.validsequence & UPDATE_MASK];
frame = &cl.inframes[cl.validsequence & UPDATE_MASK];
player = frame->playerstate + spec_track[pnum];
self = frame->playerstate + cl.playernum[pnum];
@ -517,7 +517,7 @@ void Cam_SetAutoTrack(int userid)
void Cam_TrackCrosshairedPlayer(int pnum)
{
frame_t *frame;
inframe_t *frame;
player_state_t *player;
int i;
float dot = 0.1, bestdot=0;
@ -525,7 +525,7 @@ void Cam_TrackCrosshairedPlayer(int pnum)
vec3_t selforg;
vec3_t dir;
frame = &cl.frames[cl.validsequence & UPDATE_MASK];
frame = &cl.inframes[cl.validsequence & UPDATE_MASK];
player = frame->playerstate + cl.playernum[pnum];
VectorCopy(player->origin, selforg);

View File

@ -337,7 +337,7 @@ qboolean CGQ3_GetUserCmd(int cmdNumber, q3usercmd_t *ucmd)
if (ccs.currentUserCmdNumber - cmdNumber > CMD_MASK)
return false; // too old
cmd = &cl.frames[(cmdNumber) & CMD_MASK].cmd[0];
cmd = &cl.outframes[(cmdNumber) & CMD_MASK].cmd[0];
ucmd->angles[0] = cmd->angles[0];
ucmd->angles[1] = cmd->angles[1];
ucmd->angles[2] = cmd->angles[2];

View File

@ -668,7 +668,7 @@ readnext:
{
// user sent input
i = cls.netchan.outgoing_sequence & UPDATE_MASK;
pcmd = &cl.frames[i].cmd[0];
pcmd = &cl.outframes[i].cmd[0];
r = readdemobytes (&demopos, &q1cmd, sizeof(q1cmd));
if (r != sizeof(q1cmd))
{
@ -690,9 +690,9 @@ readnext:
pcmd->buttons = q1cmd.buttons;
cl.frames[i].senttime = demotime;
cl.frames[i].receivedtime = -1; // we haven't gotten a reply yet
cl.outframes[i].senttime = realtime;
cls.netchan.outgoing_sequence++;
cl.movesequence = cls.netchan.outgoing_sequence;
for (i=0 ; i<3 ; i++)
{
readdemobytes (&demopos, &f, 4);
@ -775,6 +775,7 @@ readit:
}
cls.netchan.outgoing_sequence = LittleLong(j);
cls.netchan.incoming_sequence = LittleLong(i);
cl.movesequence = cls.netchan.outgoing_sequence;
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
cls.netchan.incoming_acknowledged = cls.netchan.incoming_sequence;

View File

@ -464,7 +464,7 @@ void FlushEntityPacket (void)
memset (&olde, 0, sizeof(olde));
cl.validsequence = 0; // can't render a frame
cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].invalid = true;
cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK].invalid = true;
// read it all, but ignore it
while (1)
@ -719,6 +719,7 @@ void CLFTE_ParseEntities(void)
qboolean isvalid = false;
entity_state_t *e;
qboolean removeflag;
int inputframe = cls.netchan.incoming_sequence;
// int i;
// for (i = cl.validsequence+1; i < cls.netchan.incoming_sequence; i++)
@ -737,11 +738,10 @@ void CLFTE_ParseEntities(void)
int i;
for (i = 0; i < MAX_SPLITS; i++)
cl.playerview[i].fixangle = false;
cls.netchan.outgoing_sequence = cls.netchan.incoming_unreliable;
cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence;
cls.netchan.outgoing_sequence++;
cls.netchan.incoming_sequence = cls.netchan.incoming_unreliable;
cl.last_servermessage = realtime;
cl.ackedinputsequence = MSG_ReadLong();
if (cls.fteprotocolextensions2 & PEXT2_PREDINFO)
inputframe = MSG_ReadLong();
if (cl.numackframes == sizeof(cl.ackframes)/sizeof(cl.ackframes[0]))
cl.numackframes--;
@ -750,7 +750,7 @@ void CLFTE_ParseEntities(void)
else
cl.ackframes[cl.numackframes++] = cls.netchan.incoming_sequence;
cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].receivedtime = realtime;
cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK].receivedtime = realtime;
// if (cl.validsequence != cls.netchan.incoming_sequence-1)
// Con_Printf("CLIENT: Dropped a frame\n");
@ -759,9 +759,9 @@ void CLFTE_ParseEntities(void)
newpacket = cls.netchan.incoming_sequence&UPDATE_MASK;
oldpacket = cl.validsequence&UPDATE_MASK;
newp = &cl.frames[newpacket].packet_entities;
oldp = &cl.frames[oldpacket].packet_entities;
cl.frames[newpacket].invalid = true;
newp = &cl.inframes[newpacket].packet_entities;
oldp = &cl.inframes[oldpacket].packet_entities;
cl.inframes[newpacket].invalid = true;
if (!cl.validsequence || cls.netchan.incoming_sequence-cl.validsequence >= UPDATE_BACKUP-1 || oldp == newp)
@ -874,8 +874,8 @@ void CLFTE_ParseEntities(void)
/*update the prediction info if needed*/
// if (e->u.q1.pmovetype)
{
frame_t *fram;
fram = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
inframe_t *fram;
fram = &cl.inframes[cls.netchan.incoming_sequence & UPDATE_MASK];
CL_PlayerFrameUpdated(&fram->playerstate[e->number-1], e, cls.netchan.incoming_sequence);
}
}
@ -884,17 +884,14 @@ void CLFTE_ParseEntities(void)
{
cl.oldvalidsequence = cl.validsequence;
cl.validsequence = cls.netchan.incoming_sequence;
cl.ackedinputsequence = cl.validsequence;
cl.frames[newpacket].invalid = false;
cl.ackedmovesequence = inputframe;
cl.inframes[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;
}
/*
@ -915,8 +912,8 @@ void CLQW_ParsePacketEntities (qboolean delta)
int from;
newpacket = cls.netchan.incoming_sequence&UPDATE_MASK;
newp = &cl.frames[newpacket].packet_entities;
cl.frames[newpacket].invalid = false;
newp = &cl.inframes[newpacket].packet_entities;
cl.inframes[newpacket].invalid = false;
if (cls.protocol == CP_QUAKEWORLD && cls.demoplayback == DPB_MVD)
{
@ -942,7 +939,7 @@ void CLQW_ParsePacketEntities (qboolean delta)
// Con_Printf("%i %i from %i\n", cls.netchan.outgoing_sequence, cls.netchan.incoming_sequence, from);
oldpacket = cl.frames[newpacket].delta_sequence;
oldpacket = cl.inframes[newpacket].delta_sequence;
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
from = oldpacket = cls.netchan.incoming_sequence - 1;
@ -970,7 +967,7 @@ void CLQW_ParsePacketEntities (qboolean delta)
return;
}
oldp = &cl.frames[oldpacket & UPDATE_MASK].packet_entities;
oldp = &cl.inframes[oldpacket & UPDATE_MASK].packet_entities;
full = false;
}
else
@ -982,6 +979,7 @@ void CLQW_ParsePacketEntities (qboolean delta)
cl.oldvalidsequence = cl.validsequence;
cl.validsequence = cls.netchan.incoming_sequence;
cl.ackedmovesequence = cl.validsequence;
oldindex = 0;
newindex = 0;
@ -1130,7 +1128,7 @@ entity_state_t *CL_FindOldPacketEntity(int num)
packet_entities_t *pack;
if (!cl.validsequence)
return NULL;
pack = &cl.frames[(cls.netchan.incoming_sequence-1)&UPDATE_MASK].packet_entities;
pack = &cl.inframes[(cls.netchan.incoming_sequence-1)&UPDATE_MASK].packet_entities;
for (pnum=0 ; pnum<pack->num_entities ; pnum++)
{
@ -1300,10 +1298,10 @@ void CLDP_ParseDarkPlaces5Entities(void) //the things I do.. :o(
cl.ackframes[cl.numackframes++] = MSG_ReadLong(); /*server sequence to be acked*/
if (cls.protocol_nq >= CPNQ_DP7)
cl.ackedinputsequence = MSG_ReadLong(); /*client input sequence which has been acked*/
cl.ackedmovesequence = MSG_ReadLong(); /*client input sequence which has been acked*/
cl.frames[(cls.netchan.incoming_sequence)&UPDATE_MASK].receivedtime = realtime;
pack = &cl.frames[(cls.netchan.incoming_sequence)&UPDATE_MASK].packet_entities;
cl.inframes[(cls.netchan.incoming_sequence)&UPDATE_MASK].receivedtime = realtime;
pack = &cl.inframes[(cls.netchan.incoming_sequence)&UPDATE_MASK].packet_entities;
pack->servertime = cl.gametime;
oldpack = *pack;
oldi = 0;
@ -1428,7 +1426,7 @@ void CLNQ_ParseEntity(unsigned int bits)
cls.signon = 4;
CLNQ_SignonReply ();
}
pack = &cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities;
pack = &cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities;
if (bits & NQU_MOREBITS)
@ -1566,7 +1564,7 @@ entity_state_t *CL_FindPacketEntity(int num)
int pnum;
entity_state_t *s1;
packet_entities_t *pack;
pack = &cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities;
pack = &cl.inframes[cl.validsequence&UPDATE_MASK].packet_entities;
for (pnum=0 ; pnum<pack->num_entities ; pnum++)
{
@ -1625,10 +1623,10 @@ void CL_RotateAroundTag(entity_t *ent, int entnum, int parenttagent, int parentt
}
else
{
org = cl.frames[parsecountmod].playerstate[parenttagent-1].origin;
ang = cl.frames[parsecountmod].playerstate[parenttagent-1].viewangles;
org = cl.inframes[parsecountmod].playerstate[parenttagent-1].origin;
ang = cl.inframes[parsecountmod].playerstate[parenttagent-1].viewangles;
}
model = cl.frames[parsecountmod].playerstate[parenttagent-1].modelindex;
model = cl.inframes[parsecountmod].playerstate[parenttagent-1].modelindex;
CL_LerpNetFrameState(FS_REG, &fstate, &cl.lerpplayers[parenttagent-1]);
}
@ -2248,7 +2246,7 @@ void CLQ1_AddVisibleBBoxes(void)
#endif
case 3:
{
frame_t *frame;
inframe_t *frame;
packet_entities_t *pak;
entity_state_t *state;
model_t *mod;
@ -2262,7 +2260,7 @@ void CLQ1_AddVisibleBBoxes(void)
"alphagen vertex\n"
"}\n"
"}\n");
frame = &cl.frames[cl.parsecount & UPDATE_MASK];
frame = &cl.inframes[cl.parsecount & UPDATE_MASK];
pak = &frame->packet_entities;
for (i=0 ; i<pak->num_entities ; i++)
@ -2279,7 +2277,7 @@ void CLQ1_AddVisibleBBoxes(void)
if (!cl.model_precache[state->modelindex])
continue;
/*this makes non-inline bsp objects non-solid for prediction*/
if ((*cl.model_precache[state->modelindex]->name == '*' || cl.model_precache[state->modelindex]->numsubmodels) && cl.model_precache[state->modelindex]->hulls[1].firstclipnode)
if ((cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) || ((*cl.model_precache[state->modelindex]->name == '*' || cl.model_precache[state->modelindex]->numsubmodels) && cl.model_precache[state->modelindex]->hulls[1].firstclipnode))
{
mod = cl.model_precache[state->modelindex];
VectorAdd(state->origin, mod->mins, min);
@ -2882,23 +2880,23 @@ static qboolean CL_ChooseInterpolationFrames(int *newf, int *oldf, float servert
//we should be picking the packet just after the server time, and the one just before
for (i = cls.netchan.incoming_sequence; i >= cls.netchan.incoming_sequence-UPDATE_MASK; i--)
{
if (cl.frames[i&UPDATE_MASK].receivedtime < 0 || cl.frames[i&UPDATE_MASK].invalid)
if (cl.inframes[i&UPDATE_MASK].receivedtime < 0 || cl.inframes[i&UPDATE_MASK].invalid)
continue; //packetloss/choke, it's really only a problem for the oldframe, but...
if (cl.frames[i&UPDATE_MASK].packet_entities.servertime >= servertime)
if (cl.inframes[i&UPDATE_MASK].packet_entities.servertime >= servertime)
{
if (cl.frames[i&UPDATE_MASK].packet_entities.servertime)
if (cl.inframes[i&UPDATE_MASK].packet_entities.servertime)
{
if (!newtime || newtime != cl.frames[i&UPDATE_MASK].packet_entities.servertime) //if it's a duplicate, pick the latest (so just-shot rockets are still present)
if (!newtime || newtime != cl.inframes[i&UPDATE_MASK].packet_entities.servertime) //if it's a duplicate, pick the latest (so just-shot rockets are still present)
{
newtime = cl.frames[i&UPDATE_MASK].packet_entities.servertime;
newtime = cl.inframes[i&UPDATE_MASK].packet_entities.servertime;
*newf = i;
}
}
}
else if (newtime)
{
if (cl.frames[i&UPDATE_MASK].packet_entities.servertime != newtime)
if (cl.inframes[i&UPDATE_MASK].packet_entities.servertime != newtime)
{ //it does actually lerp, and isn't an identical frame.
*oldf = i;
break;
@ -2917,7 +2915,7 @@ static qboolean CL_ChooseInterpolationFrames(int *newf, int *oldf, float servert
/*just grab the most recent frame that is valid*/
for (i = cls.netchan.incoming_sequence; i >= cls.netchan.incoming_sequence-UPDATE_MASK; i--)
{
if (cl.frames[i&UPDATE_MASK].receivedtime < 0 || cl.frames[i&UPDATE_MASK].invalid)
if (cl.inframes[i&UPDATE_MASK].receivedtime < 0 || cl.inframes[i&UPDATE_MASK].invalid)
continue; //packetloss/choke, it's really only a problem for the oldframe, but...
*oldf = *newf = i;
return true;
@ -2943,7 +2941,7 @@ qboolean CL_MayLerp(void)
if (cls.protocol == CP_NETQUAKE) //this includes DP protocols.
return !cl_nolerp_netquake.ival;
#endif
if (cl_nolerp.ival == 2 && cls.gamemode != GAME_DEATHMATCH)
if (cl_nolerp.ival == 2 && !cls.deathmatch)
return true;
return !cl_nolerp.ival;
}
@ -2967,7 +2965,7 @@ void CL_TransitionEntities (void)
//force our emulated time to as late as we can, if we're not using interpolation, which has the effect of disabling all interpolation
if (nolerp)
servertime = cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities.servertime;
servertime = cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities.servertime;
else
servertime = cl.servertime;
@ -2981,8 +2979,8 @@ void CL_TransitionEntities (void)
newf&=UPDATE_MASK;
oldf&=UPDATE_MASK;
/*transition the ents and stuff*/
packnew = &cl.frames[newf].packet_entities;
packold = &cl.frames[oldf].packet_entities;
packnew = &cl.inframes[newf].packet_entities;
packold = &cl.inframes[oldf].packet_entities;
// Con_Printf("%f %f %f (%i)\n", packold->servertime, servertime, packnew->servertime, newff);
// Con_Printf("%f %f %f\n", cl.oldgametime, servertime, cl.gametime);
@ -3009,8 +3007,8 @@ void CL_TransitionEntities (void)
frac = 1; //lerp totally into the new
else
frac = (servertime-packold->servertime)/(packnew->servertime-packold->servertime);
pnew = &cl.frames[newf].playerstate[0];
pold = &cl.frames[oldf].playerstate[0];
pnew = &cl.inframes[newf].playerstate[0];
pold = &cl.inframes[oldf].playerstate[0];
for (p = 0; p < cl.allocated_client_slots; p++, pnew++, pold++)
{
if (pnew->messagenum != newff)
@ -3152,7 +3150,7 @@ void CL_LinkPacketEntities (void)
if (radius)
{
radius += r_lightflicker.value?((flicker + state->number)&31):0;
CL_NewDlight(state->number, state->origin, radius, 0.1, colour[0], colour[1], colour[2]);
CL_NewDlight(state->number, ent->origin, radius, 0.1, colour[0], colour[1], colour[2]);
}
}
if (state->lightpflags & PFLAGS_FULLDYNAMIC)
@ -3168,7 +3166,7 @@ void CL_LinkPacketEntities (void)
colour[1] = state->light[1]/1024.0f;
colour[2] = state->light[2]/1024.0f;
}
dl = CL_NewDlight(state->number, state->origin, state->light[3]?state->light[3]:350, 0.1, colour[0], colour[1], colour[2]);
dl = CL_NewDlight(state->number, ent->origin, state->light[3]?state->light[3]:350, 0.1, colour[0], colour[1], colour[2]);
dl->corona = (state->lightpflags & PFLAGS_CORONA)?1:0;
dl->coronascale = 0.25;
dl->flags &= ~LFLAG_FLASHBLEND;
@ -3208,7 +3206,7 @@ void CL_LinkPacketEntities (void)
if (cl.model_precache_vwep[0])
{
if (state->modelindex == cl_playerindex)
if (state->modelindex == cl_playerindex && !cl.model_precache_vwep[0]->needload)
{
model = cl.model_precache_vwep[0];
model2 = cl.model_precache_vwep[state->modelindex2];
@ -3622,8 +3620,8 @@ void CL_MVDUpdateSpectator(void)
int s;
for (s = 0; s < cl.splitclients; s++)
{
self = &cl.frames[cl.parsecount & UPDATE_MASK].playerstate[cl.playernum[s]];
oldself = &cl.frames[(cls.netchan.outgoing_sequence - 1) & UPDATE_MASK].playerstate[cl.playernum[s]];
self = &cl.inframes[cl.parsecount & UPDATE_MASK].playerstate[cl.playernum[s]];
oldself = &cl.inframes[(cls.netchan.outgoing_sequence - 1) & UPDATE_MASK].playerstate[cl.playernum[s]];
// cl.frames[cl.parsecount & UPDATE_MASK].senttime = cl.frames[(cls.netchan.outgoing_sequence - 1) & UPDATE_MASK].senttime;
// self->messagenum = cl.parsecount;
@ -3654,8 +3652,8 @@ void CL_ParsePlayerinfo (void)
info = &cl.players[num];
oldstate = &cl.frames[oldparsecountmod].playerstate[num];
state = &cl.frames[parsecountmod].playerstate[num];
oldstate = &cl.inframes[oldparsecountmod].playerstate[num];
state = &cl.inframes[parsecountmod].playerstate[num];
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
{
@ -3667,7 +3665,7 @@ void CL_ParsePlayerinfo (void)
}
else
{
prevstate = &cl.frames[info->prevcount & UPDATE_MASK].playerstate[num];
prevstate = &cl.inframes[info->prevcount & UPDATE_MASK].playerstate[num];
}
memcpy(state, prevstate, sizeof(player_state_t));
info->prevcount = cl.parsecount;
@ -3699,7 +3697,7 @@ void CL_ParsePlayerinfo (void)
}
VectorSubtract(state->origin, prevstate->origin, dist);
VectorScale(dist, 1/(cl.frames[parsecountmod].packet_entities.servertime - cl.frames[oldparsecountmod].packet_entities.servertime), state->velocity);
VectorScale(dist, 1/(cl.inframes[parsecountmod].packet_entities.servertime - cl.inframes[oldparsecountmod].packet_entities.servertime), state->velocity);
VectorCopy (state->origin, state->predorigin);
for (i = 0; i < 3; i++)
@ -3976,7 +3974,7 @@ guess_pm_type:
//can't CL_SetStatInt as we don't know if its actually us or not
for (i = 0; i < cl.splitclients; i++)
{
if (spec_track[i] == num)
if ((cl.spectator?spec_track[i]:cl.playernum[i]) == num)
{
cl.playerview[i].stats[STAT_WEAPONFRAME] = state->weaponframe;
cl.playerview[i].statsf[STAT_WEAPONFRAME] = state->weaponframe;
@ -4123,8 +4121,8 @@ void CL_LinkPlayers (void)
double playertime;
entity_t *ent;
int msec;
frame_t *frame;
frame_t *fromf;
inframe_t *frame;
inframe_t *fromf;
int oldphysent;
vec3_t angles;
qboolean predictplayers;
@ -4141,8 +4139,8 @@ void CL_LinkPlayers (void)
if (playertime > realtime)
playertime = realtime;
frame = &cl.frames[cl.validsequence&UPDATE_MASK];
fromf = &cl.frames[cl.oldvalidsequence&UPDATE_MASK];
frame = &cl.inframes[cl.validsequence&UPDATE_MASK];
fromf = &cl.inframes[cl.oldvalidsequence&UPDATE_MASK];
predictplayers = cl_predict_players.ival;
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
@ -4510,7 +4508,7 @@ void CL_LinkViewModel(void)
plnum = Cam_TrackNum(r_refdef.currentplayernum);
if (plnum == -1)
plnum = cl.playernum[r_refdef.currentplayernum];
plstate = &cl.frames[parsecountmod].playerstate[plnum];
plstate = &cl.inframes[parsecountmod].playerstate[plnum];
CLQ1_AddPowerupShell(V_AddEntity(&ent), true, plstate?plstate->effects:0);
@ -4548,7 +4546,7 @@ Builds all the pmove physents for the current frame
void CL_SetSolidEntities (void)
{
int i;
frame_t *frame;
inframe_t *frame;
packet_entities_t *pak;
entity_state_t *state;
physent_t *pent;
@ -4559,7 +4557,7 @@ void CL_SetSolidEntities (void)
pmove.physents[0].info = 0;
pmove.numphysent = 1;
frame = &cl.frames[parsecountmod];
frame = &cl.inframes[parsecountmod];
pak = &frame->packet_entities;
for (i=0 ; i<pak->num_entities ; i++)
@ -4575,17 +4573,18 @@ void CL_SetSolidEntities (void)
continue;
if (!cl.model_precache[state->modelindex])
continue;
/*this makes non-inline bsp objects non-solid for prediction*/
if ((*cl.model_precache[state->modelindex]->name == '*' || cl.model_precache[state->modelindex]->numsubmodels) && cl.model_precache[state->modelindex]->hulls[1].firstclipnode)
{
pent = &pmove.physents[pmove.numphysent];
memset(pent, 0, sizeof(physent_t));
pent->model = cl.model_precache[state->modelindex];
VectorCopy (state->angles, pent->angles);
pent->angles[0]*=-1;
}
else
/*vanilla protocols have no 'solid' information. all entities get assigned ES_SOLID_BSP, even if its not actually solid.
so we need to make sure that item pickups are not erroneously considered solid, but doors etc are.
yes, this probably means that externally loaded models will be predicted non-solid - you'll need to upgrade your network protocol for the gamecode to be able to specify solidity.
*/
if (!(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) && !((*cl.model_precache[state->modelindex]->name == '*' || cl.model_precache[state->modelindex]->numsubmodels) && cl.model_precache[state->modelindex]->hulls[1].firstclipnode))
continue;
pent = &pmove.physents[pmove.numphysent];
memset(pent, 0, sizeof(physent_t));
pent->model = cl.model_precache[state->modelindex];
VectorCopy (state->angles, pent->angles);
pent->angles[0]*=-1;
}
else
{
@ -4649,7 +4648,7 @@ void CL_SetUpPlayerPrediction(qboolean dopred)
player_state_t exact;
double playertime;
int msec;
frame_t *frame;
inframe_t *frame;
struct predicted_player *pplayer;
extern cvar_t cl_nopred;
float predictmsmult = 1000*cl_predict_players_frac.value;
@ -4663,7 +4662,7 @@ void CL_SetUpPlayerPrediction(qboolean dopred)
if (cl_nopred.value || /*cls.demoplayback ||*/ cl.paused || cl.worldmodel->needload)
return;
frame = &cl.frames[cl.parsecount&UPDATE_MASK];
frame = &cl.inframes[cl.parsecount&UPDATE_MASK];
for (j=0, pplayer = predicted_players, state=frame->playerstate;
j < MAX_CLIENTS;
@ -4687,7 +4686,7 @@ void CL_SetUpPlayerPrediction(qboolean dopred)
{
if (j == cl.playernum[s])
{
VectorCopy(cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].playerstate[cl.playernum[s]].origin,
VectorCopy(cl.inframes[cls.netchan.outgoing_sequence&UPDATE_MASK].playerstate[cl.playernum[s]].origin,
pplayer->origin);
break;
}

View File

@ -277,7 +277,7 @@ void IN_JumpDown (void)
else
#endif
if (condition && cl.playerview[pnum].stats[STAT_HEALTH] > 0 && !cls.demoplayback && !cl.spectator &&
cl.frames[cl.validsequence&UPDATE_MASK].playerstate[cl.playernum[pnum]].messagenum == cl.validsequence && cl.waterlevel[pnum] >= 2 && (!cl.teamfortress || !(in_forward.state[pnum] & 1))
cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[cl.playernum[pnum]].messagenum == cl.validsequence && cl.waterlevel[pnum] >= 2 && (!cl.teamfortress || !(in_forward.state[pnum] & 1))
)
KeyDown(&in_up);
else if (condition && cl.spectator && Cam_TrackNum(pnum) == -1)
@ -804,7 +804,7 @@ void CL_FinishMove (usercmd_t *cmd, int msecs, int pnum)
// always dump the first two message, because it may contain leftover inputs
// from the last level
//
if (++cl.movemessages <= 2)
if (cl.movesequence <= 2)
{
cmd->buttons = 0;
return;
@ -923,16 +923,13 @@ void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf)
{
int i;
vec3_t cursor_start, cursor_impact;
int cursor_entitynumber=0;//I hate warnings as errors
if (cls.demoplayback!=DPB_NONE)
return; //err... don't bother... :)
//
// always dump the first two message, because it may contain leftover inputs
// from the last level
//
if (++cl.movemessages <= 2 || cls.state == ca_connected)
if (cl.movesequence <= 2 || cls.state == ca_connected)
{
MSG_WriteByte (buf, clc_nop);
return;
@ -940,8 +937,8 @@ void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf)
MSG_WriteByte (buf, clc_move);
if (cls.protocol_nq >= CPNQ_DP7)
MSG_WriteLong(buf, cls.netchan.outgoing_sequence);
if (cls.protocol_nq >= CPNQ_DP7 || (cls.fteprotocolextensions2 & PEXT2_PREDINFO))
MSG_WriteLong(buf, cl.movesequence);
MSG_WriteFloat (buf, cl.gametime); // so server can get ping times
@ -961,20 +958,15 @@ void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf)
MSG_WriteShort (buf, cmd->sidemove);
MSG_WriteShort (buf, cmd->upmove);
if (cls.protocol_nq >= CPNQ_DP6)
if (cls.protocol_nq >= CPNQ_DP6 || (cls.fteprotocolextensions2 & PEXT2_PRYDONCURSOR))
{
vec3_t cursor_start, cursor_impact;
int cursor_entitynumber;
CL_UpdatePrydonCursor(cmd, cursor_screen, cursor_start, cursor_impact, &cursor_entitynumber);
MSG_WriteLong (buf, cmd->buttons);
}
else
MSG_WriteByte (buf, cmd->buttons);
MSG_WriteByte (buf, cmd->impulse);
if (cls.protocol_nq >= CPNQ_DP6)
{
MSG_WriteByte (buf, cmd->impulse);
MSG_WriteShort (buf, cursor_screen[0] * 32767.0f);
MSG_WriteShort (buf, cursor_screen[1] * 32767.0f);
MSG_WriteFloat (buf, cursor_start[0]);
@ -985,6 +977,11 @@ void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf)
MSG_WriteFloat (buf, cursor_impact[2]);
MSG_WriteEntity (buf, cursor_entitynumber);
}
else
{
MSG_WriteByte (buf, cmd->buttons);
MSG_WriteByte (buf, cmd->impulse);
}
}
void Name_Callback(struct cvar_s *var, char *oldvalue)
@ -1001,14 +998,28 @@ void Name_Callback(struct cvar_s *var, char *oldvalue)
void CLNQ_SendCmd(sizebuf_t *buf)
{
int i;
usercmd_t *cmd;
// if (cls.signon == 4)
i = cl.movesequence & UPDATE_MASK;
cl.outframes[i].senttime = realtime;
cmd = &cl.outframes[i].cmd[0];
*cmd = independantphysics[0];
cmd->lightlevel = 0;
#ifdef CSQC_DAT
CSQC_Input_Frame(0, cmd);
#endif
memset(&independantphysics[0], 0, sizeof(independantphysics[0]));
//inputs are only sent once we receive an entity.
if (cls.signon == 4)
{
// send the unreliable message
if (independantphysics[0].impulse && !cls.netchan.message.cursize)
CLNQ_SendMove (&independantphysics[0], 0, &cls.netchan.message);
CLNQ_SendMove (cmd, 0, &cls.netchan.message);
else
CLNQ_SendMove (&independantphysics[0], 0, buf);
CLNQ_SendMove (cmd, 0, buf);
}
for (i = 0; i < cl.numackframes; i++)
@ -1017,8 +1028,6 @@ void CLNQ_SendCmd(sizebuf_t *buf)
MSG_WriteLong(buf, cl.ackframes[i]);
}
cl.numackframes = 0;
memset(&independantphysics[0], 0, sizeof(independantphysics[0]));
}
#else
void Name_Callback(struct cvar_s *var, char *oldvalue)
@ -1287,7 +1296,7 @@ qboolean CL_WriteDeltas (int plnum, sizebuf_t *buf)
i = (cls.netchan.outgoing_sequence-2) & UPDATE_MASK;
cmd = &cl.frames[i].cmd[plnum];
cmd = &cl.outframes[i].cmd[plnum];
if (cl_c2sImpulseBackup.ival >= 2)
dontdrop = dontdrop || cmd->impulse;
MSG_WriteDeltaUsercmd (buf, &nullcmd, cmd);
@ -1296,21 +1305,21 @@ qboolean CL_WriteDeltas (int plnum, sizebuf_t *buf)
i = (cls.netchan.outgoing_sequence-1) & UPDATE_MASK;
if (cl_c2sImpulseBackup.ival >= 3)
dontdrop = dontdrop || cmd->impulse;
cmd = &cl.frames[i].cmd[plnum];
cmd = &cl.outframes[i].cmd[plnum];
MSG_WriteDeltaUsercmd (buf, oldcmd, cmd);
oldcmd = cmd;
i = (cls.netchan.outgoing_sequence) & UPDATE_MASK;
if (cl_c2sImpulseBackup.ival >= 1)
dontdrop = dontdrop || cmd->impulse;
cmd = &cl.frames[i].cmd[plnum];
cmd = &cl.outframes[i].cmd[plnum];
MSG_WriteDeltaUsercmd (buf, oldcmd, cmd);
return dontdrop;
}
#ifdef Q2CLIENT
qboolean CL_SendCmdQ2 (sizebuf_t *buf)
qboolean CLQ2_SendCmd (sizebuf_t *buf)
{
int seq_hash;
qboolean dontdrop;
@ -1323,7 +1332,7 @@ qboolean CL_SendCmdQ2 (sizebuf_t *buf)
// send this and the previous cmds in the message, so
// if the last packet was dropped, it can be recovered
i = cls.netchan.outgoing_sequence & UPDATE_MASK;
cmd = &cl.frames[i].cmd[0];
cmd = &cl.outframes[i].cmd[0];
if (cls.resendinfo)
{
@ -1349,13 +1358,12 @@ qboolean CL_SendCmdQ2 (sizebuf_t *buf)
// msecs = msecs - (double)msecstouse;
i = cls.netchan.outgoing_sequence & UPDATE_MASK;
cmd = &cl.frames[i].cmd[0];
cmd = &cl.outframes[i].cmd[0];
*cmd = independantphysics[0];
cmd->lightlevel = lightlev;
cl.frames[i].senttime = realtime;
cl.frames[i].receivedtime = -1; // we haven't gotten a reply yet
cl.outframes[i].senttime = realtime;
memset(&independantphysics[0], 0, sizeof(independantphysics[0]));
if (cmd->buttons)
@ -1368,8 +1376,6 @@ qboolean CL_SendCmdQ2 (sizebuf_t *buf)
buf->data + checksumIndex + 1, buf->cursize - checksumIndex - 1,
seq_hash);
cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = -1;
if (cl.sendprespawn)
buf->cursize = 0; //tastyspleen.net is alergic.
@ -1377,16 +1383,18 @@ qboolean CL_SendCmdQ2 (sizebuf_t *buf)
}
#endif
qboolean CL_SendCmdQW (sizebuf_t *buf)
qboolean CLQW_SendCmd (sizebuf_t *buf)
{
int seq_hash;
qboolean dontdrop = false;
usercmd_t *cmd;
int checksumIndex, firstsize, plnum;
int clientcount, lost;
int curframe = cls.netchan.outgoing_sequence & UPDATE_MASK;
int curframe;
int st = buf->cursize;
cl.movesequence = cls.netchan.outgoing_sequence; //make sure its correct even over map changes.
curframe = cls.netchan.outgoing_sequence & UPDATE_MASK;
seq_hash = cls.netchan.outgoing_sequence;
// send this and the previous cmds in the message, so
@ -1399,7 +1407,7 @@ qboolean CL_SendCmdQW (sizebuf_t *buf)
for (plnum = 0; plnum<clientcount; plnum++)
{
cmd = &cl.frames[curframe].cmd[plnum];
cmd = &cl.outframes[curframe].cmd[plnum];
*cmd = independantphysics[plnum];
cmd->lightlevel = 0;
@ -1408,15 +1416,13 @@ qboolean CL_SendCmdQW (sizebuf_t *buf)
#endif
memset(&independantphysics[plnum], 0, sizeof(independantphysics[plnum]));
}
cl.frames[curframe].senttime = realtime;
cl.frames[curframe].receivedtime = -1; // we haven't gotten a reply yet
cl.outframes[curframe].senttime = realtime;
if ((cls.fteprotocolextensions2 & PEXT2_PRYDONCURSOR) && (*cl_prydoncursor.string && cl_prydoncursor.ival >= 0) && cls.state == ca_active)
{
vec3_t cursor_start, cursor_impact;
int cursor_entitynumber = 0;
cmd = &cl.frames[curframe].cmd[0];
cmd = &cl.outframes[curframe].cmd[0];
CL_UpdatePrydonCursor(cmd, cursor_screen, cursor_start, cursor_impact, &cursor_entitynumber);
MSG_WriteByte (buf, clc_prydoncursor);
MSG_WriteShort(buf, cursor_screen[0] * 32767.0f);
@ -1445,7 +1451,7 @@ qboolean CL_SendCmdQW (sizebuf_t *buf)
firstsize=0;
for (plnum = 0; plnum<clientcount; plnum++)
{
cmd = &cl.frames[curframe].cmd[plnum];
cmd = &cl.outframes[curframe].cmd[plnum];
if (plnum)
MSG_WriteByte (buf, clc_move);
@ -1466,15 +1472,16 @@ qboolean CL_SendCmdQW (sizebuf_t *buf)
if (cls.netchan.outgoing_sequence - cl.validsequence >= UPDATE_BACKUP-1)
cl.validsequence = 0;
//delta_sequence is the _expected_ previous sequences, so is set before it arrives.
if (cl.validsequence && !cl_nodelta.ival && cls.state == ca_active && !cls.demorecording)
{
cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = cl.validsequence;
cl.inframes[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = cl.validsequence;
MSG_WriteByte (buf, clc_delta);
// Con_Printf("%i\n", cl.validsequence);
MSG_WriteByte (buf, cl.validsequence&255);
}
else
cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = -1;
cl.inframes[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = -1;
if (cl.sendprespawn)
buf->cursize = st; //tastyspleen.net is alergic.
@ -1515,10 +1522,11 @@ 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
cl.ackedmovesequence = cl.movesequence;
i = cl.movesequence & UPDATE_MASK;
cl.movesequence++;
cl.outframes[i].senttime = realtime; // we haven't gotten a reply yet
// cl.outframes[i].receivedtime = -1; // we haven't gotten a reply yet
if (cl.splitclients > cl_splitscreen.ival+1)
{
@ -1528,7 +1536,7 @@ void CL_SendCmd (double frametime, qboolean mainloop)
}
for (plnum = 0; plnum < cl.splitclients; plnum++)
{
cmd = &cl.frames[i].cmd[plnum];
cmd = &cl.outframes[i].cmd[plnum];
memset(cmd, 0, sizeof(*cmd));
msecs += frametime*1000;
@ -1567,7 +1575,7 @@ void CL_SendCmd (double frametime, qboolean mainloop)
clientcmdlist = next;
}
cls.netchan.outgoing_sequence++;
cls.netchan.outgoing_sequence = cl.movesequence;
}
IN_Move (NULL, 0);
@ -1721,26 +1729,17 @@ void CL_SendCmd (double frametime, qboolean mainloop)
#ifdef NQPROT
case CP_NETQUAKE:
msecs -= (double)msecstouse;
i = cls.netchan.outgoing_sequence & UPDATE_MASK;
cmd = &cl.frames[i].cmd[0];
*cmd = independantphysics[0];
cl.frames[i].senttime = realtime;
cl.frames[i].receivedtime = -1; // nq doesn't allow us to find our own packetloss
#ifdef CSQC_DAT
CSQC_Input_Frame(0, cmd);
#endif
CLNQ_SendCmd (&buf);
break;
#endif
case CP_QUAKEWORLD:
msecs -= (double)msecstouse;
dontdrop = CL_SendCmdQW (&buf);
dontdrop = CLQW_SendCmd (&buf);
break;
#ifdef Q2CLIENT
case CP_QUAKE2:
msecs -= (double)msecstouse;
dontdrop = CL_SendCmdQ2 (&buf);
dontdrop = CLQ2_SendCmd (&buf);
break;
#endif
#ifdef Q3CLIENT
@ -1755,12 +1754,14 @@ void CL_SendCmd (double frametime, qboolean mainloop)
}
}
i = (cls.netchan.outgoing_sequence) & UPDATE_MASK;
cmd = &cl.frames[i].cmd[0];
i = cl.movesequence & UPDATE_MASK;
cmd = &cl.outframes[i].cmd[0];
if (cls.demorecording)
CL_WriteDemoCmd(cmd);
cl.movesequence++;
#ifdef IRCCONNECT
if (cls.netchan.remote_address.type == NA_IRC)
{
@ -1771,7 +1772,7 @@ void CL_SendCmd (double frametime, qboolean mainloop)
else
{
// don't count this message when calculating PL
cl.frames[i].receivedtime = -3;
cl.inframes[i].latency = -3;
// drop this message
cls.netchan.outgoing_sequence++;
dropcount++;
@ -1801,7 +1802,7 @@ void CL_SendCmd (double frametime, qboolean mainloop)
else
{
// don't count this message when calculating PL
cl.frames[i].receivedtime = -3;
cl.inframes[i].latency = -3;
// drop this message
cls.netchan.outgoing_sequence++;
dropcount++;

View File

@ -476,7 +476,7 @@ void CL_SendConnectPacket (int mtu,
t1 = Sys_DoubleTime ();
if (!NET_StringToAdr (cls.servername, &adr))
if (!NET_StringToAdr (cls.servername, PORT_QWSERVER, &adr))
{
Con_TPrintf (TLC_BADSERVERADDRESS);
connect_time = -1;
@ -493,8 +493,6 @@ void CL_SendConnectPacket (int mtu,
return;
}
if (adr.port == 0)
adr.port = BigShort (PORT_QWSERVER);
t2 = Sys_DoubleTime ();
cls.resendinfo = false;
@ -651,7 +649,7 @@ void CL_CheckForResend (void)
break;
#endif
default:
cl.movemessages = 0;
cl.movesequence = 0;
if (!strcmp(cl_loopbackprotocol.string, "qw"))
cls.protocol = CP_QUAKEWORLD;
else if (!strcmp(cl_loopbackprotocol.string, "fitz")) //actually proquake, because we might as well use the extra angles
@ -692,7 +690,7 @@ void CL_CheckForResend (void)
if (cls.protocol == CP_NETQUAKE)
{
if (!NET_StringToAdr (cls.servername, &adr))
if (!NET_StringToAdr (cls.servername, connect_defaultport, &adr))
{
Con_TPrintf (TLC_BADSERVERADDRESS);
connect_time = -1;
@ -762,7 +760,7 @@ void CL_CheckForResend (void)
return;
t1 = Sys_DoubleTime ();
if (!NET_StringToAdr (cls.servername, &adr))
if (!NET_StringToAdr (cls.servername, connect_defaultport, &adr))
{
Con_TPrintf (TLC_BADSERVERADDRESS);
connect_time = -1;
@ -777,15 +775,6 @@ void CL_CheckForResend (void)
return;
}
if (adr.port == 0)
{
adr.port = BigShort (connect_defaultport); //assume a different port for nq
if (!strchr(cls.servername, ':'))
{
Q_strncatz(cls.servername, va(":%u", connect_defaultport), sizeof(cls.servername));
}
}
t2 = Sys_DoubleTime ();
connect_time = realtime+t2-t1; // for retransmit requests
@ -1064,9 +1053,7 @@ void CL_Rcon_f (void)
return;
}
NET_StringToAdr (rcon_address.string, &to);
if (!to.port)
to.port = PORT_QWSERVER;
NET_StringToAdr (rcon_address.string, PORT_QWSERVER, &to);
}
NET_SendPacket (NS_CLIENT, strlen(message)+1, message
@ -1129,10 +1116,10 @@ void CL_ClearState (void)
for (i = 0; i < UPDATE_BACKUP; i++)
{
if (cl.frames[i].packet_entities.entities)
if (cl.inframes[i].packet_entities.entities)
{
Z_Free(cl.frames[i].packet_entities.entities);
cl.frames[i].packet_entities.entities = NULL;
Z_Free(cl.inframes[i].packet_entities.entities);
cl.inframes[i].packet_entities.entities = NULL;
}
}
@ -1325,6 +1312,9 @@ void CL_Disconnect (void)
Cvar_ForceSet(&cl_servername, "none");
CL_ClearState();
//now start up the csqc/menu module again.
CSQC_UnconnectedInit();
}
#undef serverrunning
@ -1627,10 +1617,7 @@ void CL_CheckServerInfo(void)
if (cls.maxfps < 20)
cls.maxfps = 72;
if (!atoi(Info_ValueForKey(cl.serverinfo, "deathmatch")))
cls.gamemode = GAME_COOP;
else
cls.gamemode = GAME_DEATHMATCH;
cls.deathmatch = atoi(Info_ValueForKey(cl.serverinfo, "deathmatch"));
cls.z_ext = atoi(Info_ValueForKey(cl.serverinfo, "*z_ext"));
@ -1926,7 +1913,7 @@ void CL_Packet_f (void)
return;
}
if (!NET_StringToAdr (Cmd_Argv(1), &adr))
if (!NET_StringToAdr (Cmd_Argv(1), PORT_QWSERVER, &adr))
{
Con_Printf ("Bad address: %s\n", Cmd_Argv(1));
return;
@ -2780,7 +2767,7 @@ void CL_ReadPackets (void)
case NQP_ERROR:
break;
case NQP_DATAGRAM://datagram
cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence - 3;
// cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence - 3;
case NQP_RELIABLE://reliable
MSG_ChangePrimitives(cls.netchan.netprim);
CLNQ_ParseServerMessage ();

View File

@ -315,26 +315,28 @@ int packet_latency[NET_TIMINGS];
int CL_CalcNet (void)
{
int a, i;
frame_t *frame;
int lost;
int i;
inframe_t *frame;
int lost = 0;
int percent;
int sent;
int pending;
// char st[80];
sent = NET_TIMINGS;
for (i=cls.netchan.outgoing_sequence-UPDATE_BACKUP+1
; i <= cls.netchan.outgoing_sequence
; i <= (cl_countpendingpl.ival?cls.netchan.outgoing_sequence:cl.parsecount)
; i++)
{
frame = &cl.frames[i&UPDATE_MASK];
if (frame->receivedtime == -1)
frame = &cl.inframes[i&UPDATE_MASK];
if (frame->latency == -1)
{
packet_latency[i&NET_TIMINGSMASK] = 9999; // dropped
else if (frame->receivedtime == -2)
lost++;
}
else if (frame->latency == -2)
packet_latency[i&NET_TIMINGSMASK] = 10000; // choked
else if (frame->receivedtime == -3)
else if (frame->latency == -3)
{
packet_latency[i&NET_TIMINGSMASK] = 9997; // c2spps
sent--;
@ -342,38 +344,13 @@ int CL_CalcNet (void)
else if (frame->invalid)
packet_latency[i&NET_TIMINGSMASK] = 9998; // invalid delta
else
packet_latency[i&NET_TIMINGSMASK] = (frame->receivedtime - frame->senttime)*60;
packet_latency[i&NET_TIMINGSMASK] = frame->latency * 60;
}
lost = 0;
for (a=0 ; a<NET_TIMINGS ; a++)
{
i = (cls.netchan.outgoing_sequence-a) & NET_TIMINGSMASK;
if (packet_latency[i] == 9999)
lost++;
}
if (!cl_countpendingpl.ival)
{
pending = cls.netchan.outgoing_sequence - cls.netchan.incoming_sequence - 1;
lost -= pending;
sent -= pending;
if (sent < 1)
percent = 100;
else
percent = lost * 100 / sent;
if (lost && !percent) //if they have any confirmed lost packets, report at least 1%
percent = 1;
}
if (sent < 1)
percent = 100; //shouldn't ever happen.
else
{
if (sent < 1)
percent = 100; //shouldn't ever happen.
else
percent = lost * 100 / sent;
}
percent = lost * 100 / sent;
return percent;
}
@ -2467,8 +2444,8 @@ void CLQW_ParseServerData (void)
cl.playernum[j] = cl.allocated_client_slots + j;
for (i = 0; i < UPDATE_BACKUP; i++)
{
cl.frames[i].playerstate[cl.playernum[j]].pm_type = PM_SPECTATOR;
cl.frames[i].playerstate[cl.playernum[j]].messagenum = 1;
cl.inframes[i].playerstate[cl.playernum[j]].pm_type = PM_SPECTATOR;
cl.inframes[i].playerstate[cl.playernum[j]].messagenum = 1;
}
}
cl.spectator = true;
@ -2922,7 +2899,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution.
}
//update gamemode
if (gametype == 1)
if (gametype != GAME_COOP)
Info_SetValueForStarKey(cl.serverinfo, "deathmatch", "1", sizeof(cl.serverinfo));
else
Info_SetValueForStarKey(cl.serverinfo, "deathmatch", "0", sizeof(cl.serverinfo));
@ -3923,8 +3900,7 @@ Server information pertaining to this client only, sent every frame
void CL_ParseClientdata (void)
{
int i;
float latency;
frame_t *frame;
inframe_t *frame;
// calculate simulated time of message
oldparsecountmod = parsecountmod;
@ -3938,30 +3914,24 @@ void CL_ParseClientdata (void)
cl.parsecount = i;
i &= UPDATE_MASK;
parsecountmod = i;
if (CPNQ_IS_DP)
i = cls.netchan.incoming_sequence & UPDATE_MASK;
frame = &cl.frames[i];
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
frame->senttime = realtime - host_frametime;
parsecounttime = cl.frames[i].senttime;
frame->receivedtime = realtime;
//(cl.gametimemark - cl.oldgametimemark)*20;
frame = &cl.inframes[i];
// if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
// frame->senttime = realtime - host_frametime;
parsecounttime = cl.outframes[i].senttime;
// calculate latency
latency = frame->receivedtime - frame->senttime;
frame->latency = realtime - parsecounttime;
if (latency < 0 || latency > 1.0)
if (frame->latency < 0 || frame->latency > 1.0)
{
// Con_Printf ("Odd latency: %5.2f\n", latency);
}
else
{
// drift the average latency towards the observed latency
if (latency < cls.latency)
cls.latency = latency;
if (frame->latency < cls.latency)
cls.latency = frame->latency;
else
cls.latency += 0.001; // drift up, so correction are needed
}
@ -4313,7 +4283,7 @@ void CL_MuzzleFlash (int destsplit)
if (i-1 == cl.playernum[destsplit] && cl_muzzleflash.value == 2)
return;
pack = &cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities;
pack = &cl.inframes[cl.validsequence&UPDATE_MASK].packet_entities;
for (pnum=0 ; pnum<pack->num_entities ; pnum++) //try looking for an entity with that id first
{
@ -4331,7 +4301,7 @@ void CL_MuzzleFlash (int destsplit)
{ //that ent number doesn't exist, go for a player with that number
if ((unsigned)(i) <= MAX_CLIENTS && i > 0)
{
pl = &cl.frames[parsecountmod].playerstate[i-1];
pl = &cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[i-1];
dl = CL_AllocDlight (-i);
VectorCopy (pl->origin, dl->origin); //set it's origin
@ -5664,7 +5634,7 @@ void CLQW_ParseServerMessage (void)
case svc_chokecount: // some preceding packets were choked
i = MSG_ReadByte ();
for (j=0 ; j<i ; j++)
cl.frames[ (cls.netchan.incoming_acknowledged-1-j)&UPDATE_MASK ].receivedtime = -2;
cl.inframes[(cls.netchan.incoming_acknowledged-1-j)&UPDATE_MASK].latency = -2;
break;
case svc_modellist:
@ -5685,12 +5655,10 @@ void CLQW_ParseServerMessage (void)
case svc_packetentities:
CLQW_ParsePacketEntities (false);
cl.ackedinputsequence = cl.validsequence;
break;
case svc_deltapacketentities:
CLQW_ParsePacketEntities (true);
cl.ackedinputsequence = cl.validsequence;
break;
case svcfte_updateentities:
CLFTE_ParseEntities();
@ -6313,25 +6281,25 @@ void CLNQ_ParseServerMessage (void)
cl.gametime = MSG_ReadFloat();
cl.gametimemark = realtime;
cl.frames[cl.validsequence&UPDATE_MASK].receivedtime = realtime;
cl.inframes[cl.validsequence&UPDATE_MASK].receivedtime = realtime;
if (CPNQ_IS_DP)
{
int n = cls.netchan.incoming_sequence&UPDATE_MASK, o = (cls.netchan.incoming_sequence-1)&UPDATE_MASK;
cl.frames[n].packet_entities.num_entities = cl.frames[o].packet_entities.num_entities;
if (cl.frames[n].packet_entities.max_entities < cl.frames[o].packet_entities.num_entities)
cl.inframes[n].packet_entities.num_entities = cl.inframes[o].packet_entities.num_entities;
if (cl.inframes[n].packet_entities.max_entities < cl.inframes[o].packet_entities.num_entities)
{
cl.frames[n].packet_entities.max_entities = cl.frames[o].packet_entities.max_entities;
cl.frames[n].packet_entities.entities = BZ_Realloc(cl.frames[n].packet_entities.entities, sizeof(entity_state_t) * cl.frames[n].packet_entities.max_entities);
cl.inframes[n].packet_entities.max_entities = cl.inframes[o].packet_entities.max_entities;
cl.inframes[n].packet_entities.entities = BZ_Realloc(cl.inframes[n].packet_entities.entities, sizeof(entity_state_t) * cl.inframes[n].packet_entities.max_entities);
}
memcpy(cl.frames[n].packet_entities.entities, cl.frames[o].packet_entities.entities, sizeof(entity_state_t) * cl.frames[o].packet_entities.num_entities);
cl.frames[n].packet_entities.servertime = cl.frames[o].packet_entities.servertime;
memcpy(cl.inframes[n].packet_entities.entities, cl.inframes[o].packet_entities.entities, sizeof(entity_state_t) * cl.inframes[o].packet_entities.num_entities);
cl.inframes[n].packet_entities.servertime = cl.inframes[o].packet_entities.servertime;
}
else
{
// cl.frames[(cls.netchan.incoming_sequence-1)&UPDATE_MASK].packet_entities = cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities;
cl.frames[cl.validsequence&UPDATE_MASK].packet_entities.num_entities=0;
cl.frames[cl.validsequence&UPDATE_MASK].packet_entities.servertime = cl.gametime;
// cl.inframes[(cls.netchan.incoming_sequence-1)&UPDATE_MASK].packet_entities = cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities;
cl.inframes[cl.validsequence&UPDATE_MASK].packet_entities.num_entities=0;
cl.inframes[cl.validsequence&UPDATE_MASK].packet_entities.servertime = cl.gametime;
}
break;

View File

@ -282,7 +282,7 @@ void CLQ2_PredictMovement (void) //q2 doesn't support split clients.
while (++ack < current)
{
frame = ack & (UPDATE_MASK);
cmd = (q2usercmd_t*)&cl.frames[frame].cmd[0];
cmd = (q2usercmd_t*)&cl.outframes[frame].cmd[0];
pm.cmd = *cmd;
Q2_Pmove (&pm);
@ -862,7 +862,7 @@ qboolean CL_PredictPlayer(lerpents_t *le, entity_state_t *state, int sequence)
CL_PlayerFrameUpdated(&start, state, sequence);
msec = 500*(realtime - cls.latency + 0.02 - cl.frames[sequence & UPDATE_MASK].receivedtime);
msec = 500*(realtime - cls.latency + 0.02 - cl.inframes[sequence & UPDATE_MASK].receivedtime);
cmd.msec = bound(0, msec, 255);
cmd.forwardmove = state->u.q1.movement[0];
cmd.sidemove = state->u.q1.movement[1];
@ -886,28 +886,56 @@ qboolean CL_PredictPlayer(lerpents_t *le, entity_state_t *state, int sequence)
CL_PredictMove
==============
*/
void CL_PredictMovePNum (int pnum)
void CL_PredictMovePNum (int vnum)
{
frame_t ind;
inframe_t indstate;
outframe_t indcmd;
int i;
float f;
frame_t *from, *to = NULL;
inframe_t *from, *to = NULL;
outframe_t *cmdfrom, *cmdto;
int oldphysent;
vec3_t lrp, lrpv;
double simtime;
extern cvar_t cl_netfps;
//these are to make svc_viewentity work better
float *vel;
float *org;
float stepheight = 0;
float netfps = cl_netfps.value;
if (!netfps)
{
//every video frame has its own input frame.
simtime = realtime;
}
else
{
netfps = bound(6.7, netfps, cls.maxfps);
if (netfps < 30)
{
//extrapolate if we've a low net rate. This should reduce apparent lag, but will be jerky if the net rate is not an (inverse) multiple of the monitor rate.
//this is in addition to any monitor desync.
simtime = realtime;
}
else
{
//interpolate. The input rate is completely smoothed out, at the cost of some latency.
//You can still get juddering if the video rate doesn't match the monitor refresh rate (and isn't so high that it doesn't matter).
//note that the code below will back-date input frames if the server acks too fast.
netfps = bound(6.7, netfps, cls.maxfps);
simtime = realtime - (1/netfps);
}
}
cl.nolocalplayer[pnum] = !!(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS);
cl.nolocalplayer[vnum] = !!(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) || (cls.protocol != CP_QUAKEWORLD);
#ifdef Q2CLIENT
if (cls.protocol == CP_QUAKE2)
{
if (!cl.worldmodel || cl.worldmodel->needload)
return;
cl.crouch[pnum] = 0;
cl.crouch[vnum] = 0;
CLQ2_PredictMovement();
return;
}
@ -916,117 +944,121 @@ void CL_PredictMovePNum (int pnum)
if (cl_pushlatency.value > 0)
Cvar_Set (&cl_pushlatency, "0");
if (cl.paused && !(cls.demoplayback!=DPB_MVD && cls.demoplayback!=DPB_EZTV) && (!cl.spectator || !autocam[pnum]))
if (cl.paused && !(cls.demoplayback!=DPB_MVD && cls.demoplayback!=DPB_EZTV) && (!cl.spectator || !autocam[vnum]))
return;
if (cl.intermission==1 && cls.protocol == CP_QUAKEWORLD)
{
cl.crouch[pnum] = 0;
cl.crouch[vnum] = 0;
return;
}
#ifdef NQPROT
if (cls.protocol == CP_NETQUAKE)
if (cls.protocol == CP_NETQUAKE && !(cls.fteprotocolextensions2 & PEXT2_PREDINFO))
{
cl.ackedinputsequence = cls.netchan.outgoing_sequence;
cl.ackedmovesequence = cl.movesequence;
}
#endif
if (!cl.ackedinputsequence)
if (!cl.validsequence)
{
return;
}
if (cls.netchan.outgoing_sequence - cl.ackedinputsequence >= UPDATE_BACKUP-1)
if (cl.movesequence - cl.ackedmovesequence >= UPDATE_BACKUP-1)
{ //lagging like poo.
if (!cl.intermission) //keep the angles working though.
VectorCopy (cl.playerview[pnum].viewangles, cl.playerview[pnum].simangles);
VectorCopy (cl.playerview[vnum].viewangles, cl.playerview[vnum].simangles);
return;
}
// this is the last frame received from the server
from = &cl.frames[cl.ackedinputsequence & UPDATE_MASK];
from = &cl.inframes[cl.validsequence & UPDATE_MASK];
cmdfrom = &cl.outframes[cl.ackedmovesequence & UPDATE_MASK];
if (!cl.intermission)
{
VectorCopy (cl.playerview[pnum].viewangles, cl.playerview[pnum].simangles);
VectorCopy (cl.playerview[vnum].viewangles, cl.playerview[vnum].simangles);
}
vel = from->playerstate[cl.playernum[pnum]].velocity;
org = from->playerstate[cl.playernum[pnum]].origin;
vel = from->playerstate[cl.playernum[vnum]].velocity;
org = from->playerstate[cl.playernum[vnum]].origin;
#ifdef PEXT_SETVIEW
if (cl.viewentity[pnum])
if (cl.viewentity[vnum] && (cl.viewentity[vnum] != cl.playernum[vnum]+1 || cl.ackedmovesequence == cl.movesequence))
{
if (cl.viewentity[pnum] < cl.maxlerpents)
if (cl.viewentity[vnum] < cl.maxlerpents)
{
cl.nolocalplayer[pnum] = true;
cl.nolocalplayer[vnum] = true;
// Con_Printf("Using lerped pos\n");
org = cl.lerpents[cl.viewentity[pnum]].origin;
org = cl.lerpents[cl.viewentity[vnum]].origin;
vel = vec3_origin;
goto fixedorg;
}
}
#endif
if (!from->playerstate[cl.playernum[pnum]].messagenum)
if (!from->playerstate[cl.playernum[vnum]].messagenum)
{
//no player states?? put the view on an ent
if (cl.playernum[pnum] < cl.maxlerpents)
if (cl.playernum[vnum] < cl.maxlerpents)
{
cl.nolocalplayer[pnum] = true;
cl.nolocalplayer[vnum] = true;
// Con_Printf("Using lerped pos\n");
org = cl.lerpents[cl.playernum[pnum]+1].origin;
org = cl.lerpents[cl.playernum[vnum]+1].origin;
vel = vec3_origin;
goto fixedorg;
}
}
if (((cl_nopred.value && cls.demoplayback!=DPB_MVD && cls.demoplayback != DPB_EZTV)|| cl.playerview[pnum].fixangle || cl.paused))
if (((cl_nopred.value && cls.demoplayback!=DPB_MVD && cls.demoplayback != DPB_EZTV)|| cl.playerview[vnum].fixangle || cl.paused))
{
if (cl_lerp_players.ival && !cls.demoplayback)
{
lerpents_t *le;
if (cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
le = &cl.lerpents[spec_track[pnum]+1];
if (cl.nolocalplayer[vnum])
le = &cl.lerpents[spec_track[vnum]+1];
else
le = &cl.lerpplayers[spec_track[pnum]];
le = &cl.lerpplayers[spec_track[vnum]];
org = le->origin;
vel = vec3_origin;
}
fixedorg:
VectorCopy (vel, cl.playerview[pnum].simvel);
VectorCopy (org, cl.playerview[pnum].simorg);
VectorCopy (vel, cl.playerview[vnum].simvel);
VectorCopy (org, cl.playerview[vnum].simorg);
to = &cl.frames[cl.ackedinputsequence & UPDATE_MASK];
// to = &cl.inframes[cl.ackedinputsequence & UPDATE_MASK];
CL_CatagorizePosition(pnum);
CL_CatagorizePosition(vnum);
goto out;
}
// predict forward until cl.time <= to->senttime
oldphysent = pmove.numphysent;
CL_SetSolidPlayers();
pmove.skipent = cl.playernum[pnum]+1;
pmove.skipent = cl.playernum[vnum]+1;
to = &cl.frames[cl.ackedinputsequence & UPDATE_MASK];
// Con_Printf("%i<%i %i\n", cl.ackedmovesequence, cl.movesequence, cl.validsequence);
if (Cam_TrackNum(pnum)>=0 && CL_MayLerp())
to = &cl.inframes[cl.validsequence & UPDATE_MASK];
cmdto = &cl.outframes[cl.ackedmovesequence & UPDATE_MASK];
if (Cam_TrackNum(vnum)>=0 && CL_MayLerp())
{
float f;
if (cl_lerp_players.ival && (cls.demoplayback==DPB_MVD || cls.demoplayback == DPB_EZTV))
{
lerpents_t *le = &cl.lerpplayers[spec_track[pnum]];
lerpents_t *le = &cl.lerpplayers[spec_track[vnum]];
org = le->origin;
vel = vec3_origin;
VectorCopy(le->angles, cl.playerview[pnum].simangles);
VectorCopy(le->angles, cl.playerview[vnum].simangles);
goto fixedorg;
}
to = &cl.frames[cl.validsequence & UPDATE_MASK];
from = &cl.frames[cl.oldvalidsequence & UPDATE_MASK];
to = &cl.inframes[cl.validsequence & UPDATE_MASK];
from = &cl.inframes[cl.oldvalidsequence & UPDATE_MASK];
//figure out the lerp factor
if (cl.gametime == cl.servertime)
@ -1046,118 +1078,139 @@ fixedorg:
// calculate origin
for (i=0 ; i<3 ; i++)
{
lrp[i] = to->playerstate[spec_track[pnum]].origin[i] +
f * (from->playerstate[spec_track[pnum]].origin[i] - to->playerstate[spec_track[pnum]].origin[i]);
lrp[i] = to->playerstate[spec_track[vnum]].origin[i] +
f * (from->playerstate[spec_track[vnum]].origin[i] - to->playerstate[spec_track[vnum]].origin[i]);
lrpv[i] = to->playerstate[spec_track[pnum]].velocity[i] +
f * (from->playerstate[spec_track[pnum]].velocity[i] - to->playerstate[spec_track[pnum]].velocity[i]);
lrpv[i] = to->playerstate[spec_track[vnum]].velocity[i] +
f * (from->playerstate[spec_track[vnum]].velocity[i] - to->playerstate[spec_track[vnum]].velocity[i]);
cl.playerview[pnum].simangles[i] = LerpAngles16(to->playerstate[spec_track[pnum]].command.angles[i], from->playerstate[spec_track[pnum]].command.angles[i], f)*360.0f/65535;
cl.playerview[vnum].simangles[i] = LerpAngles16(to->playerstate[spec_track[vnum]].command.angles[i], from->playerstate[spec_track[vnum]].command.angles[i], f)*360.0f/65535;
}
org = lrp;
vel = lrpv;
cl.pmovetype[pnum] = PM_NONE;
cl.pmovetype[vnum] = PM_NONE;
goto fixedorg;
}
else
{
if (cls.demoplayback==DPB_MVD || cls.demoplayback==DPB_EZTV)
{
to = &cl.frames[(cls.netchan.outgoing_sequence-1) & UPDATE_MASK];
to = &cl.inframes[(cls.netchan.outgoing_sequence-1) & UPDATE_MASK];
cmdto = &cl.outframes[(cl.movesequence-1) & UPDATE_MASK];
to->playerstate->pm_type = PM_SPECTATOR;
VectorCopy (cl.playerview[pnum].simvel, from->playerstate[cl.playernum[pnum]].velocity);
VectorCopy (cl.playerview[pnum].simorg, from->playerstate[cl.playernum[pnum]].origin);
VectorCopy (cl.playerview[vnum].simvel, from->playerstate[cl.playernum[vnum]].velocity);
VectorCopy (cl.playerview[vnum].simorg, from->playerstate[cl.playernum[vnum]].origin);
CL_PredictUsercmd (pnum, cl.playernum[pnum]+1, &from->playerstate[cl.playernum[pnum]], &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]);
CL_PredictUsercmd (vnum, cl.playernum[vnum]+1, &from->playerstate[cl.playernum[vnum]], &to->playerstate[cl.playernum[vnum]], &cmdto->cmd[vnum]);
}
else
{
for (i=1 ; i<UPDATE_BACKUP-1 && cl.ackedinputsequence+i <
cls.netchan.outgoing_sequence; i++)
for (i=1 ; i<UPDATE_BACKUP-1 && cl.ackedmovesequence+i <
cl.movesequence; i++)
{
to = &cl.frames[(cl.ackedinputsequence+i) & UPDATE_MASK];
CL_PredictUsercmd (pnum, cl.playernum[pnum]+1, &from->playerstate[cl.playernum[pnum]]
, &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]);
to = &cl.inframes[(cl.validsequence+i) & UPDATE_MASK];
cmdto = &cl.outframes[(cl.ackedmovesequence+i) & UPDATE_MASK];
if (to->senttime >= realtime)
CL_PredictUsercmd (vnum, cl.playernum[vnum]+1, &from->playerstate[cl.playernum[vnum]], &to->playerstate[cl.playernum[vnum]], &cmdto->cmd[vnum]);
if (cmdto->senttime >= simtime)
break;
from = to;
cmdfrom = cmdto;
}
}
if (independantphysics[pnum].msec)
if (simtime > cmdto->senttime)
{
float msec;
cmdfrom = cmdto;
from = to;
to = &ind;
to->cmd[pnum] = independantphysics[pnum];
to->senttime = realtime;
CL_PredictUsercmd (pnum, cl.playernum[pnum]+1, &from->playerstate[cl.playernum[pnum]]
, &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]);
}
cl.onground[pnum] = pmove.onground;
cl.pmovetype[pnum] = to->playerstate[cl.playernum[pnum]].pm_type;
stepheight = to->playerstate[cl.playernum[pnum]].origin[2] - from->playerstate[cl.playernum[pnum]].origin[2];
to = &indstate;
cmdto = &indcmd;
if (independantphysics[vnum].msec && !cls.demoplayback)
cmdto->cmd[vnum] = independantphysics[vnum];
else
cmdto->cmd[vnum] = cmdfrom->cmd[vnum];
cmdto->senttime = simtime;
msec = ((cmdto->senttime - cmdfrom->senttime) * 1000) + 0.5;
cmdto->cmd[vnum].msec = bound(0, msec, 250);
if (cl.nolocalplayer[pnum] && cl.maxlerpents > cl.playernum[pnum]+1)
{
//keep the entity tracking the prediction position, so mirrors don't go all weird
VectorCopy(to->playerstate[cl.playernum[pnum]].origin, cl.lerpents[cl.playernum[pnum]+1].origin);
VectorScale(to->cmd[pnum].angles, 360.0f / 0xffff, cl.lerpents[cl.playernum[pnum]+1].angles);
cl.lerpents[cl.playernum[pnum]+1].angles[0] *= -0.333;
CL_PredictUsercmd (vnum, cl.playernum[vnum]+1, &from->playerstate[cl.playernum[vnum]]
, &to->playerstate[cl.playernum[vnum]], &cmdto->cmd[vnum]);
}
cl.onground[vnum] = pmove.onground;
cl.pmovetype[vnum] = to->playerstate[cl.playernum[vnum]].pm_type;
stepheight = to->playerstate[cl.playernum[vnum]].origin[2] - from->playerstate[cl.playernum[vnum]].origin[2];
}
//backdate it if our simulation time is in the past. this will happen on localhost, but not on 300-ping servers.
for (i = 0; cmdfrom->senttime > simtime && i < 16; i++)
{
to = from;
cmdto = cmdfrom;
from = &cl.inframes[(cl.validsequence-i) & UPDATE_MASK];
cmdfrom = &cl.outframes[(cl.ackedmovesequence-i) & UPDATE_MASK];
}
pmove.numphysent = oldphysent;
if (1)//!independantphysics.msec)
// Con_Printf("%f %f %f\n", cmdfrom->senttime, simtime, cmdto->senttime);
if (cmdto->senttime == cmdfrom->senttime)
{
VectorCopy (to->playerstate[cl.playernum[pnum]].velocity, cl.playerview[pnum].simvel);
VectorCopy (to->playerstate[cl.playernum[pnum]].origin, cl.playerview[pnum].simorg);
VectorCopy (to->playerstate[cl.playernum[vnum]].velocity, cl.playerview[vnum].simvel);
VectorCopy (to->playerstate[cl.playernum[vnum]].origin, cl.playerview[vnum].simorg);
}
else
{
int pnum = cl.playernum[vnum];
// now interpolate some fraction of the final frame
if (to->senttime == from->senttime)
f = 0;
else
{
f = (realtime - from->senttime) / (to->senttime - from->senttime);
f = (simtime - cmdfrom->senttime) / (cmdto->senttime - cmdfrom->senttime);
if (f < 0)
f = 0;
if (f > 1)
f = 1;
}
if (f < 0)
f = 0;
if (f > 1)
f = 1;
for (i=0 ; i<3 ; i++)
if ( fabs(org[i] - to->playerstate[cl.playernum[pnum]].origin[i]) > 128)
if ( fabs(from->playerstate[pnum].origin[i] - to->playerstate[pnum].origin[i]) > 128)
{ // teleported, so don't lerp
VectorCopy (to->playerstate[cl.playernum[pnum]].velocity, cl.playerview[pnum].simvel);
VectorCopy (to->playerstate[cl.playernum[pnum]].origin, cl.playerview[pnum].simorg);
VectorCopy (to->playerstate[pnum].velocity, cl.playerview[vnum].simvel);
VectorCopy (to->playerstate[pnum].origin, cl.playerview[vnum].simorg);
goto out;
}
for (i=0 ; i<3 ; i++)
{
cl.playerview[pnum].simorg[i] = org[i]
+ f*(to->playerstate[cl.playernum[pnum]].origin[i] - org[i]);
cl.playerview[pnum].simvel[i] = vel[i]
+ f*(to->playerstate[cl.playernum[pnum]].velocity[i] - vel[i]);
cl.playerview[vnum].simorg[i] = (1-f)*from->playerstate[pnum].origin[i] + f*to->playerstate[pnum].origin[i];
cl.playerview[vnum].simvel[i] = (1-f)*from->playerstate[pnum].velocity[i] + f*to->playerstate[pnum].velocity[i];
if (cl.spectator)
cl.playerview[vnum].simangles[i] = LerpAngles16(from->playerstate[pnum].command.angles[i], to->playerstate[pnum].command.angles[i], f) * (360.0/65535);
else if (cls.demoplayback == DPB_QUAKEWORLD)
cl.playerview[vnum].simangles[i] = LerpAngles16(cmdfrom->cmd[vnum].angles[i], cmdto->cmd[vnum].angles[i], f) * (360.0/65535);
}
CL_CatagorizePosition(pnum);
CL_CatagorizePosition(vnum);
}
if (cl.nolocalplayer[vnum] && cl.maxlerpents > cl.playernum[vnum]+1)
{
//keep the entity tracking the prediction position, so mirrors don't go all weird
VectorCopy(to->playerstate[cl.playernum[vnum]].origin, cl.lerpents[cl.playernum[vnum]+1].origin);
VectorScale(cmdto->cmd[vnum].angles, 360.0f / 0xffff, cl.lerpents[cl.playernum[vnum]+1].angles);
cl.lerpents[cl.playernum[vnum]+1].angles[0] *= -0.333;
}
if (cls.demoplayback)
CL_LerpMove (pnum, to->senttime);
CL_LerpMove (vnum, cmdto->senttime);
out:
CL_CalcCrouch (pnum, stepheight);
cl.waterlevel[pnum] = pmove.waterlevel;
VectorCopy(pmove.gravitydir, cl.playerview[pnum].gravitydir);
CL_CalcCrouch (vnum, stepheight);
cl.waterlevel[vnum] = pmove.waterlevel;
VectorCopy(pmove.gravitydir, cl.playerview[vnum].gravitydir);
}
void CL_PredictMove (void)

View File

@ -1360,7 +1360,7 @@ void SCR_DrawUPS (void)
else
track = -1;
if (track != -1)
vel = cl.frames[cl.validsequence&UPDATE_MASK].playerstate[track].velocity;
vel = cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[track].velocity;
else
vel = cl.playerview[0].simvel;
lastups = sqrt((vel[0]*vel[0]) + (vel[1]*vel[1]));
@ -1770,7 +1770,7 @@ void SCR_SetUpToDrawConsole (void)
key_dest = key_console;
scr_conlines = scr_con_current = vid.height * fullscreenpercent;
}
else if ((key_dest == key_console || key_dest == key_game) && SCR_GetLoadingStage() == LS_NONE && cls.state < ca_active && !Media_PlayingFullScreen())
else if ((key_dest == key_console || key_dest == key_game) && SCR_GetLoadingStage() == LS_NONE && cls.state < ca_active && !Media_PlayingFullScreen() && !CSQC_UnconnectedOkay(false))
{
if (cls.state < ca_demostart)
key_dest = key_console;

View File

@ -3075,7 +3075,7 @@ void CL_UpdateBeams (void)
// VectorSubtract(cl.simorg, b->start, org);
// VectorAdd(b->end, org, b->end); //move the end point by simorg-start
pl = &cl.frames[cl.parsecount&UPDATE_MASK].playerstate[b->entity-1];
pl = &cl.inframes[cl.parsecount&UPDATE_MASK].playerstate[b->entity-1];
if (pl->messagenum == cl.parsecount || cls.protocol == CP_NETQUAKE)
{
vec3_t fwd, org, ang;
@ -3091,7 +3091,7 @@ void CL_UpdateBeams (void)
if (cl_truelightning.ival >= 2 && cls.netchan.outgoing_sequence > cl_truelightning.ival)
{
frame_t *frame = &cl.frames[(cls.netchan.outgoing_sequence-cl_truelightning.ival)&UPDATE_MASK];
inframe_t *frame = &cl.inframes[(cls.netchan.outgoing_sequence-cl_truelightning.ival)&UPDATE_MASK];
viewang = frame->playerstate[cl.playernum[j]].viewangles;
viewang[0] = (frame->playerstate[cl.playernum[j]].command.angles[0] * 360) / 65336.0;
viewang[1] = (frame->playerstate[cl.playernum[j]].command.angles[1] * 360) / 65336.0;
@ -3154,7 +3154,7 @@ void CL_UpdateBeams (void)
}
else if (b->entity <= cl.allocated_client_slots && b->entity > 0)
{
pl = &cl.frames[cl.parsecount&UPDATE_MASK].playerstate[b->entity-1];
pl = &cl.inframes[cl.parsecount&UPDATE_MASK].playerstate[b->entity-1];
VectorCopy(pl->origin, b->start);
b->start[2]+=16;
}

View File

@ -773,7 +773,7 @@ static qintptr_t UI_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
if (ui_pings[i].type == NA_INVALID)
{
serverinfo_t *info;
NET_StringToAdr(cmdtext + 5, &ui_pings[i]);
NET_StringToAdr(cmdtext + 5, 0, &ui_pings[i]);
info = Master_InfoForServer(ui_pings[i]);
if (info)
{

View File

@ -187,23 +187,30 @@ typedef struct player_info_s
typedef struct
{
double senttime; // time cmd was sent off
// generated on client side
usercmd_t cmd[MAX_SPLITS]; // cmd that generated the frame
double senttime; // time cmd was sent off
int delta_sequence; // sequence number to delta from, -1 = full update
usercmd_t cmd[MAX_SPLITS]; // cmd that generated the frame
int cmd_sequence;
int server_message_num;
int server_time;
int client_time;
} outframe_t;
typedef struct
{
//this is the sequence we requested for this frame.
int delta_sequence; // sequence number to delta from, -1 = full update
float latency;
// received from server
double receivedtime; // time message was received, or -1
player_state_t playerstate[MAX_CLIENTS+MAX_SPLITS]; // message received that reflects performing
// the usercmd
// the usercmd
packet_entities_t packet_entities;
qboolean invalid; // true if the packet_entities delta was invalid
int server_time;
int client_time;
int server_message_num;
} frame_t;
} inframe_t;
#ifdef Q2CLIENT
typedef struct
@ -427,7 +434,7 @@ typedef struct
qboolean allow_cheats;
qboolean allow_semicheats; //defaults to true, but this allows a server to enforce a strict ruleset (smackdown type rules).
float maxfps; //server capped
enum {GAME_DEATHMATCH, GAME_COOP} gamemode;
int deathmatch;
#ifdef NQPROT
int signon;
@ -510,14 +517,11 @@ typedef struct
int parsecount; // server message counter
int oldparsecount;
int oldvalidsequence;
int ackedinputsequence; //in quakeworld/q2 this is always equal to validsequence. dp can differ.
int ackedmovesequence; //in quakeworld/q2 this is always equal to validsequence. nq can differ. may only be updated when validsequence is updated.
int validsequence; // this is the sequence number of the last good
// packetentity_t we got. If this is 0, we can't
// render a frame yet
int movemessages; // since connecting to this server
// throw out the first couple, so the player
// doesn't accidentally do something the
// first frame
int movesequence; //
int spectator;
@ -534,7 +538,8 @@ typedef struct
#endif
// sentcmds[cl.netchan.outgoing_sequence & UPDATE_MASK] = cmd
frame_t frames[UPDATE_BACKUP];
outframe_t outframes[UPDATE_BACKUP]; //user inputs (cl.ackedmovesequence+1 to cl.movesequence are still pending)
inframe_t inframes[UPDATE_BACKUP]; //server state (cl.validsequence is the most recent set)
lerpents_t *lerpents;
int maxlerpents; //number of slots allocated.
int lerpentssequence;
@ -1089,6 +1094,8 @@ char *CG_GetConfigString(int num);
#ifdef CSQC_DAT
qboolean CSQC_Inited(void);
void CSQC_RendererRestarted(void);
qboolean CSQC_UnconnectedOkay(qboolean inprinciple);
qboolean CSQC_UnconnectedInit(void);
qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checksum);
qboolean CSQC_ConsoleLink(char *text, char *info);
void CSQC_RegisterCvarsAndThings(void);
@ -1222,6 +1229,7 @@ void Skin_FlushSkin(char *name);
void Skin_AllSkins_f (void);
void Skin_NextDownload (void);
void Skin_FlushPlayers(void);
void Skin_FlushAll(void);
#define RSSHOT_WIDTH 320
#define RSSHOT_HEIGHT 200

View File

@ -1015,11 +1015,10 @@ void CLQ2_ParseFrame (void)
i = MSG_ReadByte ();
for (j=0 ; j<i ; j++)
cl.frames[ (cls.netchan.incoming_acknowledged-1-j)&UPDATE_MASK ].receivedtime = -2;
cl.inframes[ (cls.netchan.incoming_acknowledged-1-j)&UPDATE_MASK ].receivedtime = -2;
if (cl_shownet.value == 3)
Con_Printf (" frame:%i delta:%i\n", cl.q2frame.serverframe,
cl.q2frame.deltaframe);
Con_Printf (" frame:%i delta:%i\n", cl.q2frame.serverframe, cl.q2frame.deltaframe);
// If the frame is delta compressed from data that we
// no longer have available, we must suck up the rest of

View File

@ -255,7 +255,7 @@ void CLQ3_ParseSnapshot(void)
int delta;
int len;
int i;
frame_t *frame;
outframe_t *frame;
// usercmd_t *ucmd;
// int commandTime;
@ -329,7 +329,7 @@ void CLQ3_ParseSnapshot(void)
snap.ping = 3;
for (i=cls.netchan.outgoing_sequence-1 ; i>cls.netchan.outgoing_sequence-Q3UPDATE_BACKUP ; i--)
{
frame = &cl.frames[i & Q3UPDATE_MASK];
frame = &cl.outframes[i & Q3UPDATE_MASK];
if (frame->server_message_num == snap.deltaFrame)
{
snap.ping = Sys_Milliseconds() - frame->client_time;
@ -873,7 +873,7 @@ void CLQ3_SendCmd(usercmd_t *cmd)
int i;
char data[MAX_OVERALLMSGLEN];
sizebuf_t msg;
frame_t *frame, *oldframe;
outframe_t *frame, *oldframe;
int cmdcount, key;
usercmd_t *to, *from;
extern int keycatcher;
@ -905,12 +905,12 @@ void CLQ3_SendCmd(usercmd_t *cmd)
if (key_dest != key_game || (keycatcher&3))
cmd->buttons |= 2; //add in the 'at console' button
cl.frames[ccs.currentUserCmdNumber&CMD_MASK].cmd[0] = *cmd;
cl.outframes[ccs.currentUserCmdNumber&CMD_MASK].cmd[0] = *cmd;
ccs.currentUserCmdNumber++;
frame = &cl.frames[cls.netchan.outgoing_sequence & Q3UPDATE_MASK];
frame = &cl.outframes[cls.netchan.outgoing_sequence & Q3UPDATE_MASK];
frame->cmd_sequence = ccs.currentUserCmdNumber;
frame->server_message_num = ccs.serverMessageNum;
frame->server_time = cl.gametime;
@ -938,7 +938,7 @@ void CLQ3_SendCmd(usercmd_t *cmd)
}
i = (cls.netchan.outgoing_sequence - 1);
oldframe = &cl.frames[i & Q3UPDATE_MASK];
oldframe = &cl.outframes[i & Q3UPDATE_MASK];
cmdcount = ccs.currentUserCmdNumber - oldframe->cmd_sequence;
if (cmdcount > Q3UPDATE_MASK)
cmdcount = Q3UPDATE_MASK;
@ -964,7 +964,7 @@ void CLQ3_SendCmd(usercmd_t *cmd)
from = &nullcmd;
for (i = oldframe->cmd_sequence; i < ccs.currentUserCmdNumber; i++)
{
to = &cl.frames[i&CMD_MASK].cmd[0];
to = &cl.outframes[i&CMD_MASK].cmd[0];
MSG_Q3_WriteDeltaUsercmd( &msg, key, from, to );
from = to;
}
@ -992,7 +992,7 @@ void CLQ3_SendAuthPacket(netadr_t gameserver)
if (*key)
{
Con_Printf("Resolving %s\n", Q3_AUTHORIZE_SERVER_NAME);
if (NET_StringToAdr(Q3_AUTHORIZE_SERVER_NAME, &authaddr))
if (NET_StringToAdr(Q3_AUTHORIZE_SERVER_NAME, 0, &authaddr))
{
msg.data = data;
msg.cursize = 0;

View File

@ -1981,8 +1981,8 @@ void INS_JoyMove (float *movements, int pnum)
static qbyte scantokey[128] =
{
// 0 1 2 3 4 5 6 7
// 8 9 A B C D E F
// 0 1 2 3 4 5 6 7
// 8 9 A B C D E F
0 , 27, '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
@ -1995,7 +1995,7 @@ static qbyte scantokey[128] =
K_UPARROW, K_PGUP, '-', K_LEFTARROW,'5', K_RIGHTARROW,'+', K_END, // 4
K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, 0, K_F11,
K_F12, 0, 0, 0, 0, 0, 0, 0, // 5
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, '\\', 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, // 6
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 // 7

View File

@ -28,7 +28,7 @@ void Draw_TextBox (int x, int y, int width, int lines)
if (!p) //assume none exist
{
R2D_ImageColours(0.0, 0.0, 0.0, 1.0);
R2D_FillBlock(x, y, width + 16, 8 * (2 + lines));
R2D_FillBlock(x, y, width*16 + 16, 8 * (2 + lines));
R2D_ImageColours(1.0, 1.0, 1.0, 1.0);
return;
}
@ -1862,6 +1862,11 @@ void M_Menu_Main_f (void)
int mgt;
#ifdef CSQC_DAT
if (CSQC_ConsoleCommand(va("%s %s", Cmd_Argv(0), Cmd_Args)))
return;
#endif
SCR_EndLoadingPlaque(); //just in case...
/*
@ -1920,7 +1925,7 @@ void M_Menu_Main_f (void)
b->common.tooltip = "Singleplayer.";
mainm->selecteditem = (menuoption_t *)b;
b->common.width = 12*20;
b->common.height = 20;
b->common.height = 32;
#endif
b = MC_AddConsoleCommand (mainm, 68, 53, "", "menu_multi\n");
b->common.tooltip = "Multiplayer.";
@ -1928,19 +1933,19 @@ void M_Menu_Main_f (void)
mainm->selecteditem = (menuoption_t *)b;
#endif
b->common.width = 12*20;
b->common.height = 20;
b->common.height = 32;
b = MC_AddConsoleCommand (mainm, 68, 93, "", "menu_options\n");
b->common.tooltip = "Options.";
b->common.width = 12*20;
b->common.height = 20;
b->common.height = 32;
b = MC_AddConsoleCommand (mainm, 68, 133, "", "menu_video\n");
b->common.tooltip = "Video Options.";
b->common.width = 12*20;
b->common.height = 20;
b->common.height = 32;
b = MC_AddConsoleCommand (mainm, 68, 173, "", "menu_quit\n");
b->common.tooltip = "Quit to DOS.";
b->common.width = 12*20;
b->common.height = 20;
b->common.height = 32;
mainm->cursoritem = (menuoption_t *)MC_AddCursor(mainm, 42, mainm->selecteditem->common.posy);
}

View File

@ -57,7 +57,7 @@ void M_BuildTranslationTable(int top, int bottom, qbyte *translationTable)
qbyte *dest, *source;
qbyte identityTable[256];
int pc = Cvar_Get("cl_playerclass", "1", 0, "foo")->value;
int pc = Cvar_Get("cl_playerclass", "1", 0, "Hexen2")->value;
if (h2playertranslations && pc)
{
int i;
@ -196,6 +196,10 @@ void M_ToggleMenu_f (void)
return;
}
#ifdef CSQC_DAT
if (CSQC_ConsoleCommand("togglemenu"))
return;
#endif
#ifdef MENU_DAT
if (MP_Toggle())
return;
@ -1027,6 +1031,8 @@ void M_Reinit(void)
#endif
{
M_Init_Internal();
CSQC_UnconnectedInit();
}
}

View File

@ -597,7 +597,7 @@ void Master_AddMaster (char *address, int type, char *description)
netadr_t adr;
master_t *mast;
if (!NET_StringToAdr(address, &adr))
if (!NET_StringToAdr(address, 0, &adr))
{
Con_Printf("Failed to resolve address \"%s\"\n", address);
return;
@ -805,7 +805,7 @@ qboolean Master_LoadMasterList (char *filename, int defaulttype, int depth)
Master_LoadMasterList(file, servertype, depth);
else if (servertype < 0)
{
if (NET_StringToAdr(line, &net_from))
if (NET_StringToAdr(line, 0, &net_from))
CL_ReadServerInfo(va("\\hostname\\%s", name), -servertype, true);
else
Con_Printf("Failed to resolve address - \"%s\"\n", line);
@ -1160,7 +1160,7 @@ void MasterInfo_ProcessHTTP(vfsfile_t *file, int type)
if (*s == '#') //hash is a comment, apparently.
continue;
if (!NET_StringToAdr(s, &adr))
if (!NET_StringToAdr(s, 80, &adr))
continue;
if ((info = Master_InfoForServer(adr))) //remove if the server already exists.
@ -1228,7 +1228,7 @@ char *jsonnode(int level, char *node)
if (level == 1)
{
if (!strcmp(key, "IPAddress"))
NET_StringToAdr(com_token, &adr);
NET_StringToAdr(com_token, 0, &adr);
if (!strcmp(key, "Port"))
port = atoi(com_token);
if (!strcmp(key, "DNS"))

File diff suppressed because it is too large Load Diff

View File

@ -8,17 +8,7 @@
#endif
#if defined(MENU_DAT) || defined(CSQC_DAT)
struct
{
float *drawfont;
float *drawfontscale;
} mp_globs;
#include "cl_master.h"
//float drawfill(vector position, vector size, vector rgb, float alpha, float flag) = #457;
void QCBUILTIN PF_CL_drawfill (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -91,30 +81,15 @@ void PR_CL_BeginString(pubprogfuncs_t *prinst, float vx, float vy, float szx, fl
int fontidx = 0; //default by default...
world_t *world = prinst->parms->user;
struct font_s *font = font_conchar;
if (!world)
if (world->g.drawfontscale)
{
//menu progs.
if (mp_globs.drawfontscale)
{
szx *= mp_globs.drawfontscale[0];
szy *= mp_globs.drawfontscale[1];
}
if (mp_globs.drawfont)
{
fontidx = *mp_globs.drawfont;
}
szx *= world->g.drawfontscale[0];
szy *= world->g.drawfontscale[1];
}
else
if (world->g.drawfont)
{
if (world->g.drawfontscale)
{
szx *= world->g.drawfontscale[0];
szy *= world->g.drawfontscale[1];
}
if (world->g.drawfont)
{
fontidx = *world->g.drawfont;
}
fontidx = *world->g.drawfont;
}
if (fontidx >= 0 && fontidx < FONT_SLOTS)
@ -905,164 +880,6 @@ static void QCBUILTIN PF_CopyEntity (pubprogfuncs_t *prinst, struct globalvars_s
memcpy(out->fields, in->fields, menuentsize);
}
#ifdef CL_MASTER
#include "cl_master.h"
void QCBUILTIN PF_M_gethostcachevalue (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
hostcacheglobal_t hcg = G_FLOAT(OFS_PARM0);
G_FLOAT(OFS_RETURN) = 0;
switch(hcg)
{
case SLIST_HOSTCACHEVIEWCOUNT:
CL_QueryServers();
Master_CheckPollSockets();
G_FLOAT(OFS_RETURN) = Master_NumSorted();
return;
case SLIST_HOSTCACHETOTALCOUNT:
CL_QueryServers();
Master_CheckPollSockets();
G_FLOAT(OFS_RETURN) = Master_TotalCount();
return;
case SLIST_MASTERQUERYCOUNT:
case SLIST_MASTERREPLYCOUNT:
case SLIST_SERVERQUERYCOUNT:
case SLIST_SERVERREPLYCOUNT:
G_FLOAT(OFS_RETURN) = 0;
return;
case SLIST_SORTFIELD:
G_FLOAT(OFS_RETURN) = Master_GetSortField();
return;
case SLIST_SORTDESCENDING:
G_FLOAT(OFS_RETURN) = Master_GetSortDescending();
return;
default:
return;
}
}
//void resethostcachemasks(void) = #615;
void QCBUILTIN PF_M_resethostcachemasks(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
Master_ClearMasks();
}
//void sethostcachemaskstring(float mask, float fld, string str, float op) = #616;
void QCBUILTIN PF_M_sethostcachemaskstring(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int mask = G_FLOAT(OFS_PARM0);
int field = G_FLOAT(OFS_PARM1);
char *str = PR_GetStringOfs(prinst, OFS_PARM2);
int op = G_FLOAT(OFS_PARM3);
Master_SetMaskString(mask, field, str, op);
}
//void sethostcachemasknumber(float mask, float fld, float num, float op) = #617;
void QCBUILTIN PF_M_sethostcachemasknumber(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int mask = G_FLOAT(OFS_PARM0);
int field = G_FLOAT(OFS_PARM1);
int str = G_FLOAT(OFS_PARM2);
int op = G_FLOAT(OFS_PARM3);
Master_SetMaskInteger(mask, field, str, op);
}
//void resorthostcache(void) = #618;
void QCBUILTIN PF_M_resorthostcache(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
Master_SortServers();
}
//void sethostcachesort(float fld, float descending) = #619;
void QCBUILTIN PF_M_sethostcachesort(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
Master_SetSortField(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
}
//void refreshhostcache(void) = #620;
void QCBUILTIN PF_M_refreshhostcache(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
MasterInfo_Refresh();
}
//float gethostcachenumber(float fld, float hostnr) = #621;
void QCBUILTIN PF_M_gethostcachenumber(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float ret = 0;
int keynum = G_FLOAT(OFS_PARM0);
int svnum = G_FLOAT(OFS_PARM1);
serverinfo_t *sv;
sv = Master_SortedServer(svnum);
ret = Master_ReadKeyFloat(sv, keynum);
G_FLOAT(OFS_RETURN) = ret;
}
void QCBUILTIN PF_M_gethostcachestring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *ret;
int keynum = G_FLOAT(OFS_PARM0);
int svnum = G_FLOAT(OFS_PARM1);
serverinfo_t *sv;
sv = Master_SortedServer(svnum);
ret = Master_ReadKeyString(sv, keynum);
RETURN_TSTRING(ret);
}
//float gethostcacheindexforkey(string key) = #622;
void QCBUILTIN PF_M_gethostcacheindexforkey(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *keyname = PR_GetStringOfs(prinst, OFS_PARM0);
G_FLOAT(OFS_RETURN) = Master_KeyForName(keyname);
}
//void addwantedhostcachekey(string key) = #623;
void QCBUILTIN PF_M_addwantedhostcachekey(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
PF_M_gethostcacheindexforkey(prinst, pr_globals);
}
void QCBUILTIN PF_M_getextresponse(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
//this does something weird
G_INT(OFS_RETURN) = 0;
}
void QCBUILTIN PF_netaddress_resolve(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *address = PR_GetStringOfs(prinst, OFS_PARM0);
netadr_t adr;
char result[256];
if (NET_StringToAdr(address, &adr))
RETURN_TSTRING(NET_AdrToString (result, sizeof(result), adr));
else
RETURN_TSTRING("");
}
#else
void PF_gethostcachevalue (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals){G_FLOAT(OFS_RETURN) = 0;}
void PF_gethostcachestring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) {G_INT(OFS_RETURN) = 0;}
//void resethostcachemasks(void) = #615;
void PF_M_resethostcachemasks(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals){}
//void sethostcachemaskstring(float mask, float fld, string str, float op) = #616;
void PF_M_sethostcachemaskstring(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals){}
//void sethostcachemasknumber(float mask, float fld, float num, float op) = #617;
void PF_M_sethostcachemasknumber(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals){}
//void resorthostcache(void) = #618;
void PF_M_resorthostcache(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals){}
//void sethostcachesort(float fld, float descending) = #619;
void PF_M_sethostcachesort(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals){}
//void refreshhostcache(void) = #620;
void PF_M_refreshhostcache(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) {}
//float gethostcachenumber(float fld, float hostnr) = #621;
void PF_M_gethostcachenumber(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals){G_FLOAT(OFS_RETURN) = 0;}
//float gethostcacheindexforkey(string key) = #622;
void PF_M_gethostcacheindexforkey(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals){G_FLOAT(OFS_RETURN) = 0;}
//void addwantedhostcachekey(string key) = #623;
void PF_M_addwantedhostcachekey(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals){}
#endif
void QCBUILTIN PF_localsound (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *soundname = PR_GetStringOfs(prinst, OFS_PARM0);
@ -1491,6 +1308,11 @@ static struct {
//gap
{"shaderforname", PF_shaderforname, 238},
//gap
{"print", PF_print, 339},
{"keynumtostring", PF_cl_keynumtostring, 340},
{"stringtokeynum", PF_cl_stringtokeynum, 341},
{"getkeybind", PF_cl_getkeybind, 342},
//gap
{"isdemo", PF_isdemo, 349},
//gap
{"findfont", PF_CL_findfont, 356},
@ -1585,33 +1407,29 @@ static struct {
{"getresolution", PF_cl_getresolution, 608},
{"keynumtostring", PF_cl_keynumtostring, 609},
{"findkeysforcommand", PF_cl_findkeysforcommand, 610},
#ifdef CL_MASTER
{"gethostcachevalue", PF_M_gethostcachevalue, 611},
{"gethostcachestring", PF_M_gethostcachestring, 612},
#endif
{"gethostcachevalue", PF_cl_gethostcachevalue, 611},
{"gethostcachestring", PF_cl_gethostcachestring, 612},
{"parseentitydata", PF_parseentitydata, 613},
{"stringtokeynum", PF_cl_stringtokeynum, 614},
{"resethostcachemasks", PF_M_resethostcachemasks, 615},
{"sethostcachemaskstring", PF_M_sethostcachemaskstring,616},
{"sethostcachemasknumber", PF_M_sethostcachemasknumber,617},
{"resorthostcache", PF_M_resorthostcache, 618},
{"sethostcachesort", PF_M_sethostcachesort, 619},
{"refreshhostcache", PF_M_refreshhostcache, 620},
{"gethostcachenumber", PF_M_gethostcachenumber, 621},
{"gethostcacheindexforkey", PF_M_gethostcacheindexforkey,622},
{"addwantedhostcachekey", PF_M_addwantedhostcachekey, 623},
#ifdef CL_MASTER
{"getextresponse", PF_M_getextresponse, 624},
{"resethostcachemasks", PF_cl_resethostcachemasks, 615},
{"sethostcachemaskstring", PF_cl_sethostcachemaskstring,616},
{"sethostcachemasknumber", PF_cl_sethostcachemasknumber,617},
{"resorthostcache", PF_cl_resorthostcache, 618},
{"sethostcachesort", PF_cl_sethostcachesort, 619},
{"refreshhostcache", PF_cl_refreshhostcache, 620},
{"gethostcachenumber", PF_cl_gethostcachenumber, 621},
{"gethostcacheindexforkey", PF_cl_gethostcacheindexforkey,622},
{"addwantedhostcachekey", PF_cl_addwantedhostcachekey,623},
{"getextresponse", PF_cl_getextresponse, 624},
{"netaddress_resolve", PF_netaddress_resolve, 625},
#endif
//gap
{"sprintf", PF_sprintf, 627},
//gap
{"setkeybind", PF_Fixme, 630},
{"getbindmaps", PF_Fixme, 631},
{"setbindmaps", PF_Fixme, 632},
{"getbindmaps", PF_cl_GetBindMap, 631},
{"setbindmaps", PF_cl_SetBindMap, 632},
{"crypto_getkeyfp", PF_crypto_getkeyfp, 633},
{"crypto_getidfp", PF_crypto_getidfp, 634},
{"crypto_getencryptlevel", PF_crypto_getencryptlevel, 635},
@ -1659,10 +1477,10 @@ void M_Init_Internal (void);
void M_DeInit_Internal (void);
int inmenuprogs;
pubprogfuncs_t *menuprogs;
progparms_t menuprogparms;
menuedict_t *menu_edicts;
int num_menu_edicts;
world_t menu_world;
func_t mp_init_function;
func_t mp_shutdown_function;
@ -1680,7 +1498,7 @@ void MP_Shutdown (void)
{
extern int mouseusedforgui;
func_t temp;
if (!menuprogs)
if (!menu_world.progs)
return;
/*
{
@ -1695,11 +1513,11 @@ void MP_Shutdown (void)
temp = mp_shutdown_function;
mp_shutdown_function = 0;
if (temp && !inmenuprogs)
PR_ExecuteProgram(menuprogs, temp);
PR_ExecuteProgram(menu_world.progs, temp);
PR_Common_Shutdown(menuprogs, false);
menuprogs->CloseProgs(menuprogs);
menuprogs = NULL;
PR_Common_Shutdown(menu_world.progs, false);
menu_world.progs->CloseProgs(menu_world.progs);
memset(&menu_world, 0, sizeof(menu_world));
PR_ResetFonts(true);
#ifdef CL_MASTER
@ -1732,7 +1550,7 @@ void VARGS Menu_Abort (char *format, ...)
char *buffer;
int size = 1024*1024*8;
buffer = Z_Malloc(size);
menuprogs->save_ents(menuprogs, buffer, &size, 3);
menu_world.progs->save_ents(menu_world.progs, buffer, &size, 3);
COM_WriteFile("menucore.txt", buffer, size);
Z_Free(buffer);
}
@ -1749,9 +1567,9 @@ void VARGS Menu_Abort (char *format, ...)
void MP_CvarChanged(cvar_t *var)
{
if (menuprogs)
if (menu_world.progs)
{
PR_AutoCvar(menuprogs, var);
PR_AutoCvar(menu_world.progs, var);
}
}
@ -1809,17 +1627,18 @@ qboolean MP_Init (void)
menuprogparms.useeditor = NULL;//sorry... QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms);
menuprogparms.useeditor = QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms);
menuprogparms.user = &menu_world;
menutime = Sys_DoubleTime();
if (!menuprogs)
if (!menu_world.progs)
{
Con_DPrintf("Initializing menu.dat\n");
menuprogs = InitProgs(&menuprogparms);
PR_Configure(menuprogs, 64*1024*1024, 1);
if (PR_LoadProgs(menuprogs, "menu.dat", 10020, NULL, 0) < 0) //no per-progs builtins.
menu_world.progs = InitProgs(&menuprogparms);
PR_Configure(menu_world.progs, 64*1024*1024, 1);
if (PR_LoadProgs(menu_world.progs, "menu.dat", 10020, NULL, 0) < 0) //no per-progs builtins.
{
//failed to load or something
// CloseProgs(menuprogs);
// CloseProgs(menu_world.progs);
// menuprogs = NULL;
return false;
}
@ -1831,33 +1650,33 @@ qboolean MP_Init (void)
}
inmenuprogs++;
PF_InitTempStrings(menuprogs);
PF_InitTempStrings(menu_world.progs);
mp_time = (float*)PR_FindGlobal(menuprogs, "time", 0, NULL);
mp_time = (float*)PR_FindGlobal(menu_world.progs, "time", 0, NULL);
if (mp_time)
*mp_time = Sys_DoubleTime();
mp_globs.drawfont = (float*)PR_FindGlobal(menuprogs, "drawfont", 0, NULL);
mp_globs.drawfontscale = (float*)PR_FindGlobal(menuprogs, "drawfontscale", 0, NULL);
menu_world.g.drawfont = (float*)PR_FindGlobal(menu_world.progs, "drawfont", 0, NULL);
menu_world.g.drawfontscale = (float*)PR_FindGlobal(menu_world.progs, "drawfontscale", 0, NULL);
PR_AutoCvarSetup(menuprogs);
PR_AutoCvarSetup(menu_world.progs);
menuentsize = PR_InitEnts(menuprogs, 8192);
menuentsize = PR_InitEnts(menu_world.progs, 8192);
//'world' edict
// EDICT_NUM(menuprogs, 0)->readonly = true;
EDICT_NUM(menuprogs, 0)->isfree = false;
// EDICT_NUM(menu_world.progs, 0)->readonly = true;
EDICT_NUM(menu_world.progs, 0)->isfree = false;
mp_init_function = PR_FindFunction(menuprogs, "m_init", PR_ANY);
mp_shutdown_function = PR_FindFunction(menuprogs, "m_shutdown", PR_ANY);
mp_draw_function = PR_FindFunction(menuprogs, "m_draw", PR_ANY);
mp_keydown_function = PR_FindFunction(menuprogs, "m_keydown", PR_ANY);
mp_keyup_function = PR_FindFunction(menuprogs, "m_keyup", PR_ANY);
mp_toggle_function = PR_FindFunction(menuprogs, "m_toggle", PR_ANY);
mp_init_function = PR_FindFunction(menu_world.progs, "m_init", PR_ANY);
mp_shutdown_function = PR_FindFunction(menu_world.progs, "m_shutdown", PR_ANY);
mp_draw_function = PR_FindFunction(menu_world.progs, "m_draw", PR_ANY);
mp_keydown_function = PR_FindFunction(menu_world.progs, "m_keydown", PR_ANY);
mp_keyup_function = PR_FindFunction(menu_world.progs, "m_keyup", PR_ANY);
mp_toggle_function = PR_FindFunction(menu_world.progs, "m_toggle", PR_ANY);
if (mp_init_function)
PR_ExecuteProgram(menuprogs, mp_init_function);
PR_ExecuteProgram(menu_world.progs, mp_init_function);
inmenuprogs--;
Con_DPrintf("Initialized menu.dat\n");
@ -1870,20 +1689,20 @@ static void MP_GameCommand_f(void)
{
void *pr_globals;
func_t gamecommand;
if (!menuprogs)
if (!menu_world.progs)
return;
gamecommand = PR_FindFunction(menuprogs, "GameCommand", PR_ANY);
gamecommand = PR_FindFunction(menu_world.progs, "GameCommand", PR_ANY);
if (!gamecommand)
return;
pr_globals = PR_globals(menuprogs, PR_CURRENT);
(((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(menuprogs, Cmd_Args()));
PR_ExecuteProgram (menuprogs, gamecommand);
pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
(((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(menu_world.progs, Cmd_Args()));
PR_ExecuteProgram (menu_world.progs, gamecommand);
}
void MP_CoreDump_f(void)
{
if (!menuprogs)
if (!menu_world.progs)
{
Con_Printf("Can't core dump, you need to be running the CSQC progs first.");
return;
@ -1892,7 +1711,7 @@ void MP_CoreDump_f(void)
{
int size = 1024*1024*8;
char *buffer = BZ_Malloc(size);
menuprogs->save_ents(menuprogs, buffer, &size, 3);
menu_world.progs->save_ents(menu_world.progs, buffer, &size, 3);
COM_WriteFile("menucore.txt", buffer, size);
BZ_Free(buffer);
}
@ -1911,13 +1730,13 @@ void MP_Breakpoint_f(void)
char *filename = Cmd_Argv(1);
int line = atoi(Cmd_Argv(2));
if (!menuprogs)
if (!menu_world.progs)
{
Con_Printf("Menu not running\n");
return;
}
wasset = menuprogs->ToggleBreak(menuprogs, filename, line, 3);
isset = menuprogs->ToggleBreak(menuprogs, filename, line, 2);
wasset = menu_world.progs->ToggleBreak(menu_world.progs, filename, line, 3);
isset = menu_world.progs->ToggleBreak(menu_world.progs, filename, line, 2);
if (wasset == isset)
Con_Printf("Breakpoint was not valid\n");
@ -1944,7 +1763,7 @@ void MP_RegisterCvarsAndCmds(void)
void MP_Draw(void)
{
if (!menuprogs)
if (!menu_world.progs)
return;
if (setjmp(mp_abort))
return;
@ -1955,7 +1774,7 @@ void MP_Draw(void)
inmenuprogs++;
if (mp_draw_function)
PR_ExecuteProgram(menuprogs, mp_draw_function);
PR_ExecuteProgram(menu_world.progs, mp_draw_function);
inmenuprogs--;
}
@ -1996,10 +1815,10 @@ void MP_Keydown(int key, int unicode)
inmenuprogs++;
if (mp_keydown_function)
{
void *pr_globals = PR_globals(menuprogs, PR_CURRENT);
void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoDPCodes(key);
G_FLOAT(OFS_PARM1) = unicode;
PR_ExecuteProgram(menuprogs, mp_keydown_function);
PR_ExecuteProgram(menu_world.progs, mp_keydown_function);
}
inmenuprogs--;
}
@ -2021,17 +1840,17 @@ void MP_Keyup(int key, int unicode)
inmenuprogs++;
if (mp_keyup_function)
{
void *pr_globals = PR_globals(menuprogs, PR_CURRENT);
void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoDPCodes(key);
G_FLOAT(OFS_PARM1) = unicode;
PR_ExecuteProgram(menuprogs, mp_keyup_function);
PR_ExecuteProgram(menu_world.progs, mp_keyup_function);
}
inmenuprogs--;
}
qboolean MP_Toggle(void)
{
if (!menuprogs)
if (!menu_world.progs)
return false;
#ifdef TEXTEDITOR
if (editormodal)
@ -2048,9 +1867,9 @@ qboolean MP_Toggle(void)
inmenuprogs++;
if (mp_toggle_function)
{
void *pr_globals = PR_globals(menuprogs, PR_CURRENT);
void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = 1;
PR_ExecuteProgram(menuprogs, mp_toggle_function);
PR_ExecuteProgram(menu_world.progs, mp_toggle_function);
}
inmenuprogs--;

View File

@ -84,6 +84,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#pragma warning( 4 : 4267) //truncation from const double to float
#pragma warning( 4 : 4710) //function not inlined
#pragma warning( error : 4020)

View File

@ -1103,7 +1103,7 @@ void R2D_DrawCrosshair(void)
int sc;
float sx, sy, sizex, sizey;
float size, chc;
float size;
if (crosshair.ival < 1)
return;
@ -1112,7 +1112,7 @@ void R2D_DrawCrosshair(void)
if (crosshair.ival == 1 && !crosshairimage.string[0])
{
// adjust console crosshair scale to match default
size = crosshairsize.value / 8;
size = crosshairsize.value;
if (size == 0)
size = 8;
else if (size < 0)
@ -1121,8 +1121,8 @@ void R2D_DrawCrosshair(void)
{
SCR_CrosshairPosition(sc, &x, &y);
Font_BeginScaledString(font_conchar, x, y, size, size, &sx, &sy);
sx -= Font_CharWidth('+' | 0xe000 | CON_WHITEMASK)/2;
sy -= Font_CharHeight()/2;
sx -= Font_CharScaleWidth('+' | 0xe000 | CON_WHITEMASK)/2;
sy -= Font_CharScaleHeight()/2;
Font_ForceColour(ch_color[0], ch_color[1], ch_color[2], crosshairalpha.value);
Font_DrawScaleChar(sx, sy, '+' | 0xe000 | CON_WHITEMASK);
Font_InvalidateColour();
@ -1138,13 +1138,11 @@ void R2D_DrawCrosshair(void)
size = -size;
sizex = size;
sizey = size;
chc = 0;
}
else
{
sizex = (size*vid.rotpixelwidth) / (float)vid.width;
sizey = (size*vid.rotpixelheight) / (float)vid.height;
chc = size / 16.0;
}
sizex = (int)sizex;
@ -1159,8 +1157,8 @@ void R2D_DrawCrosshair(void)
SCR_CrosshairPosition(sc, &x, &y);
//translate to pixel coord, for rounding
x = ((x-sizex-chc)*vid.rotpixelwidth) / (float)vid.width;
y = ((y-sizey-chc)*vid.rotpixelheight) / (float)vid.height;
x = ((x-sizex+(sizex/CS_WIDTH))*vid.rotpixelwidth) / (float)vid.width;
y = ((y-sizey+(sizey/CS_HEIGHT))*vid.rotpixelheight) / (float)vid.height;
//translate to screen coords
sx = ((x)*(int)vid.width) / (float)vid.rotpixelwidth;

View File

@ -1365,7 +1365,7 @@ TRACE(("dbg: R_ApplyRenderer: efrags\n"));
}
}
Skin_FlushPlayers();
Skin_FlushAll();
#ifdef CSQC_DAT
CSQC_RendererRestarted();

View File

@ -1850,7 +1850,7 @@ void Sbar_DrawScoreboard (void)
#ifndef CLIENTONLY
/*no scoreboard in single player (if you want bots, set deathmatch)*/
if (sv.state && cls.gamemode == GAME_COOP && sv.allocated_client_slots == 1)
if (sv.state && !cls.deathmatch && sv.allocated_client_slots == 1)
{
return;
}
@ -2474,7 +2474,7 @@ void Sbar_Draw (void)
{
if (!pnum)
{
if (cls.gamemode != GAME_DEATHMATCH)
if (!cls.deathmatch)
Sbar_CoopScoreboard ();
else
Sbar_SoloScoreboard ();
@ -3292,7 +3292,7 @@ void Sbar_IntermissionOverlay (void)
Sbar_Start();
if (cls.gamemode != GAME_DEATHMATCH)
if (!cls.deathmatch)
Sbar_CoopIntermission();
else if (cl.teamplay > 0 && !sb_showscores)
Sbar_TeamOverlay ();

View File

@ -105,7 +105,9 @@ void Font_BeginString(struct font_s *font, int vx, int vy, int *px, int *py);
void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx, float szy, float *px, float *py); /*avoid using*/
void Font_Transform(int vx, int vy, int *px, int *py);
int Font_CharHeight(void);
float Font_CharScaleHeight(void);
int Font_CharWidth(unsigned int charcode);
float Font_CharScaleWidth(unsigned int charcode);
int Font_CharEndCoord(struct font_s *font, int x, unsigned int charcode);
int Font_DrawChar(int px, int py, unsigned int charcode);
float Font_DrawScaleChar(float px, float py, unsigned int charcode); /*avoid using*/

View File

@ -590,6 +590,19 @@ void Skin_FlushPlayers(void)
CL_NewTranslation(i);
}
void Skin_FlushAll(void)
{ //wipe the skin info
int i;
for (i=0 ; i<numskins ; i++)
{
if (skins[i].cache.data)
Cache_Free (&skins[i].cache);
}
numskins = 0;
Skin_FlushPlayers();
}
/*
==========
Skin_Skins_f

View File

@ -369,7 +369,7 @@ void S_Voip_Parse(void)
}
MSG_ReadData(data, bytes);
sender &= MAX_CLIENTS-1;
sender %= MAX_CLIENTS;
amp = s_speex.decamp[sender];
@ -906,6 +906,9 @@ void S_Startup (void)
S_ClearRaw();
CL_InitTEntSounds();
ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
}
void S_SetUnderWater(qboolean underwater)
@ -931,9 +934,6 @@ void S_DoRestart (void)
S_Startup();
ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
S_StopAllSounds (true);
@ -1170,16 +1170,6 @@ void S_Init (void)
known_sfx = Hunk_AllocName (MAX_SFX*sizeof(sfx_t), "sfx_t");
num_sfx = 0;
// create a piece of DMA memory
if (sndcardinfo)
Con_SafePrintf ("Sound sampling rate: %i\n", sndcardinfo->sn.speed);
ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
S_StopAllSounds (true);
}
@ -1279,6 +1269,13 @@ void S_Purge(qboolean retaintouched)
sfx_t *sfx;
int i;
//make sure ambients are kept. silly ambients.
if (retaintouched)
{
ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
}
S_LockMixer();
for (i=0 ; i < num_sfx ; i++)
{
@ -1438,8 +1435,9 @@ void SND_Spatialize(soundcardinfo_t *sc, channel_t *ch)
dist = VectorNormalize(world_vec) * ch->dist_mult;
listener_vec[1] = DotProduct(listener_right, world_vec);
//rotate the world_vec into listener space, so that the audio direction stored in the speakerdir array can be used directly.
listener_vec[0] = DotProduct(listener_forward, world_vec);
listener_vec[1] = DotProduct(listener_right, world_vec);
listener_vec[2] = DotProduct(listener_up, world_vec);
if (snd_leftisright.ival)
@ -1447,9 +1445,7 @@ void SND_Spatialize(soundcardinfo_t *sc, channel_t *ch)
for (i = 0; i < sc->sn.numchannels; i++)
{
scale = (1 + DotProduct(listener_vec, sc->speakerdir[i])) / 2;
if (scale > 1)
scale = 1;
scale = 1 + DotProduct(listener_vec, sc->speakerdir[i]);
scale = (1.0 - dist) * scale * sc->dist[i];
ch->vol[i] = (int) (ch->master_vol * scale);
if (ch->vol[i] < 0)
@ -1813,7 +1809,7 @@ void S_UpdateAmbientSounds (soundcardinfo_t *sc)
return;
l = Q1BSP_LeafForPoint(cl.worldmodel, listener_origin);
if (!l || !ambient_level.value)
if (!l || ambient_level.value <= 0)
{
for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
{

View File

@ -146,7 +146,32 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime)
if (!s)
continue;
if (!ch->vol[0] && !ch->vol[1] && !ch->vol[2] && !ch->vol[3] && !ch->vol[4] && !ch->vol[5])
{
//does it still make a sound if it cannot be heard?...
//technically no...
//this code is hacky.
if (!s->decoder.decodedata && s->decoder.buf)
{
scache = s->decoder.buf;
ch->pos += (end-sc->paintedtime)*ch->rate;
if (ch->pos > scache->length)
{
ch->pos = 0;
if (scache->loopstart != -1)
ch->pos = scache->loopstart<<PITCHSHIFT;
else if (!ch->looping)
{
ch->sfx = NULL;
if (s->decoder.abort)
{
if (!S_IsPlayingSomewhere(s))
s->decoder.abort(s);
}
}
}
}
continue;
}
ltime = sc->paintedtime;
while (ltime < end)

View File

@ -32,6 +32,7 @@ static cvar_t editstripcr = CVARD("edit_stripcr", "1", "remove \\r from eols (on
static cvar_t editaddcr = CVARD("edit_addcr", editaddcr_default, "make sure that each line ends with a \\r (on save)");
static cvar_t edittabspacing = CVARD("edit_tabsize", "4", "How wide tab alignment is");
cvar_t debugger = CVARD("debugger", debugger_default, "When enabled, QC errors and debug events will enable step-by-step tracing.");
extern cvar_t pr_sourcedir;
static pubprogfuncs_t *editprogfuncs;
@ -83,6 +84,7 @@ static char OpenEditorFile[256];
qboolean editoractive; //(export)
keydest_t editor_oldkeydest = key_game;
qboolean editormodal; //doesn't return. (export)
static qboolean madechanges;
static qboolean editenabled;
@ -187,7 +189,8 @@ static void CloseEditor(void)
{
fileblock_t *b;
key_dest = key_game;
if (key_dest == key_editor)
key_dest = editor_oldkeydest;
editoractive = false;
editprogfuncs = NULL;
@ -280,6 +283,7 @@ static void EditorNewFile(void)
madechanges = true;
executionlinenum = -1;
editor_oldkeydest = key_dest;
key_dest = key_editor;
editoractive = true;
editenabled = true;
@ -299,7 +303,7 @@ static void EditorOpenFile(char *name, qboolean readonly)
if (!(F = FS_OpenVFS(OpenEditorFile, "rb", FS_GAME)))
{
Q_snprintfz(OpenEditorFile, sizeof(OpenEditorFile), "src/%s", name);
Q_snprintfz(OpenEditorFile, sizeof(OpenEditorFile), "%s/%s", pr_sourcedir.string, name);
if (!(F = FS_OpenVFS(OpenEditorFile, "rb", FS_GAME)))
{
Con_Printf("Couldn't open file \"%s\"\nA new file will be created\n", name);
@ -382,6 +386,7 @@ static void EditorOpenFile(char *name, qboolean readonly)
executionlinenum = -1;
editenabled = !readonly;
editor_oldkeydest = key_dest;
key_dest = key_editor;
editoractive = true;
}
@ -1066,7 +1071,14 @@ void Editor_Draw(void)
fileblock_t *b;
if (key_dest != key_console)
{
if (editor_oldkeydest == key_menu && !editormodal)
{
CloseEditor();
return;
}
key_dest = key_editor;
}
if ((editoractive && cls.state == ca_disconnected) || editormodal)
R2D_EditorBackground();
@ -1211,6 +1223,10 @@ int QCLibEditor(pubprogfuncs_t *prfncs, char *filename, int line, int statement,
f1 += 4;
if (!strncmp(f2, "src/", 4))
f2 += 4;
if (!strncmp(f1, "source/", 7))
f1 += 7;
if (!strncmp(f2, "source/", 7))
f2 += 7;
stepasm = line < 0;
@ -1263,6 +1279,7 @@ int QCLibEditor(pubprogfuncs_t *prfncs, char *filename, int line, int statement,
if (!parms)
{
int oldkeydest = key_dest;
double oldrealtime = realtime;
editormodal = true;
@ -1280,6 +1297,7 @@ int QCLibEditor(pubprogfuncs_t *prfncs, char *filename, int line, int statement,
}
realtime = oldrealtime;
key_dest = oldkeydest;
editormodal = false;
}

View File

@ -235,7 +235,7 @@ void V_DriftPitch (int pnum)
// don't count small mouse motion
if (cl.playerview[pnum].nodrift)
{
if ( fabs(cl.frames[(cls.netchan.outgoing_sequence-1)&UPDATE_MASK].cmd[pnum].forwardmove) < 200)
if ( fabs(cl.outframes[(cl.movesequence-1)&UPDATE_MASK].cmd[pnum].forwardmove) < 200)
cl.playerview[pnum].driftmove = 0;
else
cl.playerview[pnum].driftmove += host_frametime;

View File

@ -523,7 +523,7 @@ static char *Macro_Powerups (void)
if (cl.playerview[SP].stats[STAT_ITEMS] & IT_INVISIBILITY)
MacroBuf_strcat_with_separator (tp_name_ring.string);
effects = cl.frames[cl.parsecount&UPDATE_MASK].playerstate[cl.playernum[SP]].effects;
effects = cl.inframes[cl.parsecount&UPDATE_MASK].playerstate[cl.playernum[SP]].effects;
if ( (effects & (QWEF_FLAG1|QWEF_FLAG2)) || // CTF
(cl.teamfortress && cl.playerview[SP].stats[STAT_ITEMS] & (IT_KEY1|IT_KEY2)) ) // TF
MacroBuf_strcat_with_separator (tp_name_flag.string);
@ -879,7 +879,7 @@ static void CountNearbyPlayers(qboolean dead)
if (!cl.oldparsecount || !cl.parsecount || cls.state < ca_active)
return;
state = cl.frames[cl.oldparsecount & UPDATE_MASK].playerstate;
state = cl.inframes[cl.oldparsecount & UPDATE_MASK].playerstate;
info = cl.players;
for (i = 0; i < MAX_CLIENTS; i++, info++, state++) {
if (i != cl.playernum[0] && state->messagenum == cl.oldparsecount && !info->spectator && !ISDEAD(state->frame)) {
@ -2502,7 +2502,7 @@ static void TP_FindModelNumbers (void)
// for armors, returns skinnum+1 on success
static int FindNearestItem (int flags, item_t **pitem)
{
frame_t *frame;
inframe_t *frame;
packet_entities_t *pak;
entity_state_t *ent;
int i = 0, bestidx = 0, bestskin = 0;
@ -2510,11 +2510,11 @@ static int FindNearestItem (int flags, item_t **pitem)
vec3_t org, v;
item_t *item;
VectorCopy (cl.frames[cl.validsequence&UPDATE_MASK]
VectorCopy (cl.inframes[cl.validsequence&UPDATE_MASK]
.playerstate[cl.playernum[SP]].origin, org);
// look in previous frame
frame = &cl.frames[cl.oldvalidsequence&UPDATE_MASK];
frame = &cl.inframes[cl.oldvalidsequence&UPDATE_MASK];
pak = &frame->packet_entities;
bestdist = 100.0f;
bestidx = 0;
@ -2651,7 +2651,7 @@ void TP_ParsePlayerInfo(player_state_t *oldstate, player_state_t *state, player_
{
if ((state->effects & (QWEF_FLAG1|QWEF_FLAG2)) && !(oldstate->effects & (QWEF_FLAG1|QWEF_FLAG2)))
{
ExecTookTrigger (tp_name_flag.string, it_flag, cl.frames[cl.validsequence & UPDATE_MASK].playerstate[cl.playernum[SP]].origin);
ExecTookTrigger (tp_name_flag.string, it_flag, cl.inframes[cl.validsequence & UPDATE_MASK].playerstate[cl.playernum[SP]].origin);
}
else if (!(state->effects & (QWEF_FLAG1|QWEF_FLAG2)) && (oldstate->effects & (QWEF_FLAG1|QWEF_FLAG2)))
{
@ -2938,7 +2938,7 @@ static void TP_FindPoint (void)
pointflags_dmm &= ~it_weapons;
}
pak = &cl.frames[cl.validsequence & UPDATE_MASK].packet_entities;
pak = &cl.inframes[cl.validsequence & UPDATE_MASK].packet_entities;
for (i = 0,ent = pak->entities; i < pak->num_entities; i++, ent++)
{
item = model2item[ent->modelindex];
@ -2972,7 +2972,7 @@ static void TP_FindPoint (void)
}
}
state = cl.frames[cl.parsecount & UPDATE_MASK].playerstate;
state = cl.inframes[cl.parsecount & UPDATE_MASK].playerstate;
info = cl.players;
for (j = 0; j < MAX_CLIENTS; j++, info++, state++)
{
@ -3177,7 +3177,7 @@ void TP_StatChanged (int stat, int value)
if (cl.teamfortress && !cl.spectator)
{
ExecTookTrigger (tp_name_flag.string, it_flag,
cl.frames[cl.validsequence&UPDATE_MASK].playerstate[cl.playernum[SP]].origin);
cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[cl.playernum[SP]].origin);
}
}

View File

@ -92,6 +92,7 @@ typedef struct cvar_s
#define CVARAFC(ConsoleName,Value,ConsoleName2,Flags,Callback) CVARAFC(ConsoleName, Value, ConsoleName2, Flags, NULL, Callback)
#define CVARAF(ConsoleName,Value,ConsoleName2,Flags) CVARAFDC(ConsoleName, Value, ConsoleName2, Flags, NULL, NULL)
#define CVARFC(ConsoleName,Value,Flags,Callback) CVARAFDC(ConsoleName, Value, NULL, Flags, NULL, Callback)
#define CVARAD(ConsoleName,Value,ConsoleName2,Description) CVARAFDC(ConsoleName, Value, ConsoleName2, 0, Description, NULL)
#define CVARFD(ConsoleName,Value,Flags,Description) CVARAFDC(ConsoleName, Value, NULL, Flags, Description, NULL)
#define CVARF(ConsoleName,Value,Flags) CVARFC(ConsoleName, Value, Flags, NULL)
#define CVARC(ConsoleName,Value,Callback) CVARFC(ConsoleName, Value, 0, Callback)

View File

@ -97,7 +97,7 @@ qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b);
char *NET_AdrToString (char *s, int len, netadr_t a);
char *NET_BaseAdrToString (char *s, int len, netadr_t a);
qboolean NET_StringToSockaddr (const char *s, int defaultport, struct sockaddr_qstorage *sadr, int *addrfamily, int *addrsize);
qboolean NET_StringToAdr (const char *s, netadr_t *a);
qboolean NET_StringToAdr (const char *s, int defaultport, netadr_t *a);
qboolean NET_IsClientLegal(netadr_t *adr);
qboolean NET_IsLoopBackAddress (netadr_t adr);

View File

@ -196,6 +196,7 @@ unsigned int Net_PextMask(int maskset, qboolean fornq)
if (pext_replacementdeltas.ival)
mask |= PEXT2_REPLACEMENTDELTAS;
//mask |= PEXT2_PREDINFO;
if (MAX_CLIENTS != QWMAX_CLIENTS)
mask |= PEXT2_MAXPLAYERS;
@ -203,7 +204,7 @@ unsigned int Net_PextMask(int maskset, qboolean fornq)
if (fornq)
{
//only ones that are tested
mask &= PEXT2_VOICECHAT | PEXT2_REPLACEMENTDELTAS;
mask &= PEXT2_VOICECHAT | PEXT2_REPLACEMENTDELTAS | PEXT2_PREDINFO;
}
}
@ -431,13 +432,13 @@ nqprot_t NQNetChan_Process(netchan_t *chan)
{
if (sequence <= chan->incoming_unreliable)
{
Con_DPrintf("Stale datagram recieved\n");
Con_DPrintf("Stale datagram recieved (%i<=%i)\n", sequence, chan->incoming_unreliable);
return NQP_ERROR;
}
drop = sequence - chan->incoming_unreliable - 1;
if (drop > 0)
{
Con_DPrintf("Dropped %i datagrams\n", drop);
Con_DPrintf("Dropped %i datagrams (%i - %i)\n", chan->incoming_unreliable+1, sequence-1);
chan->drop_count += drop;
}
chan->incoming_unreliable = sequence;

View File

@ -856,7 +856,7 @@ dblbreak:
accepts anything that NET_StringToSockaddr accepts plus certain url schemes
including: tcp, irc
*/
qboolean NET_StringToAdr (const char *s, netadr_t *a)
qboolean NET_StringToAdr (const char *s, int defaultport, netadr_t *a)
{
struct sockaddr_qstorage sadr;
@ -1116,7 +1116,7 @@ qboolean NET_StringToAdrMasked (const char *s, netadr_t *a, netadr_t *amask)
i = sizeof(t);
Q_strncpyz(t, s, i);
if (!ParsePartialIPv4(t, a) && !NET_StringToAdr(t, a))
if (!ParsePartialIPv4(t, a) && !NET_StringToAdr(t, 0, a))
return false;
spoint++;
@ -1135,7 +1135,7 @@ qboolean NET_StringToAdrMasked (const char *s, netadr_t *a, netadr_t *amask)
}
if (c == NULL) // we have an address so resolve it and return
return ParsePartialIPv4(spoint, amask) || NET_StringToAdr(spoint, amask);
return ParsePartialIPv4(spoint, amask) || NET_StringToAdr(spoint, 0, amask);
// otherwise generate mask for given bits
i = atoi(spoint);
@ -1145,7 +1145,7 @@ qboolean NET_StringToAdrMasked (const char *s, netadr_t *a, netadr_t *amask)
{
// we don't have a slash, resolve and fill with a full mask
i = ParsePartialIPv4(s, a);
if (!i && !NET_StringToAdr(s, a))
if (!i && !NET_StringToAdr(s, 0, a))
return false;
memset (amask, 0, sizeof(*amask));
@ -1937,8 +1937,8 @@ qboolean NET_PortToAdr (int adrfamily, const char *s, netadr_t *a)
char *e;
int port;
port = strtoul(s, &e, 10);
if (*e)
return NET_StringToAdr(s, a);
if (*e) //if *e then its not just a single number in there, so treat it as a proper address.
return NET_StringToAdr(s, 0, a);
else if (port)
{
memset(a, 0, sizeof(*a));
@ -3493,7 +3493,7 @@ struct ftenet_generic_connection_s *FTENET_IRCConnect_EstablishConnection(qboole
ftenet_ircconnect_connection_t *newcon;
netadr_t adr;
if (!NET_StringToAdr(address, &adr))
if (!NET_StringToAdr(address, 6667, &adr))
return NULL; //couldn't resolve the name
@ -3860,7 +3860,7 @@ qboolean NET_EnsureRoute(ftenet_connections_t *collection, char *routename, char
{
netadr_t adr;
NET_StringToAdr(host, &adr);
NET_StringToAdr(host, 0, &adr);
switch(adr.type)
{
@ -4302,8 +4302,8 @@ void NET_GetLocalAddress (int socket, netadr_t *out)
gethostname(buff, 512);
buff[512-1] = 0;
if (!NET_StringToAdr (buff, &adr)) //urm
NET_StringToAdr ("127.0.0.1", &adr);
if (!NET_StringToAdr (buff, 0, &adr)) //urm
NET_StringToAdr ("127.0.0.1", 0, &adr);
namelen = sizeof(address);
@ -4709,7 +4709,7 @@ vfsfile_t *FS_OpenTCP(const char *name)
tcpfile_t *newf;
int sock;
netadr_t adr = {0};
if (NET_StringToAdr(name, &adr))
if (NET_StringToAdr(name, 0, &adr))
{
sock = TCP_OpenStream(adr);
if (sock == INVALID_SOCKET)

View File

@ -807,24 +807,12 @@ static qintptr_t VARGS Plug_Net_TCPListen(void *offset, quintptr_t mask, const q
int maxcount = VM_LONG(arg[2]);
netadr_t a;
if (localip)
{
if (!NET_StringToAdr(localip, &a))
return -1;
NetadrToSockadr(&a, &address);
}
else
{
memset(&address, 0, sizeof(address));
((struct sockaddr_in*)&address)->sin_family = AF_INET;
}
if (!localip)
localip = "0.0.0.0"; //pass "[::]" for ipv6
if (((struct sockaddr_in*)&address)->sin_family == AF_INET && !((struct sockaddr_in*)&address)->sin_port)
((struct sockaddr_in*)&address)->sin_port = htons(localport);
#ifdef IPPROTO_IPV6
else if (((struct sockaddr_in6*)&address)->sin6_family == AF_INET6 && !((struct sockaddr_in6*)&address)->sin6_port)
((struct sockaddr_in6*)&address)->sin6_port = htons(localport);
#endif
if (!NET_StringToAdr(localip, localport, &a))
return -1;
NetadrToSockadr(&a, &address);
switch(((struct sockaddr*)&address)->sa_family)
{
@ -914,8 +902,8 @@ static qintptr_t VARGS Plug_Net_Accept(void *offset, quintptr_t mask, const qint
//EBUILTIN(int, NET_TCPConnect, (char *ip, int port));
qintptr_t VARGS Plug_Net_TCPConnect(void *offset, quintptr_t mask, const qintptr_t *arg)
{
char *localip = VM_POINTER(arg[0]);
unsigned short localport = VM_LONG(arg[1]);
char *remoteip = VM_POINTER(arg[0]);
unsigned short remoteport = VM_LONG(arg[1]);
int handle;
struct sockaddr_qstorage to, from;
@ -924,16 +912,9 @@ qintptr_t VARGS Plug_Net_TCPConnect(void *offset, quintptr_t mask, const qintptr
netadr_t a;
if (!NET_StringToAdr(localip, &a))
if (!NET_StringToAdr(remoteip, remoteport, &a))
return -1;
NetadrToSockadr(&a, &to);
if (((struct sockaddr_in*)&to)->sin_family == AF_INET && !((struct sockaddr_in*)&to)->sin_port)
((struct sockaddr_in*)&to)->sin_port = htons(localport);
#ifdef IPPROTO_IPV6
else if (((struct sockaddr_in6*)&to)->sin6_family == AF_INET6 && !((struct sockaddr_in6*)&to)->sin6_port)
((struct sockaddr_in6*)&to)->sin6_port = htons(localport);
#endif
if ((sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{

View File

@ -695,6 +695,9 @@ void PM_AirMove (void)
blocked = PM_StepSlideMove (true);
else
blocked = PM_SlideMove ();
if (blocked & BLOCKED_FLOOR)
pmove.onground = true;
}
}
@ -978,6 +981,10 @@ void PM_NudgePosition (void)
for (i=0 ; i<3 ; i++)
base[i] = ((int)(base[i]*8)) * 0.125;
if (pmove.velocity[0] || pmove.velocity[1])
if (PM_TestPlayerPosition (pmove.origin))
return;
for (z=0 ; z<=4 ; z++)
{
for (x=0 ; x<=4 ; x++)
@ -1096,7 +1103,8 @@ void PM_PlayerMove (float gamespeed)
frametime = pmove.cmd.msec * 0.001*gamespeed;
pmove.numtouch = 0;
if (pmove.pm_type == PM_NONE || pmove.pm_type == PM_FREEZE) {
if (pmove.pm_type == PM_NONE || pmove.pm_type == PM_FREEZE)
{
PM_CategorizePosition ();
return;
}

View File

@ -2770,7 +2770,7 @@ static void PR_uri_get_callback(struct dl_download *dl)
{
extern pubprogfuncs_t *menuprogs;
world_t *w = dl->user_ctx;
pubprogfuncs_t *prinst = w?w->progs:menuprogs;
pubprogfuncs_t *prinst = w->progs;
float id = dl->user_num;
func_t func;
@ -2834,6 +2834,17 @@ void QCBUILTIN PF_uri_get (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
#endif
G_FLOAT(OFS_RETURN) = 0;
}
void QCBUILTIN PF_netaddress_resolve(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *address = PR_GetStringOfs(prinst, OFS_PARM0);
int defaultport = (prinst->callargc > 1)?G_FLOAT(OFS_PARM1):0;
netadr_t adr;
char result[256];
if (NET_StringToAdr(address, defaultport, &adr))
RETURN_TSTRING(NET_AdrToString (result, sizeof(result), adr));
else
RETURN_TSTRING("");
}
////////////////////////////////////////////////////
//Console functions
@ -4069,7 +4080,7 @@ lh_extension_t QSG_Extensions[] = {
{"FTE_PEXT_SPAWNSTATIC"}, //means that static entities can have alpha/scale and anything else the engine supports on normal ents. (Added for >256 models, while still being compatible - previous system failed with -1 skins)
{"FTE_PEXT_CUSTOMTENTS", 2, NULL, {"RegisterTempEnt", "CustomTempEnt"}},
{"FTE_PEXT_256PACKETENTITIES"}, //client is able to receive unlimited packet entities (server caps itself to 256 to prevent insanity).
{"FTE_PEXT_64PLAYERS"},
{NULL},
{"TEI_SHOWLMP2", 6, NULL, {"showpic", "hidepic", "movepic", "changepic", "showpicent", "hidepicent"}}, //telejano doesn't actually export the moveent/changeent (we don't want to either cos it would stop frik_file stuff being autoregistered)
{"DP_GFX_QUAKE3MODELTAGS", 1, NULL, {"setattachment"}},
{"FTE_PK3DOWNLOADS"},
@ -4079,7 +4090,7 @@ lh_extension_t QSG_Extensions[] = {
{"PEXT_DPFLAGS"},
//{"EXT_CSQC"}, //this is the base csqc extension. I'm not sure what needs to be separate and what does not.
{"EXT_CSQC"}, //this is the base csqc extension. I'm not sure what needs to be separate and what does not.
//{"EXT_CSQC_DELTAS"},//this is a separate extension because the feature may be banned in a league due to cheat protection.
//the rest are generic extensions

View File

@ -325,8 +325,22 @@ void QCBUILTIN PF_R_PolygonEnd(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
#define PF_R_PolygonEnd PF_Fixme
#endif
void QCBUILTIN PF_cl_gethostcachevalue (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_gethostcachestring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_resethostcachemasks(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_sethostcachemaskstring(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_sethostcachemasknumber(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_resorthostcache(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_sethostcachesort(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_refreshhostcache(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_gethostcachenumber(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_gethostcacheindexforkey(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_addwantedhostcachekey(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_getextresponse(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_netaddress_resolve(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_getmousepos (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_GetBindMap (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_SetBindMap (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_keynumtostring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_findkeysforcommand (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_stringtokeynum(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);

View File

@ -75,7 +75,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PEXT2_SETANGLEDELTA 0x00000004
#define PEXT2_REPLACEMENTDELTAS 0x00000008
#define PEXT2_MAXPLAYERS 0x00000010 //Client is able to cope with more players than 32. abs max becomes 255, due to colormap issues.
//#define PEXT2_PK3DOWNLOADS 0x10000000 //retrieve a list of pk3s/pk3s/paks for downloading (with optional URL and crcs)
#define PEXT2_PREDINFO 0x00000020 //movevars, NQ input sequences+acks.
//ZQuake transparent protocol extensions.
#define Z_EXT_PM_TYPE (1<<0) // basic PM_TYPE functionality (reliable jump_held)
@ -378,6 +378,9 @@ enum clcq2_ops_e
#define PC_PARTICLE 0x4000
#define PC_UNUSED 0xc000
#define GAME_COOP 0
#define GAME_DEATHMATCH 1
// playerinfo flags from server
// playerinfo always sends: playernum, flags, origin[] and framenumber

View File

@ -263,7 +263,7 @@ static char *defaultlanguagetext =
cvar_t language = SCVAR("language", "uk");
cvar_t language = SCVAR("language", "en-gb");
char lastlang[9];
typedef struct trans_s {

View File

@ -16,7 +16,9 @@ void Font_BeginString(struct font_s *font, int vx, int vy, int *px, int *py);
void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx, float szy, float *px, float *py); /*avoid using*/
void Font_Transform(int vx, int vy, int *px, int *py);
int Font_CharHeight(void);
float Font_CharScaleHeight(void);
int Font_CharWidth(unsigned int charcode);
float Font_CharScaleWidth(unsigned int charcode);
int Font_CharEndCoord(struct font_s *font, int x, unsigned int charcode);
int Font_DrawChar(int px, int py, unsigned int charcode);
float Font_DrawScaleChar(float px, float py, unsigned int charcode); /*avoid using*/
@ -1241,6 +1243,12 @@ int Font_CharHeight(void)
return curfont->charheight;
}
//obtains the font's row height (each row of chars should be drawn using this increment)
float Font_CharScaleHeight(void)
{
return curfont->charheight * curfont_scale[1];
}
/*
This is where the character ends.
Note: this function supports tabs - x must always be based off 0, with Font_LineDraw actually used to draw the line.
@ -1285,6 +1293,25 @@ int Font_CharWidth(unsigned int charcode)
return c->advance;
}
//obtains the width of a character from a given font. This is how wide it is. The next char should be drawn at x + result.
float Font_CharScaleWidth(unsigned int charcode)
{
struct charcache_s *c;
struct font_s *font = curfont;
if (charcode&CON_HIDDEN)
return 0;
if ((charcode & CON_2NDCHARSETTEXT) && font->alt)
font = font->alt;
c = Font_GetChar(curfont, (CHARIDXTYPE)(charcode&CON_CHARMASK));
if (!c)
{
return 0;
}
return c->advance * curfont_scale[0];
}
//for a given font, calculate the line breaks and word wrapping for a block of text
//start+end are the input string
//starts+ends are an array of line start and end points, which have maxlines elements.

View File

@ -1786,7 +1786,10 @@ void RMod_LoadLighting (lump_t *l)
}
}
else if (litdata)
{
Con_Printf("lit \"%s\" isn't a lit\n", litname);
litdata = NULL;
}
// else
//failed to find
}

View File

@ -158,7 +158,7 @@ void GLSCR_UpdateScreen (void)
else
#endif
#ifdef CSQC_DAT
if (cls.state == ca_active && CSQC_DrawView())
if (CSQC_DrawView())
nohud = true;
else
#endif

View File

@ -1389,12 +1389,19 @@ static qboolean Sh_VisOverlaps(qbyte *v1, qbyte *v2)
int i, m;
if (!v2)
return false;
m = (cl.worldmodel->numleafs-1)>>3;
for (i=0 ; i<m ; i++)
m = (cl.worldmodel->numleafs+7)>>3;
for (i=(m&~3) ; i<m ; i++)
{
if (v1[i] & v2[i])
return true;
}
m>>=2;
for (i=0 ; i<m ; i++)
{
if (((unsigned int*)v1)[i] & ((unsigned int*)v2)[i])
return true;
}
return false;
}

View File

@ -1235,6 +1235,16 @@ qboolean VID_AttachGL (rendererstate_t *info)
Con_Printf("Unsupported OpenGL context version (%s).\n", vid_gl_context_version.string);
else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB))
Con_Printf("Unsupported OpenGL profile (%s).\n", vid_gl_context_es2.ival?"gles":(vid_gl_context_compatibility.ival?"compat":"core"));
else if (error == (0xc0070000 | ERROR_INVALID_OPERATION))
Con_Printf("wglCreateContextAttribsARB returned invalid operation.\n");
else if (error == (0xc0070000 | ERROR_DC_NOT_FOUND))
Con_Printf("wglCreateContextAttribsARB returned dc not found.\n");
else if (error == (0xc0070000 | ERROR_INVALID_PIXEL_FORMAT))
Con_Printf("wglCreateContextAttribsARB returned dc not found.\n");
else if (error == (0xc0070000 | ERROR_NO_SYSTEM_RESOURCES))
Con_Printf("wglCreateContextAttribsARB ran out of system resources.\n");
else if (error == (0xc0070000 | ERROR_INVALID_PARAMETER))
Con_Printf("wglCreateContextAttribsARB reported invalid parameter.\n");
else
Con_Printf("Unknown error creating an OpenGL (%s) Context.\n", vid_gl_context_version.string);
}
@ -1283,6 +1293,8 @@ void GL_BeginRendering (void)
vid.pixelwidth = WindowRect.right - WindowRect.left;
vid.pixelheight = WindowRect.bottom - WindowRect.top;
qglDisable(GL_SCISSOR_TEST);
// if (!wglMakeCurrent( maindc, baseRC ))
// Sys_Error ("wglMakeCurrent failed");

View File

@ -1,6 +1,12 @@
#define PROGSUSED
#include "progsint.h"
#include <stdlib.h>
#define STRING_SPECMASK 0xc0000000 //
#define STRING_TEMP 0x80000000 //temp string, will be collected.
#define STRING_STATIC 0xc0000000 //pointer to non-qcvm string.
#define STRING_NORMAL_ 0x00000000 //stringtable/mutable. should always be a fallthrough
#define STRING_NORMAL2_ 0x40000000 //stringtable/mutable. should always be a fallthrough
typedef struct prmemb_s {
struct prmemb_s *prev;
int level;
@ -384,7 +390,7 @@ static void PDECL PR_memfree (pubprogfuncs_t *ppf, void *memptr)
// PR_memvalidate(progfuncs);
}
void PRAddressableFlush(progfuncs_t *progfuncs, int totalammount)
void PRAddressableFlush(progfuncs_t *progfuncs, size_t totalammount)
{
prinst.addressableused = 0;
if (totalammount < 0) //flush
@ -440,7 +446,7 @@ int PDECL PR_InitEnts(pubprogfuncs_t *ppf, int max_ents)
edictrun_t tempedict; //used as a safty buffer
static float tempedictfields[2048];
void PDECL PR_Configure (pubprogfuncs_t *ppf, int addressable_size, int max_progs) //can be used to wipe all memory
void PDECL PR_Configure (pubprogfuncs_t *ppf, size_t addressable_size, int max_progs) //can be used to wipe all memory
{
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
unsigned int i;
@ -462,8 +468,16 @@ void PDECL PR_Configure (pubprogfuncs_t *ppf, int addressable_size, int max_prog
}
PRHunkFree(progfuncs, 0); //clear mem - our hunk may not be a real hunk.
if (addressable_size<0)
if (addressable_size<0 || addressable_size == (size_t)-1)
{
#ifdef _WIN64
addressable_size = 0x80000000; //use of virtual address space rather than physical memory means we can just go crazy and use the max of 2gb.
#else
addressable_size = 8*1024*1024;
#endif
}
if (addressable_size > 0x80000000)
addressable_size = 0x80000000;
PRAddressableFlush(progfuncs, addressable_size);
pr_progstate = PRHunkAlloc(progfuncs, sizeof(progstate_t) * max_progs, "progstatetable");
@ -784,7 +798,7 @@ string_t PDECL PR_StringToProgs (pubprogfuncs_t *ppf, char *str)
for (i = prinst.numallocedstrings-1; i >= 0; i--)
{
if (prinst.allocedstrings[i] == str)
return (string_t)((unsigned int)i | 0x80000000);
return (string_t)((unsigned int)i | STRING_STATIC);
if (!prinst.allocedstrings[i])
free = i;
}
@ -793,7 +807,7 @@ string_t PDECL PR_StringToProgs (pubprogfuncs_t *ppf, char *str)
{
i = free;
prinst.allocedstrings[i] = str;
return (string_t)((unsigned int)i | 0x80000000);
return (string_t)((unsigned int)i | STRING_STATIC);
}
prinst.maxallocedstrings += 1024;
@ -810,7 +824,7 @@ string_t PDECL PR_StringToProgs (pubprogfuncs_t *ppf, char *str)
if (!prinst.allocedstrings[i])
{
prinst.allocedstrings[i] = str;
return (string_t)((unsigned int)i | 0x80000000);
return (string_t)((unsigned int)i | STRING_STATIC);
}
}
@ -824,29 +838,27 @@ char *PDECL PR_RemoveProgsString (pubprogfuncs_t *ppf, string_t str)
//input string is expected to be an allocated string
//if its a temp, or a constant, just return NULL.
if ((unsigned int)str & 0xc0000000)
if (((unsigned int)str & STRING_SPECMASK) == STRING_STATIC)
{
if ((unsigned int)str & 0x80000000)
int i = str & ~STRING_SPECMASK;
if (i >= prinst.numallocedstrings)
{
int i = str & ~0x80000000;
if (i >= prinst.numallocedstrings)
{
progfuncs->funcs.pr_trace = 1;
return NULL;
}
if (prinst.allocedstrings[i])
{
ret = prinst.allocedstrings[i];
prinst.allocedstrings[i] = NULL; //remove it
return ret;
}
else
{
progfuncs->funcs.pr_trace = 1;
return NULL; //urm, was freed...
}
progfuncs->funcs.pr_trace = 1;
return NULL;
}
if (prinst.allocedstrings[i])
{
ret = prinst.allocedstrings[i];
prinst.allocedstrings[i] = NULL; //remove it
return ret;
}
else
{
progfuncs->funcs.pr_trace = 1;
return NULL; //urm, was freed...
}
}
printf("invalid static string %x\n", str);
progfuncs->funcs.pr_trace = 1;
return NULL;
}
@ -854,41 +866,38 @@ char *PDECL PR_RemoveProgsString (pubprogfuncs_t *ppf, string_t str)
char *ASMCALL PR_StringToNative (pubprogfuncs_t *ppf, string_t str)
{
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
if ((unsigned int)str & 0xc0000000)
if (((unsigned int)str & STRING_SPECMASK) == STRING_STATIC)
{
if ((unsigned int)str & 0x80000000)
int i = str & ~STRING_SPECMASK;
if (i >= prinst.numallocedstrings)
{
int i = str & ~0x80000000;
if (i >= prinst.numallocedstrings)
{
printf("invalid string %x\n", str);
PR_StackTrace(&progfuncs->funcs);
progfuncs->funcs.pr_trace = 1;
return "";
}
if (prinst.allocedstrings[i])
return prinst.allocedstrings[i];
else
{
printf("invalid string %x\n", str);
PR_StackTrace(&progfuncs->funcs);
progfuncs->funcs.pr_trace = 1;
return ""; //urm, was freed...
}
printf("invalid string %x\n", str);
PR_StackTrace(&progfuncs->funcs);
progfuncs->funcs.pr_trace = 1;
return "";
}
if ((unsigned int)str & 0x40000000)
if (prinst.allocedstrings[i])
return prinst.allocedstrings[i];
else
{
int i = str & ~0x40000000;
if (i >= prinst.numtempstrings)
{
printf("invalid temp string %x\n", str);
PR_StackTrace(&progfuncs->funcs);
progfuncs->funcs.pr_trace = 1;
return "";
}
return prinst.tempstrings[i];
printf("invalid string %x\n", str);
PR_StackTrace(&progfuncs->funcs);
progfuncs->funcs.pr_trace = 1;
return ""; //urm, was freed...
}
}
if (((unsigned int)str & STRING_SPECMASK) == STRING_TEMP)
{
int i = str & ~STRING_SPECMASK;
if (i >= prinst.numtempstrings)
{
printf("invalid temp string %x\n", str);
PR_StackTrace(&progfuncs->funcs);
progfuncs->funcs.pr_trace = 1;
return "";
}
return prinst.tempstrings[i];
}
if ((unsigned int)str >= (unsigned int)prinst.addressableused)
{
@ -932,7 +941,7 @@ string_t PDECL PR_AllocTempString (pubprogfuncs_t *ppf, const char *str)
prinst.tempstrings[i] = progfuncs->funcs.parms->memalloc(strlen(str)+1);
strcpy(prinst.tempstrings[i], str);
return (string_t)((unsigned int)i | 0x40000000);
return (string_t)((unsigned int)i | STRING_TEMP);
}
string_t PDECL PR_AllocTempStringLen (pubprogfuncs_t *ppf, char **str, unsigned int len)
{
@ -965,7 +974,7 @@ string_t PDECL PR_AllocTempStringLen (pubprogfuncs_t *ppf, char **str, unsigne
prinst.tempstrings[i] = progfuncs->funcs.parms->memalloc(len);
*str = prinst.tempstrings[i];
return (string_t)((unsigned int)i | 0x40000000);
return (string_t)((unsigned int)i | STRING_TEMP);
}
void PR_FreeTemps (progfuncs_t *progfuncs, int depth)

View File

@ -153,8 +153,8 @@ int reorganisefields;
//initlib.c
int mfreelist;
char * addressablehunk;
unsigned int addressableused;
unsigned int addressablesize;
size_t addressableused;
size_t addressablesize;
struct edict_s **edicttable;
} prinst_t;
@ -466,7 +466,7 @@ fdef_t *ED_FindField (progfuncs_t *progfuncs, char *name);
fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs);
dfunction_t *ED_FindFunction (progfuncs_t *progfuncs, char *name, progsnum_t *pnum, progsnum_t fromprogs);
func_t PDECL PR_FindFunc(pubprogfuncs_t *progfncs, char *funcname, progsnum_t pnum);
void PDECL PR_Configure (pubprogfuncs_t *progfncs, int addressable_size, int max_progs);
void PDECL PR_Configure (pubprogfuncs_t *progfncs, size_t addressable_size, int max_progs);
int PDECL PR_InitEnts(pubprogfuncs_t *progfncs, int maxents);
char *PR_ValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val);
void PDECL QC_ClearEdict (pubprogfuncs_t *progfuncs, struct edict_s *ed);

View File

@ -66,7 +66,7 @@ struct pubprogfuncs_s
void (PDECL *CloseProgs) (pubprogfuncs_t *inst);
void (PDECL *Configure) (pubprogfuncs_t *prinst, int addressablesize, int max_progs); //configure buffers and memory. Used to reset and must be called first. Flushes a running VM.
void (PDECL *Configure) (pubprogfuncs_t *prinst, size_t addressablesize, int max_progs); //configure buffers and memory. Used to reset and must be called first. Flushes a running VM.
progsnum_t (PDECL *LoadProgs) (pubprogfuncs_t *prinst, char *s, int headercrc, builtin_t *builtins, int numbuiltins); //load a progs
int (PDECL *InitEnts) (pubprogfuncs_t *prinst, int max_ents); //returns size of edicts for use with nextedict macro
void (PDECL *ExecuteProgram) (pubprogfuncs_t *prinst, func_t fnum); //start execution

View File

@ -3846,6 +3846,9 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could
//note that we don't allow passing 0.0f for null.
//WARNING: field 0 is actually a valid field, and is commonly modelindex.
}
else if (p->type == ev_field && e->type->type == ev_field && (p->aux_type->type == ev_variant || e->type->aux_type->type == ev_variant))
{ //allow passing variant fields etc
}
else if ((p->type == ev_vector) && e->type->type == ev_integer && e->constant && !((int*)qcc_pr_globals)[e->ofs])
{
//also allow it for vector types too, but make sure the entire vector is valid.

View File

@ -8859,7 +8859,7 @@ static void QCBUILTIN PF_SendPacket(pubprogfuncs_t *prinst, struct globalvars_s
char *address = PR_GetStringOfs(prinst, OFS_PARM0);
char *contents = PF_VarString(prinst, 1, pr_globals);
NET_StringToAdr(address, &to);
NET_StringToAdr(address, 0, &to);
NET_SendPacket(NS_SERVER, strlen(contents), contents, to);
}
@ -9273,7 +9273,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"calltimeofday", PF_calltimeofday, 0, 0, 0, 231, "void()"},
//EXT_CSQC
{"clientstat", PF_clientstat, 0, 0, 0, 232, "void(float num, float type, .void fld)"}, //EXT_CSQC
{"clientstat", PF_clientstat, 0, 0, 0, 232, "void(float num, float type, .__variant fld)"}, //EXT_CSQC
{"globalstat", PF_globalstat, 0, 0, 0, 233, "void(float num, float type, string name)"}, //EXT_CSQC_1 actually
//END EXT_CSQC
{"isbackbuffered", PF_isbackbuffered, 0, 0, 0, 234, "float(entity player)"},
@ -9680,14 +9680,14 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"gethostcacheindexforkey",PF_Fixme, 0, 0, 0, 622, "float(string key)"},
{"addwantedhostcachekey",PF_Fixme, 0, 0, 0, 623, "void(string key)"},
{"getextresponse", PF_Fixme, 0, 0, 0, 624, "string()"},
{"netaddress_resolve",PF_Fixme, 0, 0, 0, 625, "string(string, float)"},
{"netaddress_resolve",PF_netaddress_resolve,0, 0, 0, 625, "string(string dnsname, optional float defport)"},
// {"getgamedirinfo", PF_Fixme, 0, 0, 0, 626, "string(float n, float prop)"},
{"sprintf", PF_sprintf, 0, 0, 0, 627, "string(string fmt, ...)"},
{"getsurfacenumtriangles",PF_getsurfacenumtriangles,0,0,0, 628, "float(entity e, float s)"},
{"getsurfacetriangle",PF_getsurfacetriangle,0, 0, 0, 629, "vector(entity e, float s, float n)"},
// {"setkeybind", PF_Fixme, 0, 0, 0, 630, "float(float key, string bind, optional float bindmap)"},
// {"getbindmaps", PF_Fixme, 0, 0, 0, 631, "vector()"},
// {"setbindmaps", PF_Fixme, 0, 0, 0, 632, "float(vector bm)"},
{"getbindmaps", PF_Fixme, 0, 0, 0, 631, "vector()" STUB},
{"setbindmaps", PF_Fixme, 0, 0, 0, 632, "float(vector bm)" STUB},
{"crypto_getkeyfp", PF_Fixme, 0, 0, 0, 633, "string(string addr)" STUB},
{"crypto_getidfp", PF_Fixme, 0, 0, 0, 634, "string(string addr)" STUB},
{"crypto_getencryptlevel",PF_Fixme, 0, 0, 0, 635, "string(string addr)" STUB},
@ -10214,6 +10214,7 @@ void PR_DumpPlatform_f(void)
#undef comfieldstring
#undef comfieldfunction
{"URI_Get_Callback", "noref void(float reqid, float responsecode, string resourcebody)", QW|NQ|CS|MENU},
{"SpectatorConnect", "noref void()", QW|NQ},
{"SpectatorDisconnect", "noref void()", QW|NQ},
{"SpectatorThink", "noref void()", QW|NQ},
@ -10414,6 +10415,17 @@ void PR_DumpPlatform_f(void)
{"MF_TRACER2", "const float", QW|NQ, EF_MF_TRACER2>>24},
{"MF_TRACER3", "const float", QW|NQ, EF_MF_TRACER3>>24},
//including these for csqc stat types.
// {"EV_VOID", "const float", QW|NQ, ev_void},
{"EV_STRING", "const float", QW|NQ, ev_string},
{"EV_FLOAT", "const float", QW|NQ, ev_float},
// {"EV_VECTOR", "const float", QW|NQ, ev_vector},
{"EV_ENTITY", "const float", QW|NQ, ev_entity},
// {"EV_FIELD", "const float", QW|NQ, ev_field},
// {"EV_FUNCTION", "const float", QW|NQ, ev_function},
// {"EV_POINTER", "const float", QW|NQ, ev_pointer},
{"EV_INTEGER", "const float", QW|NQ, ev_integer},
{"STAT_HEALTH", "const float", CS, STAT_HEALTH},
{"STAT_WEAPON", "const float", CS, STAT_WEAPON},
{"STAT_AMMO", "const float", CS, STAT_AMMO},
@ -10538,24 +10550,24 @@ void PR_DumpPlatform_f(void)
{"TEREDIT_MESH_KILL", "const float", CS, ter_mesh_kill},
{"TEREDIT_TINT", "const float", CS, ter_tint},
{"SLIST_HOSTCACHEVIEWCOUNT", "const float", MENU, SLIST_HOSTCACHEVIEWCOUNT},
{"SLIST_HOSTCACHETOTALCOUNT", "const float", MENU, SLIST_HOSTCACHETOTALCOUNT},
{"SLIST_MASTERQUERYCOUNT", "const float", MENU, SLIST_MASTERQUERYCOUNT},
{"SLIST_MASTERREPLYCOUNT", "const float", MENU, SLIST_MASTERREPLYCOUNT},
{"SLIST_SERVERQUERYCOUNT", "const float", MENU, SLIST_SERVERQUERYCOUNT},
{"SLIST_SERVERREPLYCOUNT", "const float", MENU, SLIST_SERVERREPLYCOUNT},
{"SLIST_SORTFIELD", "const float", MENU, SLIST_SORTFIELD},
{"SLIST_SORTDESCENDING", "const float", MENU, SLIST_SORTDESCENDING},
{"SLIST_TEST_CONTAINS", "const float", MENU, SLIST_TEST_CONTAINS},
{"SLIST_TEST_NOTCONTAIN", "const float", MENU, SLIST_TEST_NOTCONTAIN},
{"SLIST_TEST_LESSEQUAL", "const float", MENU, SLIST_TEST_LESSEQUAL},
{"SLIST_TEST_LESS", "const float", MENU, SLIST_TEST_LESS},
{"SLIST_TEST_EQUAL", "const float", MENU, SLIST_TEST_EQUAL},
{"SLIST_TEST_GREATER", "const float", MENU, SLIST_TEST_GREATER},
{"SLIST_TEST_GREATEREQUAL", "const float", MENU, SLIST_TEST_GREATEREQUAL},
{"SLIST_TEST_NOTEQUAL", "const float", MENU, SLIST_TEST_NOTEQUAL},
{"SLIST_TEST_STARTSWITH", "const float", MENU, SLIST_TEST_STARTSWITH},
{"SLIST_TEST_NOTSTARTSWITH", "const float", MENU, SLIST_TEST_NOTSTARTSWITH},
{"SLIST_HOSTCACHEVIEWCOUNT", "const float", CS|MENU, SLIST_HOSTCACHEVIEWCOUNT},
{"SLIST_HOSTCACHETOTALCOUNT", "const float", CS|MENU, SLIST_HOSTCACHETOTALCOUNT},
{"SLIST_MASTERQUERYCOUNT", "const float", CS|MENU, SLIST_MASTERQUERYCOUNT},
{"SLIST_MASTERREPLYCOUNT", "const float", CS|MENU, SLIST_MASTERREPLYCOUNT},
{"SLIST_SERVERQUERYCOUNT", "const float", CS|MENU, SLIST_SERVERQUERYCOUNT},
{"SLIST_SERVERREPLYCOUNT", "const float", CS|MENU, SLIST_SERVERREPLYCOUNT},
{"SLIST_SORTFIELD", "const float", CS|MENU, SLIST_SORTFIELD},
{"SLIST_SORTDESCENDING", "const float", CS|MENU, SLIST_SORTDESCENDING},
{"SLIST_TEST_CONTAINS", "const float", CS|MENU, SLIST_TEST_CONTAINS},
{"SLIST_TEST_NOTCONTAIN", "const float", CS|MENU, SLIST_TEST_NOTCONTAIN},
{"SLIST_TEST_LESSEQUAL", "const float", CS|MENU, SLIST_TEST_LESSEQUAL},
{"SLIST_TEST_LESS", "const float", CS|MENU, SLIST_TEST_LESS},
{"SLIST_TEST_EQUAL", "const float", CS|MENU, SLIST_TEST_EQUAL},
{"SLIST_TEST_GREATER", "const float", CS|MENU, SLIST_TEST_GREATER},
{"SLIST_TEST_GREATEREQUAL", "const float", CS|MENU, SLIST_TEST_GREATEREQUAL},
{"SLIST_TEST_NOTEQUAL", "const float", CS|MENU, SLIST_TEST_NOTEQUAL},
{"SLIST_TEST_STARTSWITH", "const float", CS|MENU, SLIST_TEST_STARTSWITH},
{"SLIST_TEST_NOTSTARTSWITH", "const float", CS|MENU, SLIST_TEST_NOTSTARTSWITH},
{NULL}
};
@ -10800,8 +10812,10 @@ void PR_DumpPlatform_f(void)
{
if (PR_CSQC_BuiltinValid(BuiltinList[i].name, idx))
nd |= CS;
#ifdef MENU_DAT
if (MP_BuiltinValid(BuiltinList[i].name, idx))
nd |= MENU;
#endif
if (!nd)
{

View File

@ -308,6 +308,7 @@ typedef struct //merge?
int num_entities;
int first_entity; // into the circular sv_packet_entities[]
int senttime; // for ping calculations
float ping_time;
} q2client_frame_t;
#endif
#ifdef Q3SERVER

View File

@ -1954,7 +1954,7 @@ void SV_Snap (int uid)
{
pcxname[strlen(pcxname) - 6] = i/10 + '0';
pcxname[strlen(pcxname) - 5] = i%10 + '0';
Q_snprintfz (checkname, sizeof(checkname), "%s/snap/%s", gamedirfile, pcxname);
Q_snprintfz (checkname, sizeof(checkname), "snap/%s", pcxname);
if (!COM_FCheckExists(checkname))
break; // file doesn't exist
}

View File

@ -1201,9 +1201,9 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t
/*start writing the packet*/
MSG_WriteByte (msg, svcfte_updateentities);
if (ISNQCLIENT(client))
if (ISNQCLIENT(client) && (client->fteprotocolextensions2 & PEXT2_PREDINFO))
{
MSG_WriteLong(msg, client->netchan.incoming_unreliable);
MSG_WriteLong(msg, client->last_sequence);
}
// Con_Printf("Gen sequence %i\n", sequence);
MSG_WriteFloat(msg, sv.world.physicstime);
@ -2842,16 +2842,24 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
}
}
if (ent->v->solid == SOLID_BSP || (ent->v->skin < 0 && ent->v->modelindex))
if (client && client->edict && (ent->v->owner == client->edict->entnum))
state->solid = 0;
else if (ent->v->solid == SOLID_BSP || (ent->v->skin < 0 && ent->v->modelindex))
state->solid = ES_SOLID_BSP;
else if (ent->v->solid == SOLID_BBOX || ent->v->solid == SOLID_SLIDEBOX || ent->v->skin < 0)
{
i = bound(0, -ent->v->mins[0]/8, 31);
state->solid = i;
i = bound(0, -ent->v->mins[2]/8, 31);
state->solid |= i<<5;
i = bound(0, ((ent->v->maxs[2]+32)/8), 63); /*up can be negative*/
state->solid |= i<<10;
unsigned int mdl = ent->v->modelindex;
if (mdl < MAX_MODELS && sv.models[mdl] && sv.models[mdl]->type == mod_brush)
state->solid = ES_SOLID_BSP;
else
{
i = bound(0, -ent->v->mins[0]/8, 31);
state->solid = i;
i = bound(0, -ent->v->mins[2]/8, 31);
state->solid |= i<<5;
i = bound(0, ((ent->v->maxs[2]+32)/8), 63); /*up can be negative*/
state->solid |= i<<10;
}
}
else
state->solid = 0;

View File

@ -776,11 +776,17 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
#endif
sv.state = ss_loading;
if (usecinematic)
{
qboolean Mod_LoadQ2BrushModel (model_t *mod, void *buffer);
extern model_t *loadmodel;
strcpy (sv.name, server);
strcpy (sv.modelname, "");
loadmodel = sv.world.worldmodel = Mod_FindName (sv.modelname);
loadmodel->needload = !Mod_LoadQ2BrushModel (sv.world.worldmodel, NULL);
}
else
{
@ -794,13 +800,12 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
else if (COM_FCheckExists(va(exts[2], server)))
Q_snprintfz (sv.modelname, sizeof(sv.modelname), exts[2], server);
}
sv.world.worldmodel = Mod_ForName (sv.modelname, true);
}
sv.state = ss_loading;
sv.world.worldmodel = Mod_ForName (sv.modelname, true);
if (!sv.world.worldmodel || sv.world.worldmodel->needload)
Sys_Error("%s is missing or corrupt\n", sv.modelname);
Sys_Error("\"%s\" is missing or corrupt\n", sv.modelname);
if (sv.world.worldmodel->type != mod_brush && sv.world.worldmodel->type != mod_heightmap)
Sys_Error("%s is not a bsp model\n", sv.modelname);
Sys_Error("\"%s\" is not a bsp model\n", sv.modelname);
sv.state = ss_dead;
#ifndef SERVERONLY

View File

@ -210,7 +210,7 @@ cvar_t hostname = CVARF("hostname","unnamed", CVAR_SERVERINFO);
cvar_t secure = CVARF("secure", "", CVAR_SERVERINFO);
extern cvar_t sv_nomsec;
extern cvar_t sv_nqplayerphysics;
char cvargroup_serverpermissions[] = "server permission variables";
char cvargroup_serverinfo[] = "serverinfo variables";
@ -807,7 +807,6 @@ int SV_CalcPing (client_t *cl, qboolean forcecalc)
float ping;
int i;
int count;
register client_frame_t *frame;
if (!cl->frameunion.frames)
return 0;
@ -817,7 +816,24 @@ int SV_CalcPing (client_t *cl, qboolean forcecalc)
case SCP_BAD:
break;
case SCP_QUAKE2:
break;
{
q2client_frame_t *frame;
ping = 0;
count = 0;
for (frame = cl->frameunion.q2frames, i=0 ; i<Q2UPDATE_BACKUP ; i++, frame++)
{
if (frame->ping_time > 0)
{
ping += frame->ping_time;
count++;
}
}
if (!count)
return 9999;
ping /= count;
}
return ping;
case SCP_QUAKE3:
break;
case SCP_DARKPLACES6:
@ -826,20 +842,22 @@ int SV_CalcPing (client_t *cl, qboolean forcecalc)
case SCP_PROQUAKE:
case SCP_FITZ666:
case SCP_QUAKEWORLD:
ping = 0;
count = 0;
for (frame = cl->frameunion.frames, i=0 ; i<UPDATE_BACKUP ; i++, frame++)
{
if (frame->ping_time > 0)
register client_frame_t *frame;
ping = 0;
count = 0;
for (frame = cl->frameunion.frames, i=0 ; i<UPDATE_BACKUP ; i++, frame++)
{
ping += frame->ping_time;
count++;
if (frame->ping_time > 0)
{
ping += frame->ping_time;
count++;
}
}
if (!count)
return 9999;
ping /= count;
}
if (!count)
return 9999;
ping /= count;
return ping*1000;
}
return 0;
@ -1662,7 +1680,7 @@ void SV_AcceptMessage(int protocol)
MSG_WriteByte(&sb, CCREP_ACCEPT);
NET_LocalAddressForRemote(svs.sockets, &net_from, &localaddr, 0);
MSG_WriteLong(&sb, ShortSwap(localaddr.port));
MSG_WriteByte(&sb, 1/*MOD_PROQUAKE*/);
MSG_WriteByte(&sb, (protocol==SCP_NETQUAKE)?0:1/*MOD_PROQUAKE*/);
MSG_WriteByte(&sb, 10 * 3.50/*MOD_PROQUAKE_VERSION*/);
*(int*)sb.data = BigLong(NETFLAG_CTL|sb.cursize);
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from);
@ -3441,9 +3459,7 @@ void SV_OpenRoute_f(void)
netadr_t to;
char data[64];
NET_StringToAdr(Cmd_Argv(1), &to);
if (!to.port)
to.port = PORT_QWCLIENT;
NET_StringToAdr(Cmd_Argv(1), PORT_QWCLIENT, &to);
sprintf(data, "\xff\xff\xff\xff%c", S2C_CONNECTION);
@ -3513,7 +3529,6 @@ qboolean SV_ReadPackets (float *delay)
SVNQ_ExecuteClientMessage(cl);
}
}
break;
}
else
{
@ -4343,7 +4358,7 @@ void SV_InitLocal (void)
Cvar_Register (&sv_csqcdebug, cvargroup_servercontrol);
Cvar_Register (&sv_gamespeed, cvargroup_serverphysics);
Cvar_Register (&sv_nomsec, cvargroup_serverphysics);
Cvar_Register (&sv_nqplayerphysics, cvargroup_serverphysics);
Cvar_Register (&pr_allowbutton1, cvargroup_servercontrol);
Cvar_Register (&pausable, cvargroup_servercontrol);
@ -4473,7 +4488,7 @@ void Master_Heartbeat (void)
if (!*sv_masterlist[i].cv.string)
sv_masterlist[i].adr.port = 0;
else if (!NET_StringToAdr(sv_masterlist[i].cv.string, &sv_masterlist[i].adr))
else if (!NET_StringToAdr(sv_masterlist[i].cv.string, 0, &sv_masterlist[i].adr))
{
sv_masterlist[i].adr.port = 0;
Con_Printf ("Couldn't resolve master \"%s\"\n", sv_masterlist[i].cv.string);

View File

@ -1601,8 +1601,6 @@ static qboolean SV_MVD_Record (mvddest_t *dest)
{ /*everything*/
demo.recorder.fteprotocolextensions = PEXT_CSQC | PEXT_COLOURMOD | PEXT_DPFLAGS | PEXT_CUSTOMTEMPEFFECTS | PEXT_ENTITYDBL | PEXT_ENTITYDBL2 | PEXT_FATNESS | PEXT_HEXEN2 | PEXT_HULLSIZE | PEXT_LIGHTSTYLECOL | PEXT_MODELDBL | PEXT_SCALE | PEXT_SETATTACHMENT | PEXT_SETVIEW | PEXT_SOUNDDBL | PEXT_SPAWNSTATIC2 | PEXT_TRANS | PEXT_VIEW2;
demo.recorder.fteprotocolextensions2 = PEXT2_VOICECHAT | PEXT2_SETANGLEDELTA | PEXT2_PRYDONCURSOR | PEXT2_REPLACEMENTDELTAS;
/*assume that all playback will be done with a valid csprogs that can correctly decode*/
demo.recorder.csqcactive = true;
/*enable these, because we might as well (stat ones are always useful)*/
demo.recorder.zquake_extensions = Z_EXT_PM_TYPE | Z_EXT_PM_TYPE_NEW | Z_EXT_VIEWHEIGHT | Z_EXT_SERVERTIME | Z_EXT_PITCHLIMITS | Z_EXT_JOIN_OBSERVE | Z_EXT_VWEP;
}
@ -1616,6 +1614,8 @@ static qboolean SV_MVD_Record (mvddest_t *dest)
//pointless extensions that are redundant with mvds
demo.recorder.fteprotocolextensions &= ~PEXT_ACCURATETIMINGS | PEXT_HLBSP|PEXT_Q2BSP|PEXT_Q3BSP;
/*assume that all playback will be done with a valid csprogs that can correctly decode*/
demo.recorder.csqcactive = (demo.recorder.fteprotocolextensions & PEXT_CSQC);
}
// else
// SV_WriteRecordMVDMessage(&buf, dem_read);

View File

@ -2041,6 +2041,7 @@ void World_Physics_Frame(world_t *w)
int i;
qboolean retouch;
wedict_t *ent;
extern cvar_t sv_nqplayerphysics;
w->framenum++;
@ -2085,8 +2086,32 @@ void World_Physics_Frame(world_t *w)
{
if (!svs.clients[i-1].isindependant)
{
WPhys_RunEntity (w, ent);
WPhys_RunNewmis (w);
if (sv_nqplayerphysics.ival || svs.clients[i-1].state < cs_spawned)
{
WPhys_RunEntity (w, ent);
WPhys_RunNewmis (w);
}
else
{
int newt;
int delt;
newt = sv.time*1000;
delt = newt - svs.clients[i-1].msecs;
if (delt > 1000/77 || delt < -10)
{
float ft = host_frametime;
host_client = &svs.clients[i-1];
sv_player = svs.clients[i-1].edict;
svs.clients[i-1].msecs = newt;
SV_PreRunCmd();
svs.clients[i-1].last_check = 0;
svs.clients[i-1].lastcmd.msec = bound(0, delt, 255);
SV_RunCmd (&svs.clients[i-1].lastcmd, true);
svs.clients[i-1].lastcmd.impulse = 0;
SV_PostRunCmd();
*w->g.frametime = host_frametime = ft;
}
}
}
// else
// World_LinkEdict(w, (wedict_t*)ent, true);

View File

@ -1229,7 +1229,10 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
{
MSG_WriteByte (msg, svc_time);
MSG_WriteFloat(msg, sv.world.physicstime);
client->nextservertimeupdate = sv.world.physicstime;
if (client->fteprotocolextensions2 & PEXT2_PREDINFO)
MSG_WriteLong(msg, client->last_sequence);
// Con_Printf("%f\n", sv.world.physicstime);
}
@ -1620,6 +1623,12 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf
else
statsi[STAT_VIEWZOOM] = ent->xv->viewzoom*255;
if (client->fteprotocolextensions2 & PEXT2_PREDINFO)
{
statsf[STAT_MOVEVARS_GRAVITY] = sv_gravity.value;
statsf[STAT_MOVEVARS_ENTGRAVITY] = host_client->entgravity;
statsf[STAT_MOVEVARS_MAXSPEED] = host_client->maxspeed;
}
if (client->protocol == SCP_DARKPLACES7)
{
/*note: statsf is truncated, which would mess things up*/
@ -1637,7 +1646,7 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf
statsfi[STAT_MOVEVARS_AIRACCELERATE] = sv_airaccelerate.value;
statsfi[STAT_MOVEVARS_WATERACCELERATE] = sv_wateraccelerate.value;
statsfi[STAT_MOVEVARS_ENTGRAVITY] = host_client->entgravity;
statsfi[STAT_MOVEVARS_JUMPVELOCITY] = 280;//sv_jumpvelocity.value; //bah
statsfi[STAT_MOVEVARS_JUMPVELOCITY] = 270;//sv_jumpvelocity.value; //bah
statsfi[STAT_MOVEVARS_EDGEFRICTION] = sv_edgefriction.value;
statsfi[STAT_MOVEVARS_MAXAIRSPEED] = host_client->maxspeed;
statsfi[STAT_MOVEVARS_STEPHEIGHT] = 18;
@ -2400,7 +2409,7 @@ void SV_SendClientMessages (void)
}
else
{
if (c->nextservertimeupdate > pt + 0.5*2)
if (c->nextservertimeupdate > pt + 0.1)
c->nextservertimeupdate = 0;
c->netchan.nqunreliableonly = false;
@ -2409,7 +2418,7 @@ void SV_SendClientMessages (void)
if (c->nextservertimeupdate < pt && c->state != cs_zombie)
{
c->send_message = true;
c->nextservertimeupdate = pt;
c->nextservertimeupdate = pt + 1.0/77;
}
}
}

View File

@ -58,11 +58,11 @@ cvar_t cmd_allowaccess = SCVAR("cmd_allowaccess", "0"); //set to 1 to allow cmd
cvar_t cmd_gamecodelevel = SCVAR("cmd_gamecodelevel", "50"); //execution level which gamecode is told about (for unrecognised commands)
cvar_t sv_pure = CVARFD("sv_pure", "", CVAR_SERVERINFO, "The most evil cvar in the world.");
cvar_t sv_nomsec = CVARD("sv_nomsec", "0", "Ignore client msec times, runs using NQ physics instead.");
cvar_t sv_nqplayerphysics = CVARAD("sv_nqplayerphysics", "0", "sv_nomsec", "Disregard player prediction and run NQ-style player physics instead. This can be used for compatibility with mods that expect exact behaviour.");
cvar_t sv_edgefriction = CVARAF("sv_edgefriction", "2",
"edgefriction", 0);
cvar_t sv_brokenmovetypes = CVARD("sv_brokenmovetypes", "0", "Emulate standard quakeworld movetypes. Shouldn't be used for any games other than QuakeWorld.");
cvar_t sv_brokenmovetypes = CVARD("sv_brokenmovetypes", "0", "Emulate vanilla quakeworld by forcing MOVETYPE_WALK on all players. Shouldn't be used for any games other than QuakeWorld.");
cvar_t sv_chatfilter = CVAR("sv_chatfilter", "0");
@ -416,8 +416,6 @@ void SV_New_f (void)
host_client->prespawn_idx = 0;
}
#define GAME_DEATHMATCH 0
#define GAME_COOP 1
void SVNQ_New_f (void)
{
extern cvar_t coop;
@ -998,6 +996,7 @@ void SV_SendClientPrespawnInfo(client_t *client)
client->prespawn_idx |= 0x80000000;
}
}
if (client->prespawn_stage == PRESPAWN_MODELLIST)
{
started = false;
@ -4350,9 +4349,9 @@ void Cmd_FPSList_f(void)
}
if (frames)
SV_ClientPrintf(host_client, PRINT_HIGH, "%s: %gfps (min%g max %g), in: %ibps, out: %ibps\n", cl->name, ftime/frames, minf, maxf, (int)cl->inrate, (int)cl->outrate);
SV_ClientPrintf(host_client, PRINT_HIGH, "%s: %gfps (min%g max %g), c2s: %ibps, s2c: %ibps\n", cl->name, ftime/frames, minf, maxf, (int)cl->inrate, (int)cl->outrate);
else
SV_ClientPrintf(host_client, PRINT_HIGH, "%s: unknown framerate, in: %ibps, out: %ibps\n", cl->name, (int)cl->inrate, (int)cl->outrate);
SV_ClientPrintf(host_client, PRINT_HIGH, "%s: unknown framerate, c2s: %ibps, s2c: %ibps\n", cl->name, (int)cl->inrate, (int)cl->outrate);
}
}
@ -5363,9 +5362,6 @@ int SV_PMTypeForClient (client_t *cl)
}
#endif
if (!cl->isindependant)
return PM_NONE;
if (sv_brokenmovetypes.value) //this is to mimic standard qw servers, which don't support movetypes other than MOVETYPE_FLY.
{ //it prevents bugs from being visible in unsuspecting mods.
if (cl->spectator)
@ -5442,6 +5438,11 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
// To prevent a infinite loop
if (!recurse)
{
if (!host_client->last_check)
{
host_client->msecs = 0;
host_client->last_check = realtime;
}
host_client->msecs += ucmd->msec;
if ((tmp_time = realtime - host_client->last_check) >= sv_cheatspeedchecktime.value)
@ -5613,7 +5614,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
}
if (SV_PlayerPhysicsQC && !host_client->spectator)
{ //csqc independant physics support
{ //player movement tweaks that fuck over player prediction.
pr_global_struct->frametime = host_frametime;
pr_global_struct->time = sv.time;
WPhys_RunEntity(&sv.world, (wedict_t*)sv_player);
@ -6296,7 +6297,7 @@ haveannothergo:
#endif
if (!sv.paused)
{
if (sv_nomsec.ival)
if (sv_nqplayerphysics.ival)
{
cl->isindependant = false;
if (!sv_player->v->fixangle)
@ -6465,6 +6466,24 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
// calc ping time
frame = &cl->frameunion.q2frames[cl->netchan.incoming_acknowledged & Q2UPDATE_MASK];
if (frame->senttime != -1)
{
int ping_time = realtime*1000 - frame->senttime; //no more phenomanally low pings please
if (ping_time > sv_minping.value+1)
{
cl->delay -= 0.001;
if (cl->delay < 0)
cl->delay = 0;
}
if (ping_time < sv_minping.value)
{
cl->delay += 0.001;
if (cl->delay > 1)
cl->delay = 1;
}
frame->senttime = -1;
frame->ping_time = ping_time;
}
// make sure the reply sequence number matches the incoming
// sequence number
@ -6474,8 +6493,8 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
cl->send_message = false; // don't reply, sequences have slipped
// save time for ping calculations
cl->frameunion.q2frames[cl->netchan.outgoing_sequence & Q2UPDATE_MASK].senttime = realtime;
// cl->q2frames[cl->netchan.outgoing_sequence & UPDATE_MASK].ping_time = -1;
cl->frameunion.q2frames[cl->netchan.outgoing_sequence & Q2UPDATE_MASK].senttime = realtime*1000;
cl->frameunion.q2frames[cl->netchan.outgoing_sequence & Q2UPDATE_MASK].ping_time = -1;
host_client = cl;
sv_player = host_client->edict;
@ -6520,7 +6539,8 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
lastframe = MSG_ReadLong();
if (lastframe != host_client->delta_sequence) {
if (lastframe != host_client->delta_sequence)
{
cl->delta_sequence = lastframe;
}
@ -6616,7 +6636,7 @@ void SVNQ_ReadClientMove (usercmd_t *move)
frame = &host_client->frameunion.frames[host_client->netchan.incoming_acknowledged & UPDATE_MASK];
if (host_client->protocol == SCP_DARKPLACES7)
if (host_client->protocol == SCP_DARKPLACES7 || (host_client->fteprotocolextensions2 & PEXT2_PREDINFO))
host_client->last_sequence = MSG_ReadLong ();
else
host_client->last_sequence = 0;
@ -6665,11 +6685,11 @@ void SVNQ_ReadClientMove (usercmd_t *move)
move->sidemove = MSG_ReadShort ();
move->upmove = MSG_ReadShort ();
move->msec=timesincelast*1000;
move->msec=bound(0, timesincelast*1000, 255);
frame->move_msecs = timesincelast*1000;
// read buttons
if (host_client->protocol == SCP_DARKPLACES6 || host_client->protocol == SCP_DARKPLACES7)
if (host_client->protocol == SCP_DARKPLACES6 || host_client->protocol == SCP_DARKPLACES7 || (host_client->fteprotocolextensions2 & PEXT2_PRYDONCURSOR))
bits = MSG_ReadLong();
else
bits = MSG_ReadByte ();
@ -6679,7 +6699,7 @@ void SVNQ_ReadClientMove (usercmd_t *move)
if (i)
move->impulse = i;
if (host_client->protocol == SCP_DARKPLACES6 || host_client->protocol == SCP_DARKPLACES7)
if (host_client->protocol == SCP_DARKPLACES6 || host_client->protocol == SCP_DARKPLACES7 || (host_client->fteprotocolextensions2 & PEXT2_PRYDONCURSOR))
{
SV_ReadPrydonCursor();
}
@ -6702,8 +6722,8 @@ void SVNQ_ReadClientMove (usercmd_t *move)
}
if (i && SV_FilterImpulse(i, host_client->trustlevel))
host_client->edict->v->impulse = i;
// if (i && SV_FilterImpulse(i, host_client->trustlevel))
// host_client->edict->v->impulse = i;
host_client->edict->v->button0 = bits & 1;
host_client->edict->v->button2 = (bits >> 1) & 1;
@ -6720,8 +6740,11 @@ void SVNQ_ReadClientMove (usercmd_t *move)
if (host_client->last_sequence)
{
host_frametime = timesincelast;
WPhys_RunEntity(&sv.world, (wedict_t*)host_client->edict);
host_client->isindependant = true;
SV_PreRunCmd();
SV_RunCmd (move, true);
SV_PostRunCmd();
}
else
host_client->isindependant = false;

View File

@ -634,7 +634,7 @@ void SVQ2_BuildClientFrame (client_t *client)
// this is the frame we are creating
frame = &client->frameunion.q2frames[sv.framenum & Q2UPDATE_MASK];
frame->senttime = realtime; // save it for ping calc later
frame->senttime = realtime*1000; // save it for ping calc later
// find the client's PVS
for (i=0 ; i<3 ; i++)