Add all the junk for network compat with Q2E.
Defaults to using Q2E's protocol 2023 (but not netchan). FTEQ2 servers can host both vanilla and Q2E clients simultaneously, but its recommend to use the vanilla gamecode to avoid localisation issues.
This commit is contained in:
parent
3708dab87a
commit
d781018df3
49 changed files with 3887 additions and 1046 deletions
|
@ -524,6 +524,8 @@ qboolean CL_GetDemoMessage (void)
|
|||
{
|
||||
endofdemo = false;
|
||||
CL_StopPlayback ();
|
||||
|
||||
CL_NextDemo();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2047,9 +2049,19 @@ void CL_Record_f (void)
|
|||
}
|
||||
MSG_WriteLong (&buf, cls.protocol_q2);
|
||||
MSG_WriteLong (&buf, 0x80000000 + cl.servercount);
|
||||
MSG_WriteByte (&buf, 1);
|
||||
MSG_WriteByte (&buf, 1); //attract loop
|
||||
if (cls.protocol_q2 == PROTOCOL_VERSION_Q2EX)
|
||||
MSG_WriteByte (&buf, cl.q2svnetrate); //tick rate
|
||||
MSG_WriteString (&buf, gamedirfile);
|
||||
MSG_WriteShort (&buf, cl.playerview[0].playernum);
|
||||
if (cls.protocol_q2 == PROTOCOL_VERSION_Q2EX && cl.playerview[0].playernum != -1 && cl.splitclients!=1)
|
||||
{
|
||||
MSG_WriteShort (&buf, -2);
|
||||
MSG_WriteShort (&buf, cl.splitclients);
|
||||
for (i = 0; i < cl.splitclients; i++)
|
||||
MSG_WriteShort (&buf, cl.playerview[i].playernum);
|
||||
}
|
||||
else
|
||||
MSG_WriteShort (&buf, cl.playerview[0].playernum);
|
||||
MSG_WriteString (&buf, cl.levelname);
|
||||
|
||||
for (i = 0; i < Q2MAX_CONFIGSTRINGS; i++)
|
||||
|
|
|
@ -5658,15 +5658,21 @@ void CL_LinkViewModel(void)
|
|||
#ifdef Q2CLIENT
|
||||
if (cls.protocol == CP_QUAKE2)
|
||||
{
|
||||
//generate root matrix..
|
||||
VectorCopy(pv->simorg, r_refdef.weaponmatrix[3]);
|
||||
AngleVectors(pv->simangles, r_refdef.weaponmatrix[0], r_refdef.weaponmatrix[1], r_refdef.weaponmatrix[2]);
|
||||
VectorInverse(r_refdef.weaponmatrix[1]);
|
||||
memcpy(r_refdef.weaponmatrix_bob, r_refdef.weaponmatrix, sizeof(r_refdef.weaponmatrix_bob));
|
||||
|
||||
V_ClearEntity(&ent);
|
||||
ent.model = pv->vm.oldmodel;
|
||||
|
||||
ent.framestate.g[FS_REG].frame[0] = pv->vm.prevframe;
|
||||
ent.framestate.g[FS_REG].frame[1] = pv->vm.oldframe;
|
||||
ent.framestate.g[FS_REG].frametime[0] = pv->vm.lerptime;
|
||||
ent.framestate.g[FS_REG].frametime[1] = pv->vm.oldlerptime;
|
||||
ent.framestate.g[FS_REG].lerpweight[0] = 1 - cl.lerpfrac;
|
||||
ent.framestate.g[FS_REG].lerpweight[1] = cl.lerpfrac;
|
||||
ent.framestate.g[FS_REG].frametime[0] = cl.time-pv->vm.lerptime;
|
||||
ent.framestate.g[FS_REG].frametime[1] = cl.time-pv->vm.oldlerptime;
|
||||
ent.framestate.g[FS_REG].lerpweight[0] = (cl.time - pv->vm.lerptime)*10;
|
||||
ent.framestate.g[FS_REG].lerpweight[1] = 1 - ent.framestate.g[FS_REG].lerpweight[0];
|
||||
|
||||
ent.flags |= RF_WEAPONMODEL|RF_DEPTHHACK|RF_NOSHADOW;
|
||||
if (pv->handedness == 1)
|
||||
|
@ -5674,6 +5680,9 @@ void CL_LinkViewModel(void)
|
|||
else if (pv->handedness == 2)
|
||||
return;
|
||||
|
||||
ent.shaderRGBAf[0] = ent.shaderRGBAf[1] = ent.shaderRGBAf[2] = 1;
|
||||
ent.shaderRGBAf[3] = bound(0, r_drawviewmodel.value, 1);
|
||||
|
||||
V_AddEntity (&ent);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -852,7 +852,7 @@ qboolean IN_DrawWeaponWheel(int pnum)
|
|||
Draw_FunString(pos[0], pos[1], "X");
|
||||
return true;
|
||||
}
|
||||
static void IN_WWheelDown (void)
|
||||
void IN_WWheelDown (void)
|
||||
{
|
||||
#ifdef CSQC_DAT
|
||||
int pnum = CL_TargettedSplit(false);
|
||||
|
@ -877,7 +877,7 @@ static void IN_WWheelDown (void)
|
|||
}
|
||||
KeyDown(&in_wwheel, NULL);
|
||||
}
|
||||
static void IN_WWheelUp (void)
|
||||
void IN_WWheelUp (void)
|
||||
{
|
||||
int pnum = CL_TargettedSplit(false);
|
||||
#ifdef CSQC_DAT
|
||||
|
@ -889,12 +889,29 @@ static void IN_WWheelUp (void)
|
|||
if (wwheelsel[pnum] < weaponinfo_count)
|
||||
CL_QueueImpulse(pnum, weaponinfo[wwheelsel[pnum]].impulse);
|
||||
}
|
||||
void IN_IWheelDown (void)
|
||||
{
|
||||
}
|
||||
void IN_IWheelUp (void)
|
||||
{
|
||||
}
|
||||
#else
|
||||
#define IN_DoPostSelect()
|
||||
#define IN_DoWeaponHide()
|
||||
#endif
|
||||
|
||||
|
||||
//q2e compat. too lazy to use the wwheel info. let the gamecode do it the old way.
|
||||
void IN_WeapNext_f (void)
|
||||
{
|
||||
CL_SendClientCommand(true, "weapnext");
|
||||
}
|
||||
void IN_WeapPrev_f (void)
|
||||
{
|
||||
CL_SendClientCommand(true, "weapprev");
|
||||
}
|
||||
|
||||
|
||||
static void IN_KLookDown (void) {KeyDown(&in_klook, NULL);}
|
||||
static void IN_KLookUp (void) {KeyUp(&in_klook);}
|
||||
static void IN_MLookDown (void) {KeyDown(&in_mlook, NULL);}
|
||||
|
@ -1179,8 +1196,8 @@ cvar_t cl_pitchspeed = CVAR("cl_pitchspeed","150");
|
|||
cvar_t cl_anglespeedkey = CVAR("cl_anglespeedkey","1.5");
|
||||
|
||||
|
||||
#define GATHERBIT(bname,bit) if (bname.state[pnum] & 3) {bits |= (1u<<(bit));} bname.state[pnum] &= ~2;
|
||||
#define UNUSEDBUTTON(bnum) if (in_button[bnum].state[pnum] & 3) {Con_Printf("+button%i is not supported on this protocol\n", bnum); } in_button[bnum].state[pnum] &= ~3;
|
||||
#define GATHERBIT(bname,bit) do{if (bname.state[pnum] & 3) {bits |= (1u<<(bit));} bname.state[pnum] &= ~2;}while(0)
|
||||
#define UNUSEDBUTTON(bnum) do{if (in_button[bnum].state[pnum] & 3) {Con_Printf("+button%i is not supported on this protocol\n", bnum); } in_button[bnum].state[pnum] &= ~3;}while(0)
|
||||
void CL_GatherButtons (usercmd_t *cmd, int pnum)
|
||||
{
|
||||
unsigned int bits = 0;
|
||||
|
@ -1200,6 +1217,47 @@ void CL_GatherButtons (usercmd_t *cmd, int pnum)
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef Q2CLIENT
|
||||
if (cls.protocol==CP_QUAKE2 && cls.protocol_q2 == PROTOCOL_VERSION_Q2EX)
|
||||
{ //buttons limited to 8 bits.
|
||||
|
||||
//GATHERBIT(in_attack, 0); //handled above
|
||||
GATHERBIT(in_use, 1);
|
||||
//GATHERBIT(in_holster, 2); //urgh
|
||||
//GATHERBIT(in_jump, 3); //also set by +moveup
|
||||
//GATHERBIT(in_crouch, 4); //also set by +movedown
|
||||
//GATHERBIT(in_unused, 5);
|
||||
//GATHERBIT(in_unused, 6);
|
||||
//GATHERBIT(in_any, 7); //urgh
|
||||
|
||||
//also let +button stuff map to bits.
|
||||
GATHERBIT(in_button[0], 0);
|
||||
GATHERBIT(in_button[1], 1);
|
||||
GATHERBIT(in_button[2], 2);
|
||||
GATHERBIT(in_button[3], 3);
|
||||
GATHERBIT(in_button[4], 4);
|
||||
GATHERBIT(in_button[5], 5);
|
||||
GATHERBIT(in_button[6], 6);
|
||||
GATHERBIT(in_button[7], 7);
|
||||
|
||||
UNUSEDBUTTON(8);
|
||||
UNUSEDBUTTON(9);
|
||||
UNUSEDBUTTON(10);
|
||||
UNUSEDBUTTON(11);
|
||||
UNUSEDBUTTON(12);
|
||||
UNUSEDBUTTON(13);
|
||||
UNUSEDBUTTON(14);
|
||||
UNUSEDBUTTON(15);
|
||||
UNUSEDBUTTON(16);
|
||||
UNUSEDBUTTON(17);
|
||||
UNUSEDBUTTON(18);
|
||||
UNUSEDBUTTON(19);
|
||||
// UNUSEDBUTTON(20);
|
||||
|
||||
cmd->buttons |= bits;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
//quakec's numbered buttons make no sense and have no sane relation to bit numbers
|
||||
GATHERBIT(in_button[0], 0);
|
||||
|
@ -1562,7 +1620,7 @@ void CL_ClampPitch (int pnum, float frametime)
|
|||
if (cls.protocol == CP_QUAKE2)
|
||||
{
|
||||
float pitch;
|
||||
pitch = SHORT2ANGLE(cl.q2frame.playerstate[pnum].pmove.delta_angles[PITCH]);
|
||||
pitch = SHORT2ANGLE(cl.q2frame.seat[pnum].playerstate.pmove.delta_angles[PITCH]);
|
||||
if (pitch > 180)
|
||||
pitch -= 360;
|
||||
|
||||
|
@ -2365,17 +2423,31 @@ qboolean CLQ2_SendCmd (sizebuf_t *buf)
|
|||
if (cmd->msec > 100)
|
||||
cmd->msec = 100;
|
||||
|
||||
MSG_WriteByte (buf, clcq2_move);
|
||||
if (cls.protocol_q2 == PROTOCOL_VERSION_Q2EX)
|
||||
{ //checksum byte got switched around to something that doesn't include so much sequence info. not really sure why.
|
||||
if (!seat)
|
||||
{
|
||||
MSG_WriteByte (buf, clcq2_move);
|
||||
if (!cl.q2frame.valid || cl_nodelta.ival || (cls.demorecording && !cls.demohadkeyframe))
|
||||
MSG_WriteLong (buf, -1); // no compression
|
||||
else
|
||||
MSG_WriteLong (buf, cl.q2frame.serverframe);
|
||||
}
|
||||
|
||||
if (seat)
|
||||
checksumIndex = buf->cursize;
|
||||
MSG_WriteByte (buf, 0); //each seat has its own individual checksum for some reason (but no extra clcq2_move - player counts are not dynamic).
|
||||
}
|
||||
else if (seat)
|
||||
{
|
||||
//multi-seat still has an extra clc_move per seat
|
||||
//but no checksum (pointless when its opensource anyway)
|
||||
//no sequence (only seat 0 reports that)
|
||||
MSG_WriteByte (buf, clcq2_move);
|
||||
checksumIndex = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteByte (buf, clcq2_move);
|
||||
// save the position for a checksum qbyte
|
||||
if (cls.protocol_q2 == PROTOCOL_VERSION_R1Q2 || cls.protocol_q2 == PROTOCOL_VERSION_Q2PRO)
|
||||
checksumIndex = -1;
|
||||
|
@ -2404,6 +2476,18 @@ qboolean CLQ2_SendCmd (sizebuf_t *buf)
|
|||
cl.outframes[i].senttime = realtime;
|
||||
cl.outframes[i].latency = -1;
|
||||
|
||||
if (cls.protocol_q2 == PROTOCOL_VERSION_Q2EX)
|
||||
{
|
||||
if (cmd->upmove >= 100)
|
||||
cmd->buttons |= 1<<3; //jump
|
||||
else if (cmd->upmove <= -100)
|
||||
cmd->buttons |= 1<<4; //crouch
|
||||
}
|
||||
else
|
||||
{
|
||||
if (in_jump.state[seat]&3 && cmd->upmove==0)
|
||||
cmd->upmove = 200;
|
||||
}
|
||||
if (cmd->buttons)
|
||||
cmd->buttons |= 128; //fixme: this isn't really what's meant by the anykey.
|
||||
|
||||
|
@ -2593,7 +2677,16 @@ static void CL_SendUserinfoUpdate(void)
|
|||
{
|
||||
char userinfo[2048];
|
||||
InfoSync_Strip(&cls.userinfosync, info); //can't track this stuff. all or nothing.
|
||||
if (info == &cls.userinfo[0])
|
||||
|
||||
if (cls.protocol_q2 == PROTOCOL_VERSION_Q2EX)
|
||||
{
|
||||
extern size_t Q2EX_UserInfoToString(char *infostring, size_t maxsize, const char **ignore, int seats);
|
||||
Q2EX_UserInfoToString(userinfo, sizeof(userinfo), NULL, cl.splitclients);
|
||||
|
||||
MSG_WriteByte (&cls.netchan.message, clcq2_userinfo);
|
||||
MSG_WriteString (&cls.netchan.message, userinfo+(*userinfo=='\\'?1:0));
|
||||
}
|
||||
else if (info == &cls.userinfo[0])
|
||||
{
|
||||
InfoBuf_ToString(info, userinfo, sizeof(userinfo), NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
|
@ -2641,7 +2734,11 @@ static void CL_SendUserinfoUpdate(void)
|
|||
MSG_WriteByte (&cls.netchan.message, seat);
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteByte (&cls.netchan.message, (cls.protocol == CP_QUAKE2)?clcq2_stringcmd:clc_stringcmd);
|
||||
if (cls.protocol_q2 == PROTOCOL_VERSION_Q2EX)
|
||||
MSG_WriteByte (&cls.netchan.message, 1+seat);
|
||||
}
|
||||
MSG_WriteString (&cls.netchan.message, s);
|
||||
}
|
||||
|
||||
|
@ -2891,7 +2988,12 @@ void CL_SendCmd (double frametime, qboolean mainloop)
|
|||
break;
|
||||
if (!strncmp(clientcmdlist->command, "spawn", 5) && cls.userinfosync.numkeys && cl.haveserverinfo)
|
||||
break; //HACK: don't send the spawn until all pending userinfos have been flushed.
|
||||
if (clientcmdlist->seat && (cls.fteprotocolextensions&PEXT_SPLITSCREEN))
|
||||
if (cls.protocol==CP_QUAKE2 && cls.protocol_q2==PROTOCOL_VERSION_Q2EX)
|
||||
{
|
||||
MSG_WriteByte (&cls.netchan.message, clcq2_stringcmd);
|
||||
MSG_WriteByte (&cls.netchan.message, clientcmdlist->seat+1);
|
||||
}
|
||||
else if (clientcmdlist->seat && (cls.fteprotocolextensions&PEXT_SPLITSCREEN))
|
||||
{
|
||||
MSG_WriteByte (&cls.netchan.message, clcfte_stringcmd_seat);
|
||||
MSG_WriteByte (&cls.netchan.message, clientcmdlist->seat);
|
||||
|
|
|
@ -626,6 +626,58 @@ static void CL_ConnectAbort(const char *format, ...)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
size_t Q2EX_UserInfoToString(char *infostring, size_t maxsize, const char **ignore, int seats)
|
||||
{ //infoblobs are not a thing here. don't need to maintain sync objects - can't really do anything with them anyway.
|
||||
size_t k, r = 1, l;
|
||||
char *o = infostring;
|
||||
char *e = infostring?infostring + maxsize-1:infostring;
|
||||
int s;
|
||||
|
||||
for (s = 0; s < seats; s++)
|
||||
{
|
||||
char *pf = s?va("_%i", s):"";
|
||||
size_t pfl = strlen(pf);
|
||||
infobuf_t *info = &cls.userinfo[s];
|
||||
for (k = 0; k < info->numkeys; k++)
|
||||
{
|
||||
if (ignore)
|
||||
{
|
||||
for (l = 0; ignore[l]; l++)
|
||||
{
|
||||
if (!strcmp(ignore[l], info->keys[k].name))
|
||||
break;
|
||||
else if (ignore[l][0] == '*' && !ignore[l][1] && *info->keys[k].name == '*')
|
||||
break; //read-only
|
||||
else if (ignore[l][0] == '_' && !ignore[l][1] && *info->keys[k].name == '_')
|
||||
break; //comment
|
||||
}
|
||||
if (ignore[l])
|
||||
continue; //ignore when in the list
|
||||
}
|
||||
|
||||
if (!info->keys[k].large) //lower priorities don't bother with extended blocks. be sure to prioritise them explicitly. they'd just bug stuff out.
|
||||
{
|
||||
size_t knl = strlen(info->keys[k].name);
|
||||
size_t kvl = info->keys[k].size;
|
||||
r+= 1+knl+pfl+1+kvl;
|
||||
if (o + 1+knl+1+kvl >= e)
|
||||
continue;
|
||||
o[0] = '\\';
|
||||
memcpy(o+1, info->keys[k].name, knl);
|
||||
memcpy(o+1+knl, pf, pfl);
|
||||
o[1+knl+pfl] = '\\';
|
||||
memcpy(o+1+knl+pfl+1, info->keys[k].value, kvl);
|
||||
o[1+knl+pfl+1+kvl] = 0;
|
||||
|
||||
o += 1+knl+pfl+1+kvl;
|
||||
}
|
||||
}
|
||||
}
|
||||
*o = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
=======================
|
||||
CL_SendConnectPacket
|
||||
|
@ -748,39 +800,78 @@ static void CL_SendConnectPacket (netadr_t *to)
|
|||
}
|
||||
#endif
|
||||
|
||||
Q_snprintfz(data, sizeof(data), "%c%c%c%cconnect", 255, 255, 255, 255);
|
||||
|
||||
Q_strncatz(data, va(" %i %i %i", connectinfo.subprotocol, connectinfo.qport, connectinfo.challenge), sizeof(data));
|
||||
|
||||
//userinfo0 has some twiddles for extensions from other qw engines.
|
||||
Q_strncatz(data, " \"", sizeof(data));
|
||||
//qwfwd proxy routing
|
||||
if ((a = strrchr(cls.servername, '@')))
|
||||
if (connectinfo.subprotocol == PROTOCOL_VERSION_Q2EX)
|
||||
{
|
||||
*a = 0;
|
||||
Q_strncatz(data, va("\\prx\\%s", cls.servername), sizeof(data));
|
||||
*a = '@';
|
||||
size_t foo;
|
||||
int seats = bound(1, cl_splitscreen.ival+1, MAX_SPLITS), i;
|
||||
Q_snprintfz(data, sizeof(data), "%c%c%c%cconnect", 255, 255, 255, 255);
|
||||
|
||||
//qport+challenge were removed.
|
||||
Q_strncatz(data, va(" %i %i", connectinfo.subprotocol, seats), sizeof(data));
|
||||
|
||||
//socials...
|
||||
for (i = 0; i < seats; i++)
|
||||
{
|
||||
Q_strncatz(data, va(" anon"), sizeof(data));
|
||||
|
||||
//also make sure they have a valid name field, Q2E kinda bugs out otherwise.
|
||||
if (!InfoBuf_FindKey(&cls.userinfo[i], "name", &foo))
|
||||
InfoBuf_SetValueForKey(&cls.userinfo[i], "name", va("%s-%i", name.string, i+1));
|
||||
if (!InfoBuf_FindKey(&cls.userinfo[i], "fov", &foo))
|
||||
InfoBuf_SetValueForKey(&cls.userinfo[i], "fov", scr_fov.string);
|
||||
}
|
||||
|
||||
Q_strncatz(data, " \"", sizeof(data));
|
||||
//note: this specific info string should lack the leading \\ char.
|
||||
Q_strncatz(data, va("qport\\%i", connectinfo.qport), sizeof(data)); //just in case a server enforces it (ie: someone connecting directly raw udp without the lobby junk)
|
||||
Q_strncatz(data, va("\\challenge\\%i", connectinfo.challenge), sizeof(data)); //just in case a server enforces it (ie: someone connecting directly raw udp without the lobby junk)
|
||||
if (connectinfo.spec==CIS_OBSERVE)
|
||||
Q_strncatz(data, "\\spectator\\1", sizeof(data));
|
||||
|
||||
{
|
||||
const char *ignorekeys[] = {"prx", "*z_ext", (connectinfo.spec!=CIS_DEFAULT)?"spectator":NULL, NULL};
|
||||
Q2EX_UserInfoToString(data+strlen(data), sizeof(data)-strlen(data), ignorekeys, seats);
|
||||
}
|
||||
Q_strncatz(data, "\"", sizeof(data));
|
||||
Q_strncatz(data, "\n", sizeof(data));
|
||||
|
||||
connectinfo.ext.fte1 = connectinfo.ext.fte2 = connectinfo.ext.ez1 = 0;
|
||||
}
|
||||
if (connectinfo.spec==CIS_OBSERVE)
|
||||
Q_strncatz(data, "\\spectator\\1", sizeof(data));
|
||||
//the info itself
|
||||
else
|
||||
{
|
||||
static const char *prioritykeys[] = {"name", "password", "spectator", "lang", "rate", "team", "topcolor", "bottomcolor", "skin", "_", "*", NULL};
|
||||
const char *ignorekeys[] = {"prx", "*z_ext", (connectinfo.spec!=CIS_DEFAULT)?"spectator":NULL, NULL};
|
||||
InfoBuf_ToString(&cls.userinfo[0], data+strlen(data), sizeof(data)-strlen(data), prioritykeys, ignorekeys, NULL, &cls.userinfosync, &cls.userinfo[0]);
|
||||
Q_snprintfz(data, sizeof(data), "%c%c%c%cconnect", 255, 255, 255, 255);
|
||||
|
||||
Q_strncatz(data, va(" %i %i %i", connectinfo.subprotocol, connectinfo.qport, connectinfo.challenge), sizeof(data));
|
||||
|
||||
//userinfo0 has some twiddles for extensions from other qw engines.
|
||||
Q_strncatz(data, " \"", sizeof(data));
|
||||
//qwfwd proxy routing
|
||||
if ((a = strrchr(cls.servername, '@')))
|
||||
{
|
||||
*a = 0;
|
||||
Q_strncatz(data, va("\\prx\\%s", cls.servername), sizeof(data));
|
||||
*a = '@';
|
||||
}
|
||||
if (connectinfo.spec==CIS_OBSERVE)
|
||||
Q_strncatz(data, "\\spectator\\1", sizeof(data));
|
||||
//the info itself
|
||||
{
|
||||
static const char *prioritykeys[] = {"name", "password", "spectator", "lang", "rate", "team", "topcolor", "bottomcolor", "skin", "_", "*", NULL};
|
||||
const char *ignorekeys[] = {"prx", "*z_ext", (connectinfo.spec!=CIS_DEFAULT)?"spectator":NULL, NULL};
|
||||
InfoBuf_ToString(&cls.userinfo[0], data+strlen(data), sizeof(data)-strlen(data), prioritykeys, ignorekeys, NULL, &cls.userinfosync, &cls.userinfo[0]);
|
||||
}
|
||||
if (connectinfo.protocol == CP_QUAKEWORLD) //zquake extension info.
|
||||
Q_strncatz(data, va("\\*z_ext\\%i", CLIENT_SUPPORTED_Z_EXTENSIONS), sizeof(data));
|
||||
|
||||
Q_strncatz(data, "\"", sizeof(data));
|
||||
|
||||
if (connectinfo.protocol == CP_QUAKE2 && connectinfo.subprotocol == PROTOCOL_VERSION_R1Q2)
|
||||
Q_strncatz(data, va(" %d %d", connectinfo.ext.mtu, 1905), sizeof(data)); //mti, sub-sub-version
|
||||
else if (connectinfo.protocol == CP_QUAKE2 && connectinfo.subprotocol == PROTOCOL_VERSION_Q2PRO)
|
||||
Q_strncatz(data, va(" %d 0 0 %d", connectinfo.ext.mtu, 1021), sizeof(data)); //mtu, netchan-fragmentation, zlib, sub-sub-version
|
||||
|
||||
Q_strncatz(data, "\n", sizeof(data));
|
||||
}
|
||||
if (connectinfo.protocol == CP_QUAKEWORLD) //zquake extension info.
|
||||
Q_strncatz(data, va("\\*z_ext\\%i", CLIENT_SUPPORTED_Z_EXTENSIONS), sizeof(data));
|
||||
|
||||
Q_strncatz(data, "\"", sizeof(data));
|
||||
|
||||
if (connectinfo.protocol == CP_QUAKE2 && connectinfo.subprotocol == PROTOCOL_VERSION_R1Q2)
|
||||
Q_strncatz(data, va(" %d %d", connectinfo.ext.mtu, 1905), sizeof(data)); //mti, sub-sub-version
|
||||
else if (connectinfo.protocol == CP_QUAKE2 && connectinfo.subprotocol == PROTOCOL_VERSION_Q2PRO)
|
||||
Q_strncatz(data, va(" %d 0 0 %d", connectinfo.ext.mtu, 1021), sizeof(data)); //mtu, netchan-fragmentation, zlib, sub-sub-version
|
||||
|
||||
Q_strncatz(data, "\n", sizeof(data));
|
||||
|
||||
if (connectinfo.ext.fte1)
|
||||
Q_strncatz(data, va("0x%x 0x%x\n", PROTOCOL_VERSION_FTE1, connectinfo.ext.fte1), sizeof(data));
|
||||
if (connectinfo.ext.fte2)
|
||||
|
@ -986,8 +1077,25 @@ void CL_CheckForResend (void)
|
|||
#ifdef Q2CLIENT
|
||||
case GT_QUAKE2:
|
||||
connectinfo.protocol = CP_QUAKE2;
|
||||
connectinfo.subprotocol = PROTOCOL_VERSION_Q2;
|
||||
connectinfo.ext.fte1 = PEXT_MODELDBL|PEXT_SOUNDDBL|PEXT_SPLITSCREEN;
|
||||
lbp = cl_loopbackprotocol.string;
|
||||
if (!strcmp(lbp, "q2"))
|
||||
{ //vanilla
|
||||
connectinfo.subprotocol = PROTOCOL_VERSION_Q2;
|
||||
connectinfo.ext.fte1 = 0;
|
||||
}
|
||||
else if (!strcmp(lbp, "q2e") || !strcmp(lbp, STRINGIFY(PROTOCOL_VERSION_Q2EX)))
|
||||
{ //no fte extensions
|
||||
//still provides big coords, bigger index sizes, and splitscreen(non-dynamic though)
|
||||
connectinfo.subprotocol = PROTOCOL_VERSION_Q2EX;
|
||||
connectinfo.ext.fte1 = 0;
|
||||
}
|
||||
//else if (!strcmp(lbp, "r1q2") || !strcmp(lbp, STRINGIFY(PROTOCOL_VERSION_R1Q2)))
|
||||
//else if (!strcmp(lbp, "q2pro") || !strcmp(lbp, STRINGIFY(PROTOCOL_VERSION_Q2PRO)))
|
||||
else
|
||||
{
|
||||
connectinfo.subprotocol = PROTOCOL_VERSION_Q2EX;
|
||||
connectinfo.ext.fte1 = 0;//PEXT_MODELDBL|PEXT_SOUNDDBL|PEXT_SPLITSCREEN;
|
||||
}
|
||||
connectinfo.ext.fte2 = 0;
|
||||
connectinfo.ext.ez1 = 0;
|
||||
break;
|
||||
|
@ -2012,6 +2120,13 @@ static void CL_ReconfigureCommands(int newgame)
|
|||
extern void IN_Weapon (void); //cl_input
|
||||
extern void IN_FireDown (void); //cl_input
|
||||
extern void IN_FireUp (void); //cl_input
|
||||
extern void IN_WWheelDown (void);
|
||||
extern void IN_WWheelUp (void);
|
||||
|
||||
extern void IN_IWheelDown (void);
|
||||
extern void IN_IWheelUp (void);
|
||||
extern void IN_WeapNext_f (void);
|
||||
extern void IN_WeapPrev_f (void);
|
||||
#endif
|
||||
extern void CL_Say_f (void);
|
||||
extern void CL_SayTeam_f (void);
|
||||
|
@ -2030,13 +2145,25 @@ static void CL_ReconfigureCommands(int newgame)
|
|||
{"sizeup", SCR_SizeUp_f, "Increase viewsize", Q3},
|
||||
{"sizedown", SCR_SizeDown_f, "Decrease viewsize", Q3},
|
||||
{"color", CL_Color_f, "Change Player Colours", Q3},
|
||||
{"say", CL_Say_f, NULL, Q3},
|
||||
{"say_team", CL_SayTeam_f, NULL, Q3},
|
||||
|
||||
#ifdef QUAKESTATS
|
||||
{"weapon", IN_Weapon, "Configures weapon priorities for the next +attack as an alternative for the impulse command", ~Q1},
|
||||
{"+fire", IN_FireDown, "'+fire 8 7' will fire lg if you have it and fall back on rl if you don't, and just fire your current weapon if neither are held. Releasing fire will then switch away to exploit a bug in most mods to deny your weapon upgrades to your killer.", ~Q1},
|
||||
{"-fire", IN_FireUp, NULL, ~Q1},
|
||||
{"+weaponwheel",IN_WWheelDown, "Quickly select a weapon without needing too many extra keybinds", ~Q1},
|
||||
{"-weaponwheel",IN_WWheelUp, NULL, ~Q1},
|
||||
|
||||
#ifdef Q2CLIENT
|
||||
{"+wheel", IN_WWheelDown, "Quickly select a weapon without needing too many extra keybinds", ~Q2},
|
||||
{"-wheel", IN_WWheelUp, NULL, ~Q2},
|
||||
{"+wheel2", IN_IWheelDown, "Quickly use a powerup without needing too many extra keybinds", ~Q2},
|
||||
{"-wheel2", IN_IWheelUp, NULL, ~Q2},
|
||||
{"cl_weapnext", IN_WeapNext_f, "Select the next weapon", ~Q2},
|
||||
{"cl_weapprev", IN_WeapPrev_f, "Select the previous weapon", ~Q2},
|
||||
#endif
|
||||
#endif
|
||||
{"say", CL_Say_f, NULL, Q3},
|
||||
{"say_team", CL_SayTeam_f, NULL, Q3},
|
||||
};
|
||||
#undef Q1
|
||||
#undef Q2
|
||||
|
@ -2271,7 +2398,7 @@ This is also called on Host_Error, so it shouldn't cause any errors
|
|||
*/
|
||||
void CL_Disconnect (const char *reason)
|
||||
{
|
||||
qbyte final[12];
|
||||
qbyte final[13];
|
||||
int i;
|
||||
|
||||
if (reason)
|
||||
|
@ -2317,7 +2444,13 @@ void CL_Disconnect (const char *reason)
|
|||
case CP_QUAKE2:
|
||||
#ifdef Q2CLIENT
|
||||
final[0] = clcq2_stringcmd;
|
||||
strcpy (final+1, "disconnect");
|
||||
if (cls.protocol_q2 == PROTOCOL_VERSION_Q2EX)
|
||||
{
|
||||
final[1] = 1;
|
||||
strcpy (final+2, "disconnect");
|
||||
}
|
||||
else
|
||||
strcpy (final+1, "disconnect");
|
||||
Netchan_Transmit (&cls.netchan, strlen(final)+1, final, 2500);
|
||||
Netchan_Transmit (&cls.netchan, strlen(final)+1, final, 2500);
|
||||
Netchan_Transmit (&cls.netchan, strlen(final)+1, final, 2500);
|
||||
|
@ -3422,26 +3555,47 @@ Called to play the next demo in the demo loop
|
|||
*/
|
||||
void CL_NextDemo (void)
|
||||
{
|
||||
cvar_t *cl_autodemos;
|
||||
char str[1024];
|
||||
|
||||
if (cls.demonum < 0)
|
||||
return; // don't play demos
|
||||
|
||||
if (!cls.demos[cls.demonum][0] || cls.demonum >= MAX_DEMOS)
|
||||
cl_autodemos = Cvar_FindVar("cl_autodemos");
|
||||
if (cl_autodemos && *cl_autodemos->string)
|
||||
{
|
||||
cls.demonum = 0;
|
||||
if (!cls.demos[cls.demonum][0])
|
||||
{
|
||||
// Con_Printf ("No demos listed with startdemos\n");
|
||||
Cmd_TokenizeString(cl_autodemos->string, false, false);
|
||||
if (!Cmd_Argc())
|
||||
{ //none...
|
||||
cls.demonum = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (cls.demonum >= Cmd_Argc())
|
||||
cls.demonum = 0; //restart the loop
|
||||
|
||||
if (!strcmp(cls.demos[cls.demonum], "quit"))
|
||||
Q_snprintfz (str, sizeof(str), "quit\n");
|
||||
if (!strcmp(Cmd_Argv(cls.demonum), "quit"))
|
||||
Q_snprintfz (str, sizeof(str), "quit\n");
|
||||
else
|
||||
Q_snprintfz (str, sizeof(str), "playdemo \"demos/%s\"\n", Cmd_Argv(cls.demonum));
|
||||
}
|
||||
else
|
||||
Q_snprintfz (str, sizeof(str), "playdemo %s\n", cls.demos[cls.demonum]);
|
||||
{
|
||||
if (!cls.demos[cls.demonum][0] || cls.demonum >= MAX_DEMOS)
|
||||
{
|
||||
cls.demonum = 0;
|
||||
if (!cls.demos[cls.demonum][0])
|
||||
{
|
||||
// Con_Printf ("No demos listed with startdemos\n");
|
||||
cls.demonum = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(cls.demos[cls.demonum], "quit"))
|
||||
Q_snprintfz (str, sizeof(str), "quit\n");
|
||||
else
|
||||
Q_snprintfz (str, sizeof(str), "playdemo %s\n", cls.demos[cls.demonum]);
|
||||
}
|
||||
Cbuf_InsertText (str, RESTRICT_LOCAL, false);
|
||||
cls.demonum++;
|
||||
|
||||
|
@ -3657,7 +3811,7 @@ static void CL_ConnectionlessPacket_Connection(char *tokens)
|
|||
}
|
||||
|
||||
#if defined(Q2CLIENT)
|
||||
if (tokens && cls.protocol == CP_QUAKE2)
|
||||
if (tokens && connectinfo.protocol == CP_QUAKE2)
|
||||
{
|
||||
if (cls.protocol_q2 == PROTOCOL_VERSION_R1Q2 || cls.protocol_q2 == PROTOCOL_VERSION_Q2PRO)
|
||||
qportsize = 1;
|
||||
|
@ -3678,6 +3832,8 @@ static void CL_ConnectionlessPacket_Connection(char *tokens)
|
|||
SCR_ImageName(com_token+4);
|
||||
else if (!strncmp(com_token, "dlserver=", 9))
|
||||
Q_strncpyz(cls.downloadurl, com_token+9, sizeof(cls.downloadurl));
|
||||
else if (!strcmp(com_token, STRINGIFY(PROTOCOL_VERSION_Q2EX)))
|
||||
connectinfo.subprotocol = atoi(com_token);
|
||||
else
|
||||
Con_DPrintf("client_connect: Unknown token \"%s\"\n", com_token);
|
||||
}
|
||||
|
@ -3979,7 +4135,10 @@ void CL_ConnectionlessPacket (void)
|
|||
if (connectinfo.protocol == CP_QUAKE2 || connectinfo.protocol == CP_UNKNOWN)
|
||||
{
|
||||
connectinfo.protocol = CP_QUAKE2;
|
||||
connectinfo.subprotocol = PROTOCOL_VERSION_Q2;
|
||||
if (connectinfo.mode == CIM_Q2EONLY)
|
||||
connectinfo.subprotocol = PROTOCOL_VERSION_Q2EX;
|
||||
else
|
||||
connectinfo.subprotocol = PROTOCOL_VERSION_Q2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4035,11 +4194,20 @@ void CL_ConnectionlessPacket (void)
|
|||
if (connectinfo.subprotocol < PROTOCOL_VERSION_Q2PRO)
|
||||
connectinfo.subprotocol = PROTOCOL_VERSION_Q2PRO;
|
||||
break;
|
||||
case PROTOCOL_VERSION_Q2EX:
|
||||
if (connectinfo.subprotocol < PROTOCOL_VERSION_Q2EX)
|
||||
connectinfo.subprotocol = PROTOCOL_VERSION_Q2EX;
|
||||
break;
|
||||
}
|
||||
} while (*p++ == ',');
|
||||
}
|
||||
}
|
||||
|
||||
//if its over q2e's lan layer then pretend there was a p=2023 hint in there...
|
||||
if (connectinfo.protocol == CP_QUAKE2 && net_from.prot == NP_KEXLAN)
|
||||
if (connectinfo.subprotocol < PROTOCOL_VERSION_Q2EX)
|
||||
connectinfo.subprotocol = PROTOCOL_VERSION_Q2EX;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int cmd = MSG_ReadLong ();
|
||||
|
@ -4568,9 +4736,6 @@ void CL_ReadPacket(void)
|
|||
MSG_BeginReading (&net_message, cls.netchan.netprim);
|
||||
cls.netchan.last_received = realtime;
|
||||
CLNQ_ParseServerMessage ();
|
||||
|
||||
if (!cls.demoplayback)
|
||||
CL_NextDemo();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -5329,6 +5494,10 @@ void CL_Status_f(void)
|
|||
case PROTOCOL_VERSION_Q2PRO:
|
||||
Con_Printf("Network Protocol : Q2Pro\n");
|
||||
break;
|
||||
case PROTOCOL_VERSION_Q2EXDEMO:
|
||||
case PROTOCOL_VERSION_Q2EX:
|
||||
Con_Printf("Network Protocol : Quake2Ex\n");
|
||||
break;
|
||||
default:
|
||||
Con_Printf("Network Protocol : Quake2 (OLD)\n");
|
||||
break;
|
||||
|
@ -5444,6 +5613,7 @@ void CL_Init (void)
|
|||
|
||||
cls.state = ca_disconnected;
|
||||
cls.demotrack = -1;
|
||||
cls.demonum = -1;
|
||||
|
||||
#ifdef SVNREVISION
|
||||
if (strcmp(STRINGIFY(SVNREVISION), "-"))
|
||||
|
@ -6922,13 +7092,6 @@ double Host_Frame (double time)
|
|||
;
|
||||
COM_MainThreadWork();
|
||||
|
||||
|
||||
#if defined(Q2CLIENT)
|
||||
if (cls.protocol == CP_QUAKE2)
|
||||
cl.time += host_frametime;
|
||||
#endif
|
||||
|
||||
|
||||
// if (host_frametime > 0.2)
|
||||
// host_frametime = 0.2;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -38,7 +38,6 @@ extern entity_state_t clq2_parse_entities[MAX_PARSE_ENTITIES];
|
|||
|
||||
char *Get_Q2ConfigString(int i);
|
||||
|
||||
#ifdef Q2BSPS
|
||||
void VARGS Q2_Pmove (q2pmove_t *pmove);
|
||||
#define Q2PMF_DUCKED 1
|
||||
#define Q2PMF_JUMP_HELD 2
|
||||
|
@ -47,9 +46,12 @@ void VARGS Q2_Pmove (q2pmove_t *pmove);
|
|||
#define Q2PMF_TIME_LAND 16 // pm_time is time before rejump
|
||||
#define Q2PMF_TIME_TELEPORT 32 // pm_time is non-moving time
|
||||
#define Q2PMF_NO_PREDICTION 64 // temporarily disables prediction (used for grappling hook)
|
||||
#endif
|
||||
|
||||
vec3_t cl_predicted_origins[MAX_SPLITS][UPDATE_BACKUP];
|
||||
static struct
|
||||
{
|
||||
vec3_t origin;
|
||||
int seq;
|
||||
} cl_predictions[MAX_SPLITS][UPDATE_BACKUP];
|
||||
|
||||
|
||||
/*
|
||||
|
@ -57,7 +59,6 @@ vec3_t cl_predicted_origins[MAX_SPLITS][UPDATE_BACKUP];
|
|||
CL_CheckPredictionError
|
||||
===================
|
||||
*/
|
||||
#ifdef Q2BSPS
|
||||
void CLQ2_CheckPredictionError (void)
|
||||
{
|
||||
int frame;
|
||||
|
@ -70,18 +71,21 @@ void CLQ2_CheckPredictionError (void)
|
|||
|
||||
for (seat = 0; seat < cl.splitclients; seat++)
|
||||
{
|
||||
ps = &cl.q2frame.playerstate[seat];
|
||||
ps = &cl.q2frame.seat[seat].playerstate;
|
||||
pv = &cl.playerview[seat];
|
||||
|
||||
if (cl_nopred.value || (ps->pmove.pm_flags & Q2PMF_NO_PREDICTION))
|
||||
continue;
|
||||
|
||||
// calculate the last usercmd_t we sent that the server has processed
|
||||
frame = cls.netchan.incoming_acknowledged;
|
||||
frame = cl.ackedmovesequence;
|
||||
frame &= (UPDATE_MASK);
|
||||
|
||||
if (cl_predictions[seat][frame].seq != cl.ackedmovesequence)
|
||||
continue;
|
||||
|
||||
// compare what the server returned with what we had predicted it to be
|
||||
VectorSubtract (ps->pmove.origin, cl_predicted_origins[seat][frame], delta);
|
||||
VectorSubtract (ps->pmove.origin, cl_predictions[seat][frame].origin, delta);
|
||||
|
||||
// save the prediction error for interpolation
|
||||
len = abs(delta[0]) + abs(delta[1]) + abs(delta[2]);
|
||||
|
@ -95,7 +99,7 @@ void CLQ2_CheckPredictionError (void)
|
|||
// Con_Printf ("prediction miss on %i: %i\n", cl.q2frame.serverframe,
|
||||
// delta[0] + delta[1] + delta[2]);
|
||||
|
||||
VectorCopy (ps->pmove.origin, cl_predicted_origins[seat][frame]);
|
||||
VectorCopy (ps->pmove.origin, cl_predictions[seat][frame].origin);
|
||||
|
||||
// save for error itnerpolation
|
||||
for (i=0 ; i<3 ; i++)
|
||||
|
@ -223,7 +227,6 @@ int VARGS CLQ2_PMpointcontents (vec3_t point)
|
|||
return contents;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
=================
|
||||
CL_PredictMovement
|
||||
|
@ -244,16 +247,14 @@ static void CLQ2_UserCmdToQ2(q2usercmd_t *out, const usercmd_t *cmd)
|
|||
}
|
||||
static void CLQ2_PredictMovement (int seat) //q2 doesn't support split clients.
|
||||
{
|
||||
#ifdef Q2BSPS
|
||||
int ack, current;
|
||||
int frame;
|
||||
int oldframe;
|
||||
q2pmove_t pm;
|
||||
int step;
|
||||
int oldz;
|
||||
#endif
|
||||
int i;
|
||||
q2player_state_t *ps = &cl.q2frame.playerstate[seat];
|
||||
q2player_state_t *ps = &cl.q2frame.seat[seat].playerstate;
|
||||
playerview_t *pv = &cl.playerview[seat];
|
||||
|
||||
if (cls.state != ca_active)
|
||||
|
@ -262,9 +263,7 @@ static void CLQ2_PredictMovement (int seat) //q2 doesn't support split clients.
|
|||
// if (cl_paused->value)
|
||||
// return;
|
||||
|
||||
#ifdef Q2BSPS
|
||||
if (cl_nopred.value || cls.demoplayback || (ps->pmove.pm_flags & Q2PMF_NO_PREDICTION))
|
||||
#endif
|
||||
{ // just set angles
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
|
@ -272,9 +271,8 @@ static void CLQ2_PredictMovement (int seat) //q2 doesn't support split clients.
|
|||
}
|
||||
return;
|
||||
}
|
||||
#ifdef Q2BSPS
|
||||
ack = cls.netchan.incoming_acknowledged;
|
||||
current = cls.netchan.outgoing_sequence;
|
||||
ack = cl.ackedmovesequence; //index was received
|
||||
current = cl.movesequence; //count generated, [current] is thus invalid.
|
||||
|
||||
// if we are too far out of date, just freeze
|
||||
if (current - ack >= UPDATE_MASK)
|
||||
|
@ -297,7 +295,7 @@ static void CLQ2_PredictMovement (int seat) //q2 doesn't support split clients.
|
|||
|
||||
frame = 0;
|
||||
|
||||
predignoreentitynum = cl.q2frame.clientnum[seat]+1;//cl.playerview[seat].playernum+1;
|
||||
predignoreentitynum = cl.q2frame.seat[seat].clientnum+1;//cl.playerview[seat].playernum+1;
|
||||
|
||||
// run frames
|
||||
while (++ack < current)
|
||||
|
@ -307,7 +305,8 @@ static void CLQ2_PredictMovement (int seat) //q2 doesn't support split clients.
|
|||
Q2_Pmove (&pm);
|
||||
|
||||
// save for debug checking
|
||||
VectorCopy (pm.s.origin, cl_predicted_origins[seat][frame]);
|
||||
VectorCopy (pm.s.origin, cl_predictions[seat][frame].origin);
|
||||
cl_predictions[seat][frame].seq = ack;
|
||||
}
|
||||
|
||||
if (cl_pendingcmd[seat].msec)
|
||||
|
@ -317,7 +316,7 @@ static void CLQ2_PredictMovement (int seat) //q2 doesn't support split clients.
|
|||
}
|
||||
|
||||
oldframe = (ack-1) & (UPDATE_MASK);
|
||||
oldz = cl_predicted_origins[seat][oldframe][2];
|
||||
oldz = cl_predictions[seat][oldframe].origin[2];
|
||||
step = pm.s.origin[2] - oldz;
|
||||
if (step > 63 && step < 160 && (pm.s.pm_flags & Q2PMF_ON_GROUND) )
|
||||
{
|
||||
|
@ -335,7 +334,6 @@ static void CLQ2_PredictMovement (int seat) //q2 doesn't support split clients.
|
|||
|
||||
VectorScale (pm.s.velocity, 0.125, pv->simvel);
|
||||
VectorCopy (pm.viewangles, pv->predicted_angles);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -637,13 +635,16 @@ void CL_CalcClientTime(void)
|
|||
//default is to drift in demos+SP but not live (oh noes! added latency!)
|
||||
if (cls.protocol == CP_QUAKE2 || cls.protocol==CP_NETQUAKE/*FIXME*/ || (cls.protocol != CP_QUAKE3 && (!cl_lerp_smooth.ival || (cl_lerp_smooth.ival == 2 && !(cls.demoplayback || cl.allocated_client_slots == 1 || cl.playerview[0].spectator))) && cls.demoplayback != DPB_MVD))
|
||||
{ //no drift logic
|
||||
float f;
|
||||
double f;
|
||||
extern cvar_t cl_demospeed;
|
||||
f = cl.gametime - cl.oldgametime;
|
||||
if (f > 0.1)
|
||||
f = 0.1;
|
||||
f = (realtime - cl.gametimemark) / (f);
|
||||
if (cls.demoplayback && cl_demospeed.value > 0 && cls.state == ca_active)
|
||||
f *= cl_demospeed.value;
|
||||
f = bound(0, f, 1);
|
||||
cl.servertime = cl.gametime*f + cl.oldgametime*(1-f);
|
||||
cl.servertime = cl.oldgametime + f*(cl.gametime-cl.oldgametime);
|
||||
}
|
||||
else
|
||||
{ //funky magic drift logic. we be behind the most recent frame in order to attempt to cover network congestions (which is apparently common in germany).
|
||||
|
|
|
@ -2384,17 +2384,20 @@ void SCR_DrawLoading (qboolean opaque)
|
|||
|
||||
y+= 16+8;
|
||||
}
|
||||
else if (CL_TryingToConnect())
|
||||
else if ((s=CL_TryingToConnect()))
|
||||
{
|
||||
char dots[4];
|
||||
char *nl;
|
||||
if (!strchr(s, '\n'))
|
||||
s = va("^bConnecting to: %s...", s);
|
||||
|
||||
s = CL_TryingToConnect();
|
||||
x = (vid.width - (strlen(s)+15)*8) / 2;
|
||||
dots[0] = '.';
|
||||
dots[1] = '.';
|
||||
dots[2] = '.';
|
||||
dots[(int)realtime & 3] = 0;
|
||||
Draw_FunString(x, y+4, va("Connecting to: %s%s", s, dots));
|
||||
for (;s; s = nl)
|
||||
{
|
||||
nl = strchr(s, '\n');
|
||||
if (nl)
|
||||
*nl++ = 0;
|
||||
Draw_FunStringWidth(0, y+4, s, vid.width, 2, false);
|
||||
y += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,15 +83,26 @@ static const char *q2efnames[] =
|
|||
"TEQ2_EXPLOSION1_NP",
|
||||
"TEQ2_FLECHETTE",
|
||||
|
||||
//RERELEASE
|
||||
"TEQ2EX_BLUEHYPERBLASTER",
|
||||
"TEQ2EX_BFGZAP",
|
||||
"TEQ2EX_BERSERK_SLAM",
|
||||
"TEQ2EX_GRAPPLE_CABLE_2",
|
||||
"TEQ2EX_POWER_SPLASH",
|
||||
"TEQ2EX_LIGHTNING_BEAM",
|
||||
"TEQ2EX_EXPLOSION1_NL",
|
||||
"TEQ2EX_EXPLOSION2_NL",
|
||||
//RERELEASE
|
||||
|
||||
NULL,//"TEQ2_CR_LEADERBLASTER",
|
||||
NULL,//"TEQ2_CR_BLASTER_MUZZLEFLASH",
|
||||
NULL,//"TEQ2_CR_BLUE_MUZZLEFLASH",
|
||||
NULL,//"TEQ2_CR_SMART_MUZZLEFLASH",
|
||||
NULL,//"TEQ2_CR_LEADERFIELD",
|
||||
NULL,//"TEQ2_CR_DEATHFIELD",
|
||||
NULL,//"TEQ2_CR_BLASTERBEAM",
|
||||
NULL,//"TEQ2_CR_STAIN",
|
||||
|
||||
// NULL,//"TEQ2_CR_LEADERBLASTER",
|
||||
// NULL,//"TEQ2_CR_BLASTER_MUZZLEFLASH",
|
||||
// NULL,//"TEQ2_CR_BLUE_MUZZLEFLASH",
|
||||
// NULL,//"TEQ2_CR_SMART_MUZZLEFLASH",
|
||||
// NULL,//"TEQ2_CR_LEADERFIELD",
|
||||
// NULL,//"TEQ2_CR_DEATHFIELD",
|
||||
// NULL,//"TEQ2_CR_BLASTERBEAM",
|
||||
// NULL,//"TEQ2_CR_STAIN",
|
||||
NULL,//"TEQ2_CR_FIRE",
|
||||
NULL,//"TEQ2_CR_CABLEGUT",
|
||||
NULL,//"TEQ2_CR_SMOKE",
|
||||
|
@ -106,6 +117,7 @@ static const char *q2efnames[] =
|
|||
"te_splashslime",
|
||||
"te_splashlava",
|
||||
"te_splashblood",
|
||||
"te_splashelect",
|
||||
|
||||
"TR_BLASTERTRAIL",
|
||||
"TR_BLASTERTRAIL2",
|
||||
|
@ -131,6 +143,8 @@ static const char *q2efnames[] =
|
|||
"ev_item_respawn",
|
||||
"ev_player_teleport",
|
||||
"ev_footstep",
|
||||
"ev_other_footstep",
|
||||
"ev_ladder_step",
|
||||
};
|
||||
int pt_q2[sizeof(q2efnames)/sizeof(q2efnames[0])];
|
||||
#endif
|
||||
|
@ -761,40 +775,37 @@ beam_t *CL_NewBeam (int entity, int tag, tentmodels_t *btype)
|
|||
{
|
||||
for (i=0, b=cl_beams; i < beams_running; i++, b++)
|
||||
if (b->entity == entity && b->tag == tag)
|
||||
{
|
||||
b->info = btype;
|
||||
return b;
|
||||
}
|
||||
goto found;
|
||||
}
|
||||
|
||||
// find a free beam
|
||||
for (i=0, b=cl_beams; i < beams_running; i++, b++)
|
||||
{
|
||||
if (!b->info)
|
||||
{
|
||||
b->info = btype;
|
||||
return b;
|
||||
}
|
||||
goto found;
|
||||
}
|
||||
|
||||
// if (i == beams_running && i < cl_maxbeams.ival)
|
||||
|
||||
// if (i >= cl_maxbeams.ival)
|
||||
// return NULL;
|
||||
if (i == cl_beams_max)
|
||||
{
|
||||
if (i == cl_beams_max)
|
||||
{
|
||||
int nm = (i+1)*2;
|
||||
CL_ClearTEntParticleState();
|
||||
int nm = (i+1)*2;
|
||||
CL_ClearTEntParticleState();
|
||||
|
||||
cl_beams = BZ_Realloc(cl_beams, nm*sizeof(*cl_beams));
|
||||
memset(cl_beams + cl_beams_max, 0, sizeof(*cl_beams)*(nm-cl_beams_max));
|
||||
cl_beams_max = nm;
|
||||
}
|
||||
|
||||
beams_running++;
|
||||
cl_beams[i].info = btype;
|
||||
return &cl_beams[i];
|
||||
cl_beams = BZ_Realloc(cl_beams, nm*sizeof(*cl_beams));
|
||||
memset(cl_beams + cl_beams_max, 0, sizeof(*cl_beams)*(nm-cl_beams_max));
|
||||
cl_beams_max = nm;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
beams_running++;
|
||||
b = &cl_beams[i];
|
||||
|
||||
found:
|
||||
b->info = btype;
|
||||
b->bflags = 0;
|
||||
VectorClear(b->offset);
|
||||
return b;
|
||||
}
|
||||
#define STREAM_ATTACHTOPLAYER 1 //if owned by the viewentity then attach to camera (but don't for other entities).
|
||||
#define STREAM_JITTER 2 //moves up to 30qu forward/back (40qu per sec)
|
||||
|
@ -1964,8 +1975,6 @@ void CL_ParseTEnt_Sized (void)
|
|||
}
|
||||
}
|
||||
|
||||
void MSG_ReadPos (vec3_t pos);
|
||||
void MSG_ReadDir (vec3_t dir);
|
||||
typedef struct {
|
||||
char name[64];
|
||||
int netstyle;
|
||||
|
@ -2632,14 +2641,22 @@ void CLQ2_ParseTEnt (void)
|
|||
int r;
|
||||
int ent;
|
||||
// int magnitude;
|
||||
explosion_t *ex;
|
||||
// explosion_t *ex;
|
||||
|
||||
type = MSG_ReadByte ();
|
||||
|
||||
if (type <= Q2TE_MAX)
|
||||
{
|
||||
if (cl_shownet.ival > 1)
|
||||
Con_Printf("\t%s\n", q2efnames[type]);
|
||||
pt = pt_q2[type];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cl_shownet.ival > 1)
|
||||
Con_Printf("\tTE%u\n", type);
|
||||
pt = P_INVALID;
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
case Q2TE_GUNSHOT: //grey tall thing with smoke+sparks
|
||||
|
@ -2672,9 +2689,12 @@ void CLQ2_ParseTEnt (void)
|
|||
case Q2TE_DEBUGTRAIL: //long lived blue trail
|
||||
case Q2TE_BUBBLETRAIL2: //grey rising trail
|
||||
case Q2TE_BLUEHYPERBLASTER: //TE_BLASTER without model+light
|
||||
case Q2TEEX_RAILTRAIL2:
|
||||
case Q2TEEX_BFGZAP:
|
||||
MSG_ReadPos (pos);
|
||||
MSG_ReadPos (pos2);
|
||||
P_ParticleTrail(pos, pos2, pt, 1, 0, NULL, NULL);
|
||||
P_RunParticleEffectTypeString(pos2, NULL, 1, va("%s_end", q2efnames[type]));
|
||||
break;
|
||||
case Q2TE_EXPLOSION1: //column
|
||||
case Q2TE_EXPLOSION2: //splits
|
||||
|
@ -2774,16 +2794,38 @@ void CLQ2_ParseTEnt (void)
|
|||
Con_Printf("FIXME: Q2TE_WIDOWBEAMOUT not implemented\n");
|
||||
break;
|
||||
|
||||
case Q2TE_RAILTRAIL2: /*not implemented in vanilla*/
|
||||
//case Q2TE_RAILTRAIL2: /*not implemented in vanilla*/
|
||||
case Q2TE_FLAME: /*not implemented in vanilla*/
|
||||
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
|
||||
break;
|
||||
|
||||
case Q2TEEX_BLUEHYPERBLASTER:
|
||||
case Q2TEEX_BERSERK_SLAM:
|
||||
MSG_ReadPos (pos);
|
||||
MSG_ReadDir (pos2);
|
||||
P_RunParticleEffectType(pos, dir, 1, pt);
|
||||
break;
|
||||
|
||||
case Q2TEEX_GRAPPLE_CABLE_2:
|
||||
CL_ParseBeam (BT_Q2GRAPPLE);
|
||||
break;
|
||||
|
||||
case Q2TEEX_POWER_SPLASH:
|
||||
MSGCL_ReadEntity();
|
||||
MSG_ReadByte();
|
||||
break;
|
||||
case Q2TEEX_LIGHTNING_BEAM:
|
||||
CL_ParseBeam (BT_Q2LIGHTNING);
|
||||
break;
|
||||
case Q2TEEX_EXPLOSION1_NL:
|
||||
case Q2TEEX_EXPLOSION2_NL:
|
||||
MSG_ReadPos (pos);
|
||||
P_RunParticleEffectType(pos, NULL, 1, pt);
|
||||
break;
|
||||
|
||||
|
||||
//My old attempt at running AlienArena years ago. probably not enough now. Other engines will have other effects.
|
||||
case CRTE_LEADERBLASTER:
|
||||
/* case CRTE_LEADERBLASTER:
|
||||
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
|
||||
case CRTE_BLASTER_MUZZLEFLASH:
|
||||
MSG_ReadPos (pos);
|
||||
|
@ -2825,7 +2867,7 @@ void CLQ2_ParseTEnt (void)
|
|||
MSG_ReadPos (pos2);
|
||||
P_ParticleTrail(pos, pos2, P_FindParticleType("q2part.TR_BLASTERTRAIL2"), 1, 0, NULL, NULL);
|
||||
break;
|
||||
/* case CRTE_STAIN:
|
||||
case CRTE_STAIN:
|
||||
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
|
||||
case CRTE_FIRE:
|
||||
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
|
||||
|
|
|
@ -99,17 +99,25 @@ typedef enum
|
|||
Q2PM_GIB, // different bounding box
|
||||
Q2PM_FREEZE
|
||||
} q2pmtype_t;
|
||||
enum
|
||||
{ //urgh.
|
||||
// can accelerate and turn
|
||||
Q2EPM_NORMAL,
|
||||
Q2EPM_GRAPPLE,
|
||||
Q2EPM_SPECTATOR,
|
||||
Q2EPM_SPECTATOR2,
|
||||
// no acceleration or turning
|
||||
Q2EPM_DEAD,
|
||||
Q2EPM_GIB, // different bounding box
|
||||
Q2EPM_FREEZE
|
||||
};
|
||||
typedef struct
|
||||
{ //shared with q2 dll
|
||||
|
||||
q2pmtype_t pm_type;
|
||||
|
||||
#if 0
|
||||
int origin[3]; // 12.3
|
||||
#else
|
||||
short origin[3]; // 20.3
|
||||
#endif
|
||||
short velocity[3]; // 12.3
|
||||
short origin[3]; // 13.3
|
||||
short velocity[3]; // 13.3
|
||||
qbyte pm_flags; // ducked, jump_held, etc
|
||||
qbyte pm_time; // each unit = 8 ms
|
||||
short gravity;
|
||||
|
@ -266,9 +274,11 @@ typedef struct
|
|||
int serverframe;
|
||||
int servertime; // server time the message is valid for (in msec)
|
||||
int deltaframe;
|
||||
qbyte areabits[MAX_Q2MAP_AREAS/8]; // portalarea visibility bits
|
||||
q2player_state_t playerstate[MAX_SPLITS];
|
||||
int clientnum[MAX_SPLITS];
|
||||
struct {
|
||||
qbyte areabits[MAX_Q2MAP_AREAS/8]; // portalarea visibility bits
|
||||
q2player_state_t playerstate;
|
||||
int clientnum;
|
||||
} seat[MAX_SPLITS];
|
||||
int num_entities;
|
||||
int parse_entities; // non-masked index into cl_parse_entities array
|
||||
} q2frame_t;
|
||||
|
@ -307,8 +317,9 @@ typedef struct
|
|||
#define LFLAG_SHADOWMAP (1<<9)
|
||||
#define LFLAG_CREPUSCULAR (1<<10) //weird type of sun light that gives god rays
|
||||
#define LFLAG_ORTHO (1<<11) //sun-style -light
|
||||
#define LFLAG_FORCECACHE (1<<12) //shadowmap/surfaces should be cached from one frame to the next.
|
||||
|
||||
#define LFLAG_INTERNAL (LFLAG_LIGHTMAP|LFLAG_FLASHBLEND) //these are internal to FTE, and never written to disk (ie: .rtlights files shouldn't contain these)
|
||||
#define LFLAG_INTERNAL (LFLAG_LIGHTMAP|LFLAG_FLASHBLEND|LFLAG_FORCECACHE) //these are internal to FTE, and never written to disk (ie: .rtlights files shouldn't contain these)
|
||||
#define LFLAG_DYNAMIC (LFLAG_LIGHTMAP | LFLAG_FLASHBLEND | LFLAG_NORMALMODE)
|
||||
|
||||
typedef struct dlight_s
|
||||
|
@ -859,14 +870,14 @@ typedef struct
|
|||
double lastlinktime; //cl.time from last frame.
|
||||
double mapstarttime; //for computing csqc's cltime.
|
||||
|
||||
float servertime; //current server time, bound between gametime and gametimemark
|
||||
double servertime; //current server time, bound between gametime and gametimemark
|
||||
float mtime; //server time as on the server when we last received a packet. not allowed to decrease.
|
||||
float oldmtime; //server time as on the server for the previously received packet.
|
||||
|
||||
float gametime;
|
||||
float gametimemark;
|
||||
float oldgametime; //used as the old time to lerp cl.time from.
|
||||
float oldgametimemark; //if it's 0, cl.time will casually increase.
|
||||
double gametime;
|
||||
double gametimemark;
|
||||
double oldgametime; //used as the old time to lerp cl.time from.
|
||||
double oldgametimemark; //if it's 0, cl.time will casually increase.
|
||||
float demogametimebias; //mvd timings are weird.
|
||||
int demonudge; //
|
||||
float demopausedtilltime;//demo is paused until realtime>this
|
||||
|
@ -1643,6 +1654,7 @@ void CLR1Q2_ParsePlayerUpdate(void);
|
|||
void CLQ2_ParseFrame (int extrabits);
|
||||
void CLQ2_ParseMuzzleFlash (void);
|
||||
void CLQ2_ParseMuzzleFlash2 (void);
|
||||
void CLQ2EX_ParseMuzzleFlash3 (void);
|
||||
void CLQ2_ParseInventory (int seat);
|
||||
int CLQ2_RegisterTEntModels (void);
|
||||
void CLQ2_WriteDemoBaselines(sizebuf_t *buf);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2328,7 +2328,7 @@ int Key_StringToKeynum (const char *str, int *modifier)
|
|||
for (i = 0; i < countof(mods); )
|
||||
{
|
||||
if (!Q_strncasecmp(mods[i].prefix, str, mods[i].len))
|
||||
if (str[mods[i].len] == '_' || str[mods[i].len] == '+' || str[mods[i].len] == ' ')
|
||||
if (/*str[mods[i].len] == '_' ||*/ str[mods[i].len] == '+' || str[mods[i].len] == ' ')
|
||||
if (str[mods[i].len+1])
|
||||
{
|
||||
*modifier |= mods[i].mod;
|
||||
|
|
|
@ -2365,7 +2365,17 @@ qboolean MC_Main_Key (emenu_t *menu, int key, unsigned int unicode) //here purly
|
|||
//don't spam menu open+close events if we're not going to be allowing the console to appear
|
||||
if (con_stayhidden.ival && cls.state == ca_disconnected)
|
||||
if (!CL_TryingToConnect())
|
||||
{
|
||||
extern cvar_t cl_demoreel;
|
||||
if (cl_demoreel.ival)
|
||||
{ //start a demo instead. this should probably be on a timer...
|
||||
cls.demonum = MAX_DEMOS;
|
||||
CL_NextDemo();
|
||||
if (cls.state)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,8 @@ struct
|
|||
|
||||
extern qbyte *host_basepal;
|
||||
|
||||
static float throttle;
|
||||
|
||||
extern int PClassic_PointFile(int c, vec3_t point);
|
||||
extern particleengine_t pe_classic;
|
||||
particleengine_t *fallback = NULL; //does this really need to be 'extern'?
|
||||
|
@ -314,7 +316,8 @@ typedef struct part_type_s {
|
|||
SM_UNICIRCLE, //unicircle = uniform circle
|
||||
SM_FIELD, //field = synced field (brightfield, etc)
|
||||
SM_DISTBALL, // uneven distributed ball
|
||||
SM_MESHSURFACE //distributed roughly evenly over the surface of the mesh
|
||||
SM_MESHSURFACE, //distributed roughly evenly over the surface of the mesh
|
||||
SM_FIXMEWARNING, //for people to use to mark placeholder effects.
|
||||
} spawnmode;
|
||||
|
||||
float gravity;
|
||||
|
@ -1924,6 +1927,8 @@ parsefluid:
|
|||
ptype->looks.blendmode = BM_BLEND; //fallback
|
||||
}
|
||||
}
|
||||
else if (!strcmp(var, "placeholder"))
|
||||
ptype->spawnmode = SM_FIXMEWARNING;
|
||||
else if (!strcmp(var, "spawnmode"))
|
||||
{
|
||||
if (!strcmp(value, "circle"))
|
||||
|
@ -2525,6 +2530,9 @@ qboolean PScript_Query(int typenum, int body, char *outstr, int outstrlen)
|
|||
case SM_MESHSURFACE:
|
||||
Q_strncatz(outstr, va("spawnmode meshsurface\n"), outstrlen);
|
||||
break;
|
||||
case SM_FIXMEWARNING:
|
||||
Q_strncatz(outstr, va("placeholder\n"), outstrlen);
|
||||
break;
|
||||
}
|
||||
if (ptype->spawnvel || ptype->spawnvelvert || all)
|
||||
Q_strncatz(outstr, va("spawnvel %g %g\n", ptype->spawnvel, ptype->spawnvelvert), outstrlen);
|
||||
|
@ -4916,6 +4924,9 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count,
|
|||
// area = 0;
|
||||
// tri = -1;
|
||||
// break;
|
||||
case SM_FIXMEWARNING:
|
||||
Con_ThrottlePrintf(&throttle, 0, CON_WARNING"Particle effect %s.%s is marked as a placeholder\n", ptype->config, ptype->name);
|
||||
return 1;
|
||||
default: //others don't need intitialisation
|
||||
break;
|
||||
}
|
||||
|
@ -5702,18 +5713,24 @@ static void P_ParticleTrailSpawn (vec3_t startpos, vec3_t end, part_type_t *ptyp
|
|||
// VectorAdd(start, ptype->orgbias, start);
|
||||
|
||||
// spawn mode precalculations
|
||||
if (ptype->spawnmode == SM_SPIRAL)
|
||||
switch(ptype->spawnmode)
|
||||
{
|
||||
case SM_SPIRAL:
|
||||
VectorVectors(vec, right, up);
|
||||
|
||||
// precalculate degree of rotation
|
||||
if (ptype->spawnparam1)
|
||||
tdegree = 2.0*M_PI/ptype->spawnparam1; /* distance per rotation inversed */
|
||||
sdegree = ptype->spawnparam2*(M_PI/180);
|
||||
}
|
||||
else if (ptype->spawnmode == SM_CIRCLE)
|
||||
{
|
||||
break;
|
||||
case SM_CIRCLE:
|
||||
VectorVectors(vec, right, up);
|
||||
break;
|
||||
case SM_FIXMEWARNING:
|
||||
Con_ThrottlePrintf(&throttle, 0, CON_WARNING"Particle effect %s.%s is marked as a placeholder\n", ptype->config, ptype->name);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (ptype->flags & PT_NOSPREADFIRST)
|
||||
|
|
|
@ -368,6 +368,7 @@ extern cvar_t worker_flush;
|
|||
qboolean COM_DoWork(int thread, qboolean leavelocked);
|
||||
#define COM_MainThreadWork() while (COM_DoWork(0, false) && worker_flush.ival) /*called each frame to do any gl uploads or whatever*/
|
||||
#define COM_MainThreadFlush() while (COM_DoWork(0, false)) /*make sure the main thread has done ALL work pending*/
|
||||
unsigned int COM_HasWorkers(wgroup_t tg);
|
||||
void COM_AddWork(wgroup_t thread, void(*func)(void *ctx, void *data, size_t a, size_t b), void *ctx, void *data, size_t a, size_t b); //low priority
|
||||
void COM_InsertWork(wgroup_t tg, void(*func)(void *ctx, void *data, size_t a, size_t b), void *ctx, void *data, size_t a, size_t b); //high priority
|
||||
qboolean COM_HasWork(void);
|
||||
|
@ -385,6 +386,7 @@ void COM_AssertMainThread(const char *msg);
|
|||
#endif
|
||||
#else
|
||||
#define com_workererror false
|
||||
#define COM_HasWorkers(t) 0
|
||||
#define COM_AddWork(t,f,a,b,c,d) (f)((a),(b),(c),(d))
|
||||
#define COM_InsertWork(t,f,a,b,c,d) (f)((a),(b),(c),(d))
|
||||
#define COM_WorkerPartialSync(c,a,v)
|
||||
|
|
|
@ -3475,22 +3475,6 @@ char *particle_set_q2part =
|
|||
"scalefactor 0.8\n"
|
||||
"}\n"
|
||||
|
||||
"r_part placeholder\n"
|
||||
"{ //FIXME: fix the things that assoc this!\n"
|
||||
"texture \"classicparticle\"\n"
|
||||
"tcoords 0 0 16 16 32\n"
|
||||
"count 1\n"
|
||||
"scale 1\n"
|
||||
"alpha 1\n"
|
||||
"die 0.3 0.8\n"
|
||||
"randomvel 20\n"
|
||||
"orgadd 0 31\n"
|
||||
"spawnorg 4\n"
|
||||
"gravity 40\n"
|
||||
"scalefactor 0.8\n"
|
||||
"colorindex 0 255 //something that makes it obviously a placeholder.\n"
|
||||
"}\n"
|
||||
|
||||
"r_part te_splashsparks\n"
|
||||
"{\n"
|
||||
"texture \"classicparticle\"\n"
|
||||
|
@ -3585,6 +3569,21 @@ char *particle_set_q2part =
|
|||
"scalefactor 0.8\n"
|
||||
"colorindex 0xe0\n"
|
||||
"}\n"
|
||||
"r_part te_splashelect\n"
|
||||
"{\n"
|
||||
"texture \"classicparticle\"\n"
|
||||
"tcoords 0 0 16 16 32\n"
|
||||
"count 20\n"
|
||||
"scale 1\n"
|
||||
"alpha 1\n"
|
||||
"die 0.3 0.5\n"
|
||||
"randomvel 20\n"
|
||||
"orgadd 0 31\n"
|
||||
"spawnorg 4\n"
|
||||
"gravity 40\n"
|
||||
"scalefactor 0.8\n"
|
||||
"colorindex 0xb0\n"
|
||||
"}\n"
|
||||
"r_part te_splashblood\n"
|
||||
"{\n"
|
||||
"texture \"classicparticle\"\n"
|
||||
|
@ -4161,20 +4160,52 @@ char *particle_set_q2part =
|
|||
"sound \"weapons/disrupthit.wav\" 1 1 0 0\n"
|
||||
"}\n"
|
||||
"r_part teq2_teleport_effect\n"
|
||||
"{ //FIXME\n"
|
||||
"assoc placeholder\n"
|
||||
"{\n"
|
||||
"texture \"classicparticle\"\n"
|
||||
"tcoords 0 0 16 16 32\n"
|
||||
"count 400\n"
|
||||
"scale 1\n"
|
||||
"alpha 1\n"
|
||||
"die 0.5 0.8\n"
|
||||
"orgadd 8 -48\n"
|
||||
"veladd -100 -0\n"
|
||||
"spawnmode circle\n"
|
||||
"spawnorg 0 0\n"
|
||||
"spawnvel -50 30\n"
|
||||
"randomvel -32 -31\n"
|
||||
"gravity 0\n"
|
||||
"colorindex 15\n"
|
||||
"scalefactor 0.8\n"
|
||||
"}\n"
|
||||
"r_part teq2_dball_goal\n"
|
||||
"{ //FIXME\n"
|
||||
"assoc placeholder\n"
|
||||
"{ // same as teq2_teleport_effect\n"
|
||||
"assoc teq2_teleport_effect\n"
|
||||
"}\n"
|
||||
"r_part teq2_widowsplash\n"
|
||||
"{ //FIXME\n"
|
||||
"assoc placeholder\n"
|
||||
"{ // particle ball that slowly expands\n"
|
||||
"texture \"classicparticle\"\n"
|
||||
"tcoords 0 0 16 16 32\n"
|
||||
"count 400\n"
|
||||
"scale 1\n"
|
||||
"alpha 1\n"
|
||||
"die 3 3\n"
|
||||
"veladd 10 10\n"
|
||||
"spawnmode circle\n"
|
||||
"spawnorg 0 0\n"
|
||||
"randomvel -10 10\n"
|
||||
"gravity 0\n"
|
||||
"colorindex 104 7\n"
|
||||
"scalefactor 0.8\n"
|
||||
"}\n"
|
||||
"r_part teq2_debugtrail\n"
|
||||
"{ //FIXME\n"
|
||||
"assoc placeholder\n"
|
||||
"{\n"
|
||||
"texture \"classicparticle\"\n"
|
||||
"tcoords 0 0 16 16 32\n"
|
||||
"scale 1\n"
|
||||
"alpha 1\n"
|
||||
"step 5\n"
|
||||
"die 5 5\n"
|
||||
"colorindex 111\n"
|
||||
"}\n"
|
||||
"r_part teq2_chainfist_smoke\n"
|
||||
"{\n"
|
||||
|
@ -4305,11 +4336,41 @@ char *particle_set_q2part =
|
|||
"}\n"
|
||||
|
||||
"r_part tr_trap\n"
|
||||
"{ //FIXME: add particles\n"
|
||||
"{\n"
|
||||
"texture \"classicparticle\"\n"
|
||||
"tcoords 0 0 16 16 32\n"
|
||||
"count 30\n"
|
||||
"scale 1\n"
|
||||
"alpha 1\n"
|
||||
"die 0.4 0.8\n"
|
||||
"randomvel 8\n"
|
||||
"veladd 48\n"
|
||||
"colorindex 0xe0 7\n"
|
||||
"spawnmode telebox 0 4\n"
|
||||
"spawnorg 8 16\n"
|
||||
"lighttime 0\n"
|
||||
"lightradius 100 200\n"
|
||||
"lightrgb 1.0 0.8 0.25\n"
|
||||
"assoc placeholder\n"
|
||||
"}\n"
|
||||
|
||||
"r_part +tr_trap\n"
|
||||
"{\n"
|
||||
"texture \"classicparticle\"\n"
|
||||
"tcoords 0 0 16 16 32\n"
|
||||
"count 128\n"
|
||||
"scale 1\n"
|
||||
"alpha 1\n"
|
||||
"die 0.4 0.8\n"
|
||||
"randomvel 8\n"
|
||||
"veladd 20\n"
|
||||
"colorindex 58\n"
|
||||
"spawnmode telebox 0 4\n"
|
||||
"spawnorg 1 48\n"
|
||||
"}\n"
|
||||
|
||||
"r_part ef_trap\n"
|
||||
"{ //FIXME\n"
|
||||
"placeholder\n"
|
||||
"}\n"
|
||||
|
||||
//flags do NOT use coronas, because it obscures the holding player's skin colour
|
||||
|
@ -4418,6 +4479,13 @@ char *particle_set_q2part =
|
|||
"sound \"player/step3.wav\" 1 1 0 0 1\n"
|
||||
"sound \"player/step4.wav\" 1 1 0 0 1\n"
|
||||
"}\n"
|
||||
"r_part ev_other_footstep\n"
|
||||
"{ //q2e - same but with idle attenuation\n"
|
||||
"sound \"player/step1.wav\" 1 2 0 0 1\n"
|
||||
"sound \"player/step2.wav\" 1 2 0 0 1\n"
|
||||
"sound \"player/step3.wav\" 1 2 0 0 1\n"
|
||||
"sound \"player/step4.wav\" 1 2 0 0 1\n"
|
||||
"}\n"
|
||||
|
||||
//central explosion
|
||||
"r_part teq2_bfg_bigexplosion\n"
|
||||
|
@ -4472,12 +4540,35 @@ char *particle_set_q2part =
|
|||
"}\n"
|
||||
|
||||
"r_part teq2_heatbeam_sparks\n"
|
||||
"{ //FIXME\n"
|
||||
"assoc placeholder\n"
|
||||
"{\n"
|
||||
"texture \"classicparticle\"\n"
|
||||
"tcoords 0 0 16 16 32\n"
|
||||
"count 30\n"
|
||||
"scale 1\n"
|
||||
"alpha 1\n"
|
||||
"die 0.3 0.8\n"
|
||||
"veladd 64\n"
|
||||
"orgadd 0 16\n"
|
||||
"spawnorg 4\n"
|
||||
"gravity 40\n"
|
||||
"scalefactor 0.8\n"
|
||||
"colorindex 9 7\n"
|
||||
"}\n"
|
||||
"r_part teq2_heatbeam_steam\n"
|
||||
"{ //FIXME\n"
|
||||
"assoc placeholder\n"
|
||||
"{\n"
|
||||
"texture \"classicparticle\"\n"
|
||||
"tcoords 0 0 16 16 32\n"
|
||||
"count 30\n"
|
||||
"scale 1\n"
|
||||
"alpha 1\n"
|
||||
"die 0.2 0.4\n"
|
||||
"randomvel 40\n"
|
||||
"orgadd 0 15\n"
|
||||
"veladd 30\n"
|
||||
"spawnorg 4\n"
|
||||
"gravity 40\n"
|
||||
"scalefactor 0.8\n"
|
||||
"colorindex 0xe0 7\n"
|
||||
"}\n"
|
||||
|
||||
//r_part teq2_heatbeam_steam
|
||||
|
@ -4512,6 +4603,138 @@ char *particle_set_q2part =
|
|||
"randomvel 5\n"
|
||||
"die 3 3.5\n"
|
||||
"}\n"
|
||||
|
||||
"r_part teq2ex_bluehyperblaster_puff\n"
|
||||
"{\n"
|
||||
"count 0 0 1\n"
|
||||
"model \"models/objects/explode/tris.md2\" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=1\n"
|
||||
"}\n"
|
||||
|
||||
"r_part teq2ex_bluehyperblaster\n"
|
||||
"{\n"
|
||||
"texture \"classicparticle\"\n"
|
||||
"tcoords 0 0 16 16 32\n"
|
||||
"count 60\n"
|
||||
"scale 1\n"
|
||||
"alpha 1\n"
|
||||
"die 0.3 0.8\n"
|
||||
"randomvel 40\n"
|
||||
"orgadd 0 15\n"
|
||||
"veladd 30\n"
|
||||
"spawnorg 4\n"
|
||||
"gravity 40\n"
|
||||
"scalefactor 0.8\n"
|
||||
"colorindex 111 108\n"
|
||||
"assoc teq2ex_bluehyperblaster_puff\n"
|
||||
"lightradius 150\n"
|
||||
"lightradiusfade 400\n"
|
||||
"lightrgb 0 0 1\n"
|
||||
"lightshadows 1\n"
|
||||
"sound \"weapons/lashit.wav\" 1 1 0 0\n"
|
||||
"}\n"
|
||||
|
||||
"r_part teq2ex_bfgzap_end\n"
|
||||
"{\n"
|
||||
"assoc teq2_bfg_explosion\n"
|
||||
"}\n"
|
||||
|
||||
"r_part teq2ex_bfgzap\n"
|
||||
"{ // green bolt-beam with small green explosion sprite at the end\n"
|
||||
"texture \"particles/fteparticlefont.tga\"\n"
|
||||
"tcoords 97 97 191 191 256\n"
|
||||
"scale 4\n"
|
||||
"alpha 1.0\n"
|
||||
"step 4\n"
|
||||
"randomvel 0\n"
|
||||
"type beam\n"
|
||||
"die 1\n"
|
||||
"colorindex 0xd0\n"
|
||||
"}\n"
|
||||
|
||||
"r_part teq2ex_berserk_slampuff\n"
|
||||
"{\n"
|
||||
"count 0 0 1\n"
|
||||
"model \"models/objects/explode/tris.md2\" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=3\n"
|
||||
"}\n"
|
||||
"r_part teq2ex_berserk_slam\n"
|
||||
"{\n"
|
||||
"texture \"classicparticle\"\n"
|
||||
"tcoords 0 0 16 16 32\n"
|
||||
"count 256\n"
|
||||
"scale 1\n"
|
||||
"alpha 1\n"
|
||||
"die 0.625 1\n"
|
||||
"spawnmode ball\n"
|
||||
"spawnorg 16\n"
|
||||
"spawnvel 192\n"
|
||||
"scalefactor 0.8\n"
|
||||
"gravity 40\n"
|
||||
"colorindex 111 108\n"
|
||||
"assoc teq2ex_berserk_slampuff\n"
|
||||
"}\n"
|
||||
"r_part teq2ex_grapple_cable_2\n"
|
||||
"{\n"
|
||||
"texture \"particles/fteparticlefont.tga\"\n"
|
||||
"tcoords 97 97 191 191 256\n"
|
||||
"scale 2\n"
|
||||
"alpha 1.0\n"
|
||||
"step 4\n"
|
||||
"randomvel 0\n"
|
||||
"type beam\n"
|
||||
"die 0.25\n"
|
||||
"colorindex 6\n"
|
||||
"}\n"
|
||||
"r_part teq2ex_power_splash\n"
|
||||
"{\n"
|
||||
"texture \"classicparticle\"\n"
|
||||
"tcoords 0 0 16 16 32\n"
|
||||
"count 256\n"
|
||||
"scale 4\n"
|
||||
"alpha 0.4\n"
|
||||
"die 1 0.625\n"
|
||||
"spawnmode ball\n"
|
||||
"spawnorg 16\n"
|
||||
"spawnvel 192\n"
|
||||
"scalefactor 0.8\n"
|
||||
"gravity 40\n"
|
||||
"colorindex 208 209\n"
|
||||
"}\n"
|
||||
"r_part teq2ex_lightning_beam\n"
|
||||
"{\n"
|
||||
"texture \"particles/fteparticlefont.tga\"\n"
|
||||
"tcoords 97 97 191 191 256\n"
|
||||
"scale 2\n"
|
||||
"alpha 1.0\n"
|
||||
"step 4\n"
|
||||
"randomvel 0\n"
|
||||
"type beam\n"
|
||||
"die 0.25\n"
|
||||
"colorindex 108\n"
|
||||
"}\n"
|
||||
"r_part teq2ex_explosion1_nl\n"
|
||||
"{ // the _nl stands for 'no light'\n"
|
||||
"assoc std_explosion_particles\n"
|
||||
"sound \"weapons/rocklx1a.wav\" 1 1 0 0\n"
|
||||
"model \"models/objects/r_explode/tris.md2\" framestart=0 frames=15 skin=-1 fullbright noshadow\n"
|
||||
"}\n"
|
||||
"r_part teq2ex_explosion2_nl\n"
|
||||
"{ // ditto\n"
|
||||
"assoc std_explosion_particles\n"
|
||||
"sound \"weapons/rocklx1a.wav\" 1 1 0 0\n"
|
||||
"model \"models/objects/r_explode/tris.md2\" framestart=15 frames=15 skin=-1 fullbright noshadow\n"
|
||||
"}\n"
|
||||
"r_part ef_trackershell\n"
|
||||
"{ // the black glob model thing\n"
|
||||
"model \"models/objects/r_explode/tris.md2\" framestart=30 frames=19 skin=-1 fullbright noshadow\n"
|
||||
"}\n"
|
||||
"r_part ev_ladder_step\n"
|
||||
"{\n"
|
||||
"sound \"player/steps/ladder1.wav\" 1 1 0 0 1\n"
|
||||
"sound \"player/steps/ladder2.wav\" 1 1 0 0 1\n"
|
||||
"sound \"player/steps/ladder3.wav\" 1 1 0 0 1\n"
|
||||
"sound \"player/steps/ladder4.wav\" 1 1 0 0 1\n"
|
||||
"sound \"player/steps/ladder5.wav\" 1 1 0 0 1\n"
|
||||
"}\n"
|
||||
;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -295,27 +295,30 @@ static char *q2sb_nums[2][11] =
|
|||
|
||||
static mpic_t *Sbar_Q2CachePic(char *name)
|
||||
{
|
||||
mpic_t *pic = R2D_SafeCachePic(va("pics/%s.pcx", name));
|
||||
mpic_t *pic = R2D_SafeCachePic(strncmp(name, "../", 3)?va("pics/%s.pcx", name):va("%s.pcx", name+3));
|
||||
#if defined(IMAGEFMT_PCX)
|
||||
int xmin,ymin,swidth,sheight;
|
||||
size_t length;
|
||||
pcx_t *pcx = (pcx_t*)COM_LoadTempFile(va("pics/%s.pcx", name), 0, &length);
|
||||
if (pcx && length >= sizeof(*pcx))
|
||||
if (pic->width == 0 && pic->height == 0)
|
||||
{
|
||||
xmin = LittleShort(pcx->xmin);
|
||||
ymin = LittleShort(pcx->ymin);
|
||||
swidth = LittleShort(pcx->xmax)-xmin+1;
|
||||
sheight = LittleShort(pcx->ymax)-ymin+1;
|
||||
|
||||
if (pcx->manufacturer == 0x0a
|
||||
&& pcx->version == 5
|
||||
&& pcx->encoding == 1
|
||||
&& pcx->bits_per_pixel == 8
|
||||
&& swidth <= 1024
|
||||
&& sheight <= 1024)
|
||||
int xmin,ymin,swidth,sheight;
|
||||
size_t length;
|
||||
pcx_t *pcx = (pcx_t*)COM_LoadTempFile(strncmp(name, "../", 3)?va("pics/%s.pcx", name):va("%s.pcx", name+3), 0, &length);
|
||||
if (pcx && length >= sizeof(*pcx))
|
||||
{
|
||||
pic->width = swidth;
|
||||
pic->height = sheight;
|
||||
xmin = LittleShort(pcx->xmin);
|
||||
ymin = LittleShort(pcx->ymin);
|
||||
swidth = LittleShort(pcx->xmax)-xmin+1;
|
||||
sheight = LittleShort(pcx->ymax)-ymin+1;
|
||||
|
||||
if (pcx->manufacturer == 0x0a
|
||||
&& pcx->version == 5
|
||||
&& pcx->encoding == 1
|
||||
&& pcx->bits_per_pixel == 8
|
||||
&& swidth <= 1024
|
||||
&& sheight <= 1024)
|
||||
{
|
||||
pic->width = swidth;
|
||||
pic->height = sheight;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -398,7 +401,7 @@ void Sbar_ExecuteLayoutString (char *s, int seat)
|
|||
int pw, ph;
|
||||
// q2clientinfo_t *ci;
|
||||
mpic_t *p;
|
||||
q2player_state_t *ps = &cl.q2frame.playerstate[seat];
|
||||
q2player_state_t *ps = &cl.q2frame.seat[seat].playerstate;
|
||||
|
||||
if (cls.state != ca_active)
|
||||
return;
|
||||
|
@ -561,8 +564,9 @@ void Sbar_ExecuteLayoutString (char *s, int seat)
|
|||
s = COM_Parse (s);
|
||||
index = atoi(com_token);
|
||||
if (index < 0 || index >= countof(ps->stats))
|
||||
Host_EndGame ("Bad stat index");
|
||||
value = ps->stats[index];
|
||||
value = 0;
|
||||
else
|
||||
value = ps->stats[index];
|
||||
SCR_DrawField (x, y, 0, width, value);
|
||||
continue;
|
||||
}
|
||||
|
@ -680,8 +684,9 @@ void Sbar_ExecuteLayoutString (char *s, int seat)
|
|||
s = COM_Parse (s);
|
||||
index = atoi(com_token);
|
||||
if (index < 0 || index >= countof(ps->stats))
|
||||
Host_EndGame ("Bad stat index");
|
||||
value = ps->stats[index];
|
||||
value = 0;
|
||||
else
|
||||
value = ps->stats[index];
|
||||
if (!value)
|
||||
{ // skip to endif
|
||||
while (s && strcmp(com_token, "endif") )
|
||||
|
@ -710,13 +715,14 @@ static void Sbar_Q2DrawInventory(int seat)
|
|||
int keys[1], keymods[1];
|
||||
char cmd[1024];
|
||||
const char *boundkey;
|
||||
q2player_state_t *ps = &cl.q2frame.playerstate[seat];
|
||||
q2player_state_t *ps = &cl.q2frame.seat[seat].playerstate;
|
||||
unsigned int validlist[Q2MAX_ITEMS], rows, i, item, selected = ps->stats[Q2STAT_SELECTED_ITEM];
|
||||
int first;
|
||||
unsigned int maxrows = ((240-24*2-8*2)/8);
|
||||
//draw background
|
||||
float x = sbar_rect.x + (sbar_rect.width - 256)/2;
|
||||
float y = sbar_rect.y + (sbar_rect.height - 240)/2;
|
||||
int deflang = TL_FindLanguage(""); //ffs... read: english
|
||||
if (y < sbar_rect.y)
|
||||
y = sbar_rect.y; //try to fix small-res 3-way splitscreen slightly
|
||||
R2D_ScalePic(x, y, 256, 240, Sbar_Q2CachePic("inventory"));
|
||||
|
@ -745,13 +751,13 @@ static void Sbar_Q2DrawInventory(int seat)
|
|||
{
|
||||
item = validlist[i];
|
||||
|
||||
Q_snprintfz(cmd, sizeof(cmd), "use %s", Get_Q2ConfigString(Q2CS_ITEMS+item));
|
||||
Q_snprintfz(cmd, sizeof(cmd), "use %s", TL_Translate(deflang, Get_Q2ConfigString(Q2CS_ITEMS+item)));
|
||||
if (!M_FindKeysForCommand(0, 0, cmd, keys, keymods, countof(keys)))
|
||||
boundkey = ""; //we don't actually know which ones can be selected at all.
|
||||
else
|
||||
boundkey = Key_KeynumToString(keys[0], keymods[0]);
|
||||
|
||||
Q_snprintfz(cmd, sizeof(cmd), "%6s %3i %s", boundkey, cl.inventory[seat][item], Get_Q2ConfigString(Q2CS_ITEMS+item));
|
||||
Q_snprintfz(cmd, sizeof(cmd), "%6s %3i %s", boundkey, cl.inventory[seat][item], TL_Translate(com_language, Get_Q2ConfigString(Q2CS_ITEMS+item)));
|
||||
Draw_FunStringWidth(x, y, cmd, 256-24*2+8, false, item != selected); y+=8;
|
||||
}
|
||||
}
|
||||
|
@ -3052,9 +3058,9 @@ void Sbar_Draw (playerview_t *pv)
|
|||
R2D_ImageColours(1, 1, 1, 1);
|
||||
if (*cl.q2statusbar)
|
||||
Sbar_ExecuteLayoutString(cl.q2statusbar, seat);
|
||||
if (cl.q2frame.playerstate[seat].stats[Q2STAT_LAYOUTS] & 1)
|
||||
if (*cl.q2layout && (cl.q2frame.seat[seat].playerstate.stats[Q2STAT_LAYOUTS] & 1))
|
||||
Sbar_ExecuteLayoutString(cl.q2layout[seat], seat);
|
||||
if (cl.q2frame.playerstate[seat].stats[Q2STAT_LAYOUTS] & 2)
|
||||
if (cl.q2frame.seat[seat].playerstate.stats[Q2STAT_LAYOUTS] & 2)
|
||||
Sbar_Q2DrawInventory(seat);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -469,6 +469,7 @@ void Skin_NextDownload (void)
|
|||
int j;
|
||||
char *slash;
|
||||
char *skinname;
|
||||
char *dogtag;
|
||||
for (i = 0; i != MAX_CLIENTS; i++)
|
||||
{
|
||||
sc = &cl.players[i];
|
||||
|
@ -479,6 +480,11 @@ void Skin_NextDownload (void)
|
|||
if (slash)
|
||||
{
|
||||
*slash = 0;
|
||||
|
||||
dogtag = strchr(slash+1, '\\'); //q2e
|
||||
if (dogtag)
|
||||
*dogtag++ = 0;
|
||||
|
||||
CL_CheckOrEnqueDownloadFile(va("players/%s/tris.md2", skinname), NULL, 0);
|
||||
for (j = 1; j < MAX_PRECACHE_MODELS; j++)
|
||||
{
|
||||
|
|
|
@ -397,7 +397,7 @@ typedef struct q2miptex_s
|
|||
#define SANITY_MAX_MAP_BRUSHES (~0u/sizeof(*out))
|
||||
#define SANITY_MAX_MAP_LEAFFACES 262144 //sanity only
|
||||
|
||||
#define MAX_Q2MAP_AREAS 256
|
||||
#define MAX_Q2MAP_AREAS (MAX_MAP_AREA_BYTES*8)
|
||||
#define MAX_Q2MAP_AREAPORTALS 1024
|
||||
//#define MAX_Q2MAP_VERTS MAX_MAP_VERTS
|
||||
//#define MAX_Q2MAP_FACES MAX_MAP_FACES
|
||||
|
|
|
@ -1277,7 +1277,7 @@ int MSG_ReadSize16 (sizebuf_t *sb)
|
|||
return solid;
|
||||
}
|
||||
}
|
||||
void MSG_WriteSize16 (sizebuf_t *sb, int sz)
|
||||
void MSG_WriteSize16 (sizebuf_t *sb, unsigned int sz)
|
||||
{
|
||||
if (sz == ES_SOLID_BSP)
|
||||
MSG_WriteShort(sb, ES_SOLID_BSP);
|
||||
|
@ -1297,12 +1297,25 @@ void MSG_WriteSize16 (sizebuf_t *sb, int sz)
|
|||
}
|
||||
void COM_DecodeSize(int solid, float *mins, float *maxs)
|
||||
{
|
||||
#if 1
|
||||
#if 0
|
||||
//q2e 32bit-encoding
|
||||
int x,y,d,u;
|
||||
x = (solid>>0)&0xff;
|
||||
y = (solid>>8)&0xff;
|
||||
d = (solid>>16)&0xff;
|
||||
u = (solid>>24)&0xff;
|
||||
|
||||
mins[0] = -x; maxs[0] = x;
|
||||
mins[1] = -y; maxs[1] = y;
|
||||
mins[2] = -d; maxs[2] = u - 32;
|
||||
#elif 1
|
||||
//r1q2/q2pro 32bit-encoding
|
||||
maxs[0] = maxs[1] = solid & 255;
|
||||
mins[0] = mins[1] = -maxs[0];
|
||||
mins[2] = -((solid>>8) & 255);
|
||||
maxs[2] = ((solid>>16) & 65535) - 32768;
|
||||
#else
|
||||
//classic q2 16-bit encoding.
|
||||
maxs[0] = maxs[1] = 8*(solid & 31);
|
||||
mins[0] = mins[1] = -maxs[0];
|
||||
mins[2] = -8*((solid>>5) & 31);
|
||||
|
@ -1319,6 +1332,7 @@ int COM_EncodeSize(const float *mins, const float *maxs)
|
|||
if (solid == 0x80000000)
|
||||
solid = 0; //point sized stuff should just be non-solid. you'll thank me for splitscreens.
|
||||
#else
|
||||
//vanilla q2
|
||||
solid = bound(0, (int)-mins[0]/8, 31);
|
||||
solid |= bound(0, (int)-mins[2]/8, 31)<<5;
|
||||
solid |= bound(0, (int)((maxs[2]+32)/8), 63)<<10; /*up can be negative*/;
|
||||
|
@ -1385,6 +1399,51 @@ unsigned int MSGCL_ReadEntity(void)
|
|||
#endif
|
||||
|
||||
#if defined(Q2CLIENT) && defined(HAVE_CLIENT)
|
||||
void MSGQ2EX_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const usercmd_t *cmd)
|
||||
{
|
||||
unsigned int bits = 0;
|
||||
// unsigned char buttons = 0;
|
||||
if (cmd->angles[0] != from->angles[0])
|
||||
bits |= Q2CM_ANGLE1;
|
||||
if (cmd->angles[1] != from->angles[1])
|
||||
bits |= Q2CM_ANGLE2;
|
||||
if (cmd->angles[2] != from->angles[2])
|
||||
bits |= Q2CM_ANGLE3;
|
||||
if (cmd->forwardmove != from->forwardmove)
|
||||
bits |= Q2CM_FORWARD;
|
||||
if (cmd->sidemove != from->sidemove)
|
||||
bits |= Q2CM_SIDE;
|
||||
// if (cmd->upmove != from->upmove)
|
||||
// bits |= Q2CM_UP;
|
||||
if (cmd->buttons != from->buttons)
|
||||
bits |= Q2CM_BUTTONS;
|
||||
// if (cmd->impulse != from->impulse)
|
||||
// bits |= Q2CM_IMPULSE;
|
||||
|
||||
MSG_WriteByte (buf, bits);
|
||||
|
||||
if (bits & Q2CM_ANGLE1)
|
||||
MSG_WriteFloat (buf, SHORT2ANGLE(cmd->angles[0]));
|
||||
if (bits & Q2CM_ANGLE2)
|
||||
MSG_WriteFloat (buf, SHORT2ANGLE(cmd->angles[1]));
|
||||
if (bits & Q2CM_ANGLE3)
|
||||
MSG_WriteFloat (buf, SHORT2ANGLE(cmd->angles[2]));
|
||||
|
||||
if (bits & Q2CM_FORWARD)
|
||||
MSG_WriteFloat (buf, cmd->forwardmove);
|
||||
if (bits & Q2CM_SIDE)
|
||||
MSG_WriteFloat (buf, cmd->sidemove);
|
||||
// if (bits & Q2CM_UP)
|
||||
// MSG_WriteFloat (buf, cmd->upmove);
|
||||
|
||||
if (bits & Q2CM_BUTTONS)
|
||||
MSG_WriteByte (buf, cmd->buttons);
|
||||
//if (bits & Q2CM_IMPULSE)
|
||||
// MSG_WriteByte (buf, cmd->impulse);
|
||||
MSG_WriteByte (buf, bound(0, cmd->msec, 250)); //clamp msecs to 250, because r1q2 likes kicking us if we stall for any reason
|
||||
|
||||
// MSG_WriteByte (buf, cmd->lightlevel);
|
||||
}
|
||||
void MSGQ2_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const usercmd_t *cmd)
|
||||
{
|
||||
unsigned int bits = 0;
|
||||
|
@ -1894,7 +1953,12 @@ void MSGCL_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const userc
|
|||
{
|
||||
#if defined(Q2CLIENT)
|
||||
if (cls_state && cls.protocol == CP_QUAKE2)
|
||||
MSGQ2_WriteDeltaUsercmd(buf, from, cmd);
|
||||
{
|
||||
if (cls.protocol_q2 == PROTOCOL_VERSION_Q2EX)
|
||||
MSGQ2EX_WriteDeltaUsercmd(buf, from, cmd);
|
||||
else
|
||||
MSGQ2_WriteDeltaUsercmd(buf, from, cmd);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
MSGQW_WriteDeltaUsercmd(buf, from, cmd);
|
||||
|
@ -1906,7 +1970,7 @@ void MSGCL_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const userc
|
|||
//
|
||||
qboolean msg_badread;
|
||||
struct netprim_s msg_nullnetprim;
|
||||
static sizebuf_t *msg_readmsg;
|
||||
sizebuf_t *msg_readmsg;
|
||||
|
||||
void MSG_BeginReading (sizebuf_t *sb, struct netprim_s prim)
|
||||
{
|
||||
|
@ -2414,7 +2478,7 @@ float MSG_ReadCoordFloat (void)
|
|||
return MSG_FromCoord(c, COORDTYPE_FLOAT_32);
|
||||
}
|
||||
|
||||
void MSG_ReadPos (float pos[3])
|
||||
void MSG_ReadPos (float *pos)
|
||||
{
|
||||
pos[0] = MSG_ReadCoord();
|
||||
pos[1] = MSG_ReadCoord();
|
||||
|
@ -2561,7 +2625,7 @@ void MSGQW_ReadDeltaUsercmd (const usercmd_t *from, usercmd_t *move, int protove
|
|||
}
|
||||
}
|
||||
|
||||
void MSGQ2_ReadDeltaUsercmd (const usercmd_t *from, usercmd_t *move)
|
||||
void MSGQ2_ReadDeltaUsercmd (client_t *cl, const usercmd_t *from, usercmd_t *move)
|
||||
{
|
||||
int bits;
|
||||
unsigned int buttons = 0;
|
||||
|
@ -2573,63 +2637,97 @@ void MSGQ2_ReadDeltaUsercmd (const usercmd_t *from, usercmd_t *move)
|
|||
if (msg_readmsg->prim.flags & NPQ2_R1Q2_UCMD)
|
||||
buttons = MSG_ReadByte();
|
||||
|
||||
// read current angles
|
||||
if (bits & Q2CM_ANGLE1)
|
||||
if (cl->protocol == SCP_QUAKE2EX)
|
||||
{
|
||||
if (buttons & R1Q2_BUTTON_BYTE_ANGLE1)
|
||||
move->angles[0] = MSG_ReadChar ()*64;
|
||||
else
|
||||
move->angles[0] = MSG_ReadShort ();
|
||||
}
|
||||
if (bits & Q2CM_ANGLE2)
|
||||
{
|
||||
if (buttons & R1Q2_BUTTON_BYTE_ANGLE2)
|
||||
move->angles[1] = MSG_ReadChar ()*256;
|
||||
else
|
||||
move->angles[1] = MSG_ReadShort ();
|
||||
}
|
||||
if (bits & Q2CM_ANGLE3)
|
||||
move->angles[2] = MSG_ReadShort ();
|
||||
if (bits & Q2CM_ANGLE1)
|
||||
move->angles[0] = ANGLE2SHORT(MSG_ReadFloat());
|
||||
if (bits & Q2CM_ANGLE2)
|
||||
move->angles[1] = ANGLE2SHORT(MSG_ReadFloat());
|
||||
if (bits & Q2CM_ANGLE3)
|
||||
move->angles[2] = ANGLE2SHORT(MSG_ReadFloat());
|
||||
|
||||
// read movement
|
||||
if (bits & Q2CM_FORWARD)
|
||||
{
|
||||
if (buttons & R1Q2_BUTTON_BYTE_FORWARD)
|
||||
move->forwardmove = MSG_ReadChar ()*5;
|
||||
else
|
||||
move->forwardmove = MSG_ReadShort ();
|
||||
}
|
||||
if (bits & Q2CM_SIDE)
|
||||
{
|
||||
if (buttons & R1Q2_BUTTON_BYTE_SIDE)
|
||||
move->sidemove = MSG_ReadChar ()*5;
|
||||
else
|
||||
move->sidemove = MSG_ReadShort ();
|
||||
}
|
||||
if (bits & Q2CM_UP)
|
||||
{
|
||||
if (buttons & R1Q2_BUTTON_BYTE_UP)
|
||||
move->upmove = MSG_ReadChar ()*5;
|
||||
else
|
||||
move->upmove = MSG_ReadShort ();
|
||||
}
|
||||
// read movement
|
||||
if (bits & Q2CM_FORWARD)
|
||||
move->forwardmove = MSG_ReadFloat ();
|
||||
if (bits & Q2CM_SIDE)
|
||||
move->sidemove = MSG_ReadFloat();
|
||||
if (bits & Q2CM_UP)
|
||||
Con_DPrintf("Q2CM_UP unexpected\n");
|
||||
|
||||
// read buttons
|
||||
if (bits & Q2CM_BUTTONS)
|
||||
{
|
||||
if (msg_readmsg->prim.flags & NPQ2_R1Q2_UCMD)
|
||||
move->buttons = buttons & (1|2|128); //only use the bits that are actually buttons, so gamecode can't get excited despite being crippled by this.
|
||||
else
|
||||
if (bits & Q2CM_BUTTONS)
|
||||
move->buttons = MSG_ReadByte ();
|
||||
|
||||
if (bits & Q2CM_IMPULSE/*repurposed*/)
|
||||
move->sequence = MSG_ReadLong();
|
||||
|
||||
if (move->buttons & (1<<3))
|
||||
move->upmove = 200;
|
||||
else if (move->buttons & (1<<4))
|
||||
move->upmove = -200;
|
||||
}
|
||||
else
|
||||
{
|
||||
// read current angles
|
||||
if (bits & Q2CM_ANGLE1)
|
||||
{
|
||||
if (buttons & R1Q2_BUTTON_BYTE_ANGLE1)
|
||||
move->angles[0] = MSG_ReadChar ()*64;
|
||||
else
|
||||
move->angles[0] = MSG_ReadShort ();
|
||||
}
|
||||
if (bits & Q2CM_ANGLE2)
|
||||
{
|
||||
if (buttons & R1Q2_BUTTON_BYTE_ANGLE2)
|
||||
move->angles[1] = MSG_ReadChar ()*256;
|
||||
else
|
||||
move->angles[1] = MSG_ReadShort ();
|
||||
}
|
||||
if (bits & Q2CM_ANGLE3)
|
||||
move->angles[2] = MSG_ReadShort ();
|
||||
|
||||
// read movement
|
||||
if (bits & Q2CM_FORWARD)
|
||||
{
|
||||
if (buttons & R1Q2_BUTTON_BYTE_FORWARD)
|
||||
move->forwardmove = MSG_ReadChar ()*5;
|
||||
else
|
||||
move->forwardmove = MSG_ReadShort ();
|
||||
}
|
||||
if (bits & Q2CM_SIDE)
|
||||
{
|
||||
if (buttons & R1Q2_BUTTON_BYTE_SIDE)
|
||||
move->sidemove = MSG_ReadChar ()*5;
|
||||
else
|
||||
move->sidemove = MSG_ReadShort ();
|
||||
}
|
||||
if (bits & Q2CM_UP)
|
||||
{
|
||||
if (buttons & R1Q2_BUTTON_BYTE_UP)
|
||||
move->upmove = MSG_ReadChar ()*5;
|
||||
else
|
||||
move->upmove = MSG_ReadShort ();
|
||||
}
|
||||
|
||||
// read buttons
|
||||
if (bits & Q2CM_BUTTONS)
|
||||
{
|
||||
if (msg_readmsg->prim.flags & NPQ2_R1Q2_UCMD)
|
||||
move->buttons = buttons & (1|2|128); //only use the bits that are actually buttons, so gamecode can't get excited despite being crippled by this.
|
||||
else
|
||||
move->buttons = MSG_ReadByte ();
|
||||
}
|
||||
|
||||
if (bits & Q2CM_IMPULSE)
|
||||
move->impulse = MSG_ReadByte ();
|
||||
}
|
||||
|
||||
if (bits & Q2CM_IMPULSE)
|
||||
move->impulse = MSG_ReadByte ();
|
||||
|
||||
// read time to run command
|
||||
// read time to run command
|
||||
move->msec = MSG_ReadByte ();
|
||||
|
||||
move->lightlevel = MSG_ReadByte ();
|
||||
if (cl->protocol == SCP_QUAKE2EX)
|
||||
move->lightlevel = 255; //light level removed.
|
||||
else
|
||||
move->lightlevel = MSG_ReadByte ();
|
||||
}
|
||||
|
||||
void MSG_ReadData (void *data, int len)
|
||||
|
@ -5961,6 +6059,10 @@ static struct com_work_s
|
|||
size_t a;
|
||||
size_t b;
|
||||
} *com_work_head[WG_COUNT], *com_work_tail[WG_COUNT];
|
||||
unsigned int COM_HasWorkers(wgroup_t tg)
|
||||
{ //simply returns if adding work will block or not (and a hint for how many jobs should be queued at once).
|
||||
return com_liveworkers[tg];
|
||||
}
|
||||
//return if there's *any* loading that needs to be done anywhere.
|
||||
qboolean COM_HasWork(void)
|
||||
{
|
||||
|
@ -6871,6 +6973,175 @@ unsigned int COM_RemapMapChecksum(model_t *model, unsigned int checksum)
|
|||
{"maps/dm5.bsp", 0xD651996F, /*0x2DB66BBC,*/ 0xB02D48FD},
|
||||
{"maps/dm6.bsp", 0x33F7D9C9, /*0x0EBB386D,*/ 0x5208DA2B},
|
||||
// {"maps/end.bsp", 0x3C87824B, /*0xA66198D8,*/ 0xBBD4B4A5},
|
||||
|
||||
//Quake2 Rerelease.
|
||||
//These are listed to remap the rerelease's crc32 checksums from the vanilla maps to the rerelease, so q2e can connect to regular servers.
|
||||
//the reverse is not a concern as there's too many translation errors that way anyway.
|
||||
//yes this is kinda backwards vs the q1 stuff above.
|
||||
|
||||
//MAP NAME VAN+fmd4 VAN+crc32 REMST+fmd4 REMST+crc32
|
||||
//base12/pak0
|
||||
// {"maps/base1.bsp", /*0x0,*/ 0xc49cac93, /*0x0,*/ 0x8939212b}, //expanded area and some wallhacky bits and areaportal screwups
|
||||
//{"maps/base2.bsp", /*0x0,*/ 0x49ed539e, /*0x0,*/ 0xda61be7b},
|
||||
//{"maps/base3.bsp", /*0x0,*/ 0xf29055e4, /*0x0,*/ 0x13ac20a1},
|
||||
//{"maps/biggun.bsp", /*0x0,*/ 0x0b95a4ae, /*0x0,*/ 0x7cae003f},
|
||||
//{"maps/boss1.bsp", /*0x0,*/ 0x7a52514a, /*0x0,*/ 0xeeff1917},
|
||||
//{"maps/boss2.bsp", /*0x0,*/ 0x81ac4371, /*0x0,*/ 0x7b6392d6},
|
||||
//{"maps/bunk1.bsp", /*0x0,*/ 0xa37f1a6d, /*0x0,*/ 0xe529ac52},
|
||||
//{"maps/city1.bsp", /*0x0,*/ 0x4fd6239b, /*0x0,*/ 0x8876eb6a},
|
||||
//{"maps/city2.bsp", /*0x0,*/ 0x6f7768d8, /*0x0,*/ 0xd0797f11},
|
||||
//{"maps/city3.bsp", /*0x0,*/ 0x3809bd4e, /*0x0,*/ 0xb7135bdd},
|
||||
//{"maps/command.bsp", /*0x0,*/ 0x80d7b67c, /*0x0,*/ 0x66e404f5},
|
||||
//{"maps/cool1.bsp", /*0x0,*/ 0xeabfd863, /*0x0,*/ 0xbbe51fc9},
|
||||
//{"maps/fact1.bsp", /*0x0,*/ 0xfba460e5, /*0x0,*/ 0xf9bf8d9f},
|
||||
//{"maps/fact2.bsp", /*0x0,*/ 0x6655c1a5, /*0x0,*/ 0xb2cc8d37},
|
||||
//{"maps/fact3.bsp", /*0x0,*/ 0xabe9c595, /*0x0,*/ 0xb64f87d4},
|
||||
//{"maps/hangar1.bsp", /*0x0,*/ 0x5893e66d, /*0x0,*/ 0x1334d867},
|
||||
//{"maps/hangar2.bsp", /*0x0,*/ 0x933c0a95, /*0x0,*/ 0x077e9ba3},
|
||||
//{"maps/jail1.bsp", /*0x0,*/ 0xee5e64ec, /*0x0,*/ 0x158a1107},
|
||||
//{"maps/jail2.bsp", /*0x0,*/ 0x154ae1bf, /*0x0,*/ 0x2921f388},
|
||||
//{"maps/jail3.bsp", /*0x0,*/ 0x8f3de333, /*0x0,*/ 0x32554a02},
|
||||
//{"maps/jail4.bsp", /*0x0,*/ 0xe66ec160, /*0x0,*/ 0xb1013e3b},
|
||||
//{"maps/jail5.bsp", /*0x0,*/ 0x3af55df6, /*0x0,*/ 0xbd077c5b},
|
||||
//{"maps/lab.bsp", /*0x0,*/ 0xf2bc9c9a, /*0x0,*/ 0x4eea0f97},
|
||||
//{"maps/mine1.bsp", /*0x0,*/ 0x31db729e, /*0x0,*/ 0x5fc5f3cf},
|
||||
//{"maps/mine2.bsp", /*0x0,*/ 0xf8c3c330, /*0x0,*/ 0x35eacacb},
|
||||
//{"maps/mine3.bsp", /*0x0,*/ 0x1ba1ba64, /*0x0,*/ 0x6c8e3f66},
|
||||
//{"maps/mine4.bsp", /*0x0,*/ 0x6d4d9c98, /*0x0,*/ 0x48a30d5d},
|
||||
//{"maps/mintro.bsp", /*0x0,*/ 0x15bcf39c, /*0x0,*/ 0xfb72d23f},
|
||||
//{"maps/power1.bsp", /*0x0,*/ 0x6e9407f7, /*0x0,*/ 0x8d15b695},
|
||||
//{"maps/power2.bsp", /*0x0,*/ 0xd64d63b5, /*0x0,*/ 0xcf9fd9f5},
|
||||
//{"maps/security.bsp", /*0x0,*/ 0xc75d06ff, /*0x0,*/ 0xcb7a0229},
|
||||
//{"maps/space.bsp", /*0x0,*/ 0xe9b1ca59, /*0x0,*/ 0x34678329},
|
||||
//{"maps/strike.bsp", /*0x0,*/ 0x373acf3b, /*0x0,*/ 0x1e6aa8da},
|
||||
//{"maps/train.bsp", /*0x0,*/ 0x339a6bf3, /*0x0,*/ 0x1c6b7d5c},
|
||||
//{"maps/ware1.bsp", /*0x0,*/ 0x039d00bc, /*0x0,*/ 0x34713cb1},
|
||||
//{"maps/ware2.bsp", /*0x0,*/ 0xe25b761e, /*0x0,*/ 0x00c06d11},
|
||||
//{"maps/waste1.bsp", /*0x0,*/ 0x14f41c2e, /*0x0,*/ 0x33dd40ff},
|
||||
//{"maps/waste2.bsp", /*0x0,*/ 0x91267752, /*0x0,*/ 0x5b53de97},
|
||||
//{"maps/waste3.bsp", /*0x0,*/ 0x7658206d, /*0x0,*/ 0x80101af0},
|
||||
|
||||
//baseq2/pak1.pak
|
||||
{"maps/q2dm1.bsp", /*0x0,*/ 0x6cc8eda7, /*0x0,*/ 0x23393278},
|
||||
{"maps/q2dm2.bsp", /*0x0,*/ 0x60a8b392, /*0x0,*/ 0x2f03a689},
|
||||
// {"maps/q2dm3.bsp", /*0x0,*/ 0xdc3aac9b, /*0x0,*/ 0x378903ee}, //bmodel snafus
|
||||
{"maps/q2dm4.bsp", /*0x0,*/ 0x87db6388, /*0x0,*/ 0xa6b504da},
|
||||
{"maps/q2dm5.bsp", /*0x0,*/ 0x7da73bb5, /*0x0,*/ 0xc639cbb7},
|
||||
{"maps/q2dm6.bsp", /*0x0,*/ 0xc63f6546, /*0x0,*/ 0xbe784b8a},
|
||||
{"maps/q2dm7.bsp", /*0x0,*/ 0x39f11899, /*0x0,*/ 0xea6ac852},
|
||||
// {"maps/q2dm8.bsp", /*0x0,*/ 0x8659ee44, /*0x0,*/ 0x09a423b2}, //crates are missing
|
||||
|
||||
// //one-offs
|
||||
// {"maps/base64.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x7db2883f},
|
||||
// {"maps/city64.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x635eb291},
|
||||
// {"maps/sewer64.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x46da9e37},
|
||||
//mg
|
||||
// {"maps/mgdm1.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x826e737a},
|
||||
// {"maps/mgu1m1.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0xc27e2cef},
|
||||
// {"maps/mgu1m2.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x1ec516fa},
|
||||
// {"maps/mgu1m3.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0xb9f13047},
|
||||
// {"maps/mgu1m4.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x8211337e},
|
||||
// {"maps/mgu1m5.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x1549c505},
|
||||
// {"maps/mgu1trial.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x0f75a608},
|
||||
// {"maps/mgu2m1.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x4a769bb0},
|
||||
// {"maps/mgu2m2.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0xd307cad8},
|
||||
// {"maps/mgu2m3.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0xd9352a68},
|
||||
// {"maps/mgu3m1.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x5ab2ea83},
|
||||
// {"maps/mgu3m2.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x4952301e},
|
||||
// {"maps/mgu3m3.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x7ed253fa},
|
||||
// {"maps/mgu3m4.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0xc91edb2e},
|
||||
// {"maps/mgu3secret.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0xdb50aa0d},
|
||||
// {"maps/mgu4m1.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x5558556a},
|
||||
// {"maps/mgu4m2.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x32090016},
|
||||
// {"maps/mgu4m3.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0xa60d1e9a},
|
||||
// {"maps/mgu4trial.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x5cb612d1},
|
||||
// {"maps/mgu5m1.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x60d40817},
|
||||
// {"maps/mgu5m2.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x88083b2f},
|
||||
// {"maps/mgu5m3.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x4dc5140a},
|
||||
// {"maps/mgu5trial.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x4808e583},
|
||||
// {"maps/mgu6m1.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0xbcc16455},
|
||||
// {"maps/mgu6m2.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x6313d469},
|
||||
// {"maps/mgu6m3.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x2651b5f7},
|
||||
// {"maps/mgu6trial.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0xfabf1b9f},
|
||||
// {"maps/mguboss.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x12733e70},
|
||||
// {"maps/mguhub.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x51fbdd73},
|
||||
//
|
||||
// //new
|
||||
// {"maps/ndctf0.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0xa8c81b2b},
|
||||
// {"maps/q2kctf1.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x8d176d56},
|
||||
// {"maps/q2kctf2.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x01a32428},
|
||||
// {"maps/tutorial.bsp", /*0x0,*/ 0x0, /*0x0,*/ 0x8869d954},
|
||||
|
||||
//q2ctf maps
|
||||
//{"maps/q2ctf1.bsp", /*0x0,*/ 0xe067a203, /*0x0,*/ 0x6143b5e7},
|
||||
//{"maps/q2ctf2.bsp", /*0x0,*/ 0x28030fe8, /*0x0,*/ 0x5c71d212},
|
||||
//{"maps/q2ctf3.bsp", /*0x0,*/ 0xca29c6a3, /*0x0,*/ 0x59bb4823},
|
||||
//{"maps/q2ctf4.bsp", /*0x0,*/ 0x2fa28832, /*0x0,*/ 0x63fef5de},
|
||||
//{"maps/q2ctf5.bsp", /*0x0,*/ 0x033ccd79, /*0x0,*/ 0x98116fdd},
|
||||
// {"maps/q2ctf6.bsp", /*0x0,*/ 0xe0f199b9, /*0x0,*/ 0x0}, //no idea why these are missing in the rerelease..
|
||||
// {"maps/q2ctf7.bsp", /*0x0,*/ 0x390abd05, /*0x0,*/ 0x0},
|
||||
// {"maps/q2ctf8.bsp", /*0x0,*/ 0x3ba7c491, /*0x0,*/ 0x0},
|
||||
|
||||
//xatrix maps
|
||||
//{"maps/badlands.bsp", /*0x0,*/ 0xafa0e22e, /*0x0,*/ 0x203ffacb},
|
||||
//{"maps/industry.bsp", /*0x0,*/ 0x876bd244, /*0x0,*/ 0x3cf0c2bd},
|
||||
//{"maps/outbase.bsp", /*0x0,*/ 0xe7531d00, /*0x0,*/ 0x1c36a9e0},
|
||||
//{"maps/refinery.bsp", /*0x0,*/ 0xe4e81e7b, /*0x0,*/ 0xaf61d172},
|
||||
//{"maps/w_treat.bsp", /*0x0,*/ 0xde9eb38c, /*0x0,*/ 0x4a3685fe},
|
||||
//{"maps/xcompnd1.bsp", /*0x0,*/ 0xb3540a91, /*0x0,*/ 0x24bc9f6f},
|
||||
//{"maps/xcompnd2.bsp", /*0x0,*/ 0xe4745192, /*0x0,*/ 0x55df1931},
|
||||
//{"maps/xdm1.bsp", /*0x0,*/ 0x3d48b316, /*0x0,*/ 0x26a71790},
|
||||
//{"maps/xdm2.bsp", /*0x0,*/ 0x1152e7c4, /*0x0,*/ 0x11db3085},
|
||||
//{"maps/xdm3.bsp", /*0x0,*/ 0xdb97aeac, /*0x0,*/ 0xb60a8631},
|
||||
//{"maps/xdm4.bsp", /*0x0,*/ 0xeef68945, /*0x0,*/ 0x6e070a92},
|
||||
//{"maps/xdm5.bsp", /*0x0,*/ 0x47c1f3a3, /*0x0,*/ 0x558d4dd6},
|
||||
//{"maps/xdm6.bsp", /*0x0,*/ 0x852def91, /*0x0,*/ 0x3cb70b50},
|
||||
//{"maps/xdm7.bsp", /*0x0,*/ 0xc4d93896, /*0x0,*/ 0xc0de3235},
|
||||
//{"maps/xhangar1.bsp", /*0x0,*/ 0x9e18dceb, /*0x0,*/ 0x10de03f6},
|
||||
//{"maps/xhangar2.bsp", /*0x0,*/ 0x781c8f17, /*0x0,*/ 0xd9f92aa3},
|
||||
//{"maps/xintell.bsp", /*0x0,*/ 0x5cf61c9b, /*0x0,*/ 0x2c979acf},
|
||||
//{"maps/xmoon1.bsp", /*0x0,*/ 0xc2ec98f6, /*0x0,*/ 0x57f1373c},
|
||||
//{"maps/xmoon2.bsp", /*0x0,*/ 0x79cdedf8, /*0x0,*/ 0xc2236a38},
|
||||
//{"maps/xreactor.bsp", /*0x0,*/ 0xa32f926d, /*0x0,*/ 0x5dc0db58},
|
||||
//{"maps/xsewer1.bsp", /*0x0,*/ 0x53f393b3, /*0x0,*/ 0x68c01403},
|
||||
//{"maps/xsewer2.bsp", /*0x0,*/ 0xdae8d63f, /*0x0,*/ 0xc78c8261},
|
||||
//{"maps/xship.bsp", /*0x0,*/ 0xcaae64c3, /*0x0,*/ 0x16434a51},
|
||||
//{"maps/xswamp.bsp", /*0x0,*/ 0x7a01ffe3, /*0x0,*/ 0x92852525},
|
||||
//{"maps/xware.bsp", /*0x0,*/ 0x769d834c, /*0x0,*/ 0xa21dad68},
|
||||
|
||||
//(q2) rogue maps
|
||||
//{"maps/rammo1.bsp", /*0x0,*/ 0x157c38b5, /*0x0,*/ 0x70778442},
|
||||
//{"maps/rammo2.bsp", /*0x0,*/ 0xe59eb4f3, /*0x0,*/ 0xb9a6bb64},
|
||||
//{"maps/rbase1.bsp", /*0x0,*/ 0xfe907818, /*0x0,*/ 0xcc316310},
|
||||
//{"maps/rbase2.bsp", /*0x0,*/ 0x6a9f5a26, /*0x0,*/ 0xd148fd82},
|
||||
//{"maps/rboss.bsp", /*0x0,*/ 0x5c3167e7, /*0x0,*/ 0x0ba861c9},
|
||||
//{"maps/rdm1.bsp", /*0x0,*/ 0x9d581b00, /*0x0,*/ 0xcc0dc613},
|
||||
//{"maps/rdm2.bsp", /*0x0,*/ 0xcaef085e, /*0x0,*/ 0xcb93d84b},
|
||||
//{"maps/rdm3.bsp", /*0x0,*/ 0xecd65aea, /*0x0,*/ 0x2c334d25},
|
||||
//{"maps/rdm4.bsp", /*0x0,*/ 0xb0e01e67, /*0x0,*/ 0xc9d989ea},
|
||||
//{"maps/rdm5.bsp", /*0x0,*/ 0x998f2929, /*0x0,*/ 0xf4e5d735},
|
||||
//{"maps/rdm6.bsp", /*0x0,*/ 0x06041298, /*0x0,*/ 0x7dc53173},
|
||||
//{"maps/rdm7.bsp", /*0x0,*/ 0x5d1a6d8e, /*0x0,*/ 0x8c618a24},
|
||||
//{"maps/rdm8.bsp", /*0x0,*/ 0x9563932d, /*0x0,*/ 0x07b32d04},
|
||||
//{"maps/rdm9.bsp", /*0x0,*/ 0x6abbd719, /*0x0,*/ 0x726d4859},
|
||||
//{"maps/rdm10.bsp", /*0x0,*/ 0xe5097216, /*0x0,*/ 0x54b0b786},
|
||||
//{"maps/rdm11.bsp", /*0x0,*/ 0x55602288, /*0x0,*/ 0x890dc692},
|
||||
//{"maps/rdm12.bsp", /*0x0,*/ 0xeadab431, /*0x0,*/ 0x762197d8},
|
||||
//{"maps/rdm13.bsp", /*0x0,*/ 0x8b51e2d9, /*0x0,*/ 0x20678587},
|
||||
//{"maps/rdm14.bsp", /*0x0,*/ 0x9f12a7af, /*0x0,*/ 0xe22f5e58},
|
||||
//{"maps/rhangar1.bsp", /*0x0,*/ 0x29f4a50f, /*0x0,*/ 0xf5b1eeee},
|
||||
//{"maps/rhangar2.bsp", /*0x0,*/ 0xfa92ab46, /*0x0,*/ 0x6167fa5e},
|
||||
//{"maps/rlava1.bsp", /*0x0,*/ 0x54a8f40b, /*0x0,*/ 0xa16d41ec},
|
||||
//{"maps/rlava2.bsp", /*0x0,*/ 0x994cec5d, /*0x0,*/ 0x92e9c884},
|
||||
//{"maps/rmine1.bsp", /*0x0,*/ 0xf5e042cf, /*0x0,*/ 0x7a9eb9a8},
|
||||
//{"maps/rmine2.bsp", /*0x0,*/ 0xeb8ddc19, /*0x0,*/ 0xa4e07d51},
|
||||
//{"maps/rsewer1.bsp", /*0x0,*/ 0x934df93c, /*0x0,*/ 0x605443ab},
|
||||
//{"maps/rsewer2.bsp", /*0x0,*/ 0x07e18c79, /*0x0,*/ 0x62513621},
|
||||
// {"maps/runit2.bsp", /*0x0,*/ 0x074e46de, /*0x0,*/ 0x}, //pointless content-skip rooms for coop, I guess
|
||||
// {"maps/runit3.bsp", /*0x0,*/ 0x36c066a7, /*0x0,*/ 0x},
|
||||
// {"maps/runit4.bsp", /*0x0,*/ 0xd31d0e32, /*0x0,*/ 0x},
|
||||
//{"maps/rware1.bsp", /*0x0,*/ 0xbba033a9, /*0x0,*/ 0x031eda0a},
|
||||
//{"maps/rware2.bsp", /*0x0,*/ 0xc2993fed, /*0x0,*/ 0xcba25fcf},
|
||||
};
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(sums)/sizeof(sums[0]); i++)
|
||||
|
|
|
@ -371,18 +371,19 @@ char *MSG_ReadStringLine (void);
|
|||
|
||||
float MSG_ReadCoord (void);
|
||||
float MSG_ReadCoordFloat (void);
|
||||
void MSG_ReadPos (float pos[3]);
|
||||
void MSG_ReadPos (float *pos); //uses md2 normals to approximate a unit vector into a single byte.
|
||||
void MSG_ReadDir (float *dir); //simply 3 coords
|
||||
float MSG_ReadAngle (void);
|
||||
float MSG_ReadAngle16 (void);
|
||||
void MSGQW_ReadDeltaUsercmd (const struct usercmd_s *from, struct usercmd_s *cmd, int qwprotocolver);
|
||||
void MSGFTE_ReadDeltaUsercmd (const struct usercmd_s *from, struct usercmd_s *move);
|
||||
void MSGQ2_ReadDeltaUsercmd (const struct usercmd_s *from, struct usercmd_s *move);
|
||||
void MSGQ2_ReadDeltaUsercmd (struct client_s *cl, const struct usercmd_s *from, struct usercmd_s *move);
|
||||
void MSG_ReadData (void *data, int len);
|
||||
void MSG_ReadSkip (int len);
|
||||
|
||||
|
||||
int MSG_ReadSize16 (sizebuf_t *sb);
|
||||
void MSG_WriteSize16 (sizebuf_t *sb, int sz);
|
||||
void MSG_WriteSize16 (sizebuf_t *sb, unsigned int sz);
|
||||
void COM_DecodeSize(int solid, float *mins, float *maxs);
|
||||
int COM_EncodeSize(const float *mins, const float *maxs);
|
||||
|
||||
|
|
|
@ -5052,11 +5052,19 @@ static void FS_ReloadPackFilesFlags(unsigned int reloadflags)
|
|||
searchpathfuncs_t *pak;
|
||||
vfsfile_t *vfs;
|
||||
char pakname[MAX_OSPATH];
|
||||
Q_snprintfz(pakname, sizeof(pakname), "%sQuakeEX.kpf", com_gamepath);
|
||||
vfs = VFSOS_Open(pakname, "rb");
|
||||
pak = FSZIP_LoadArchive(vfs, NULL, pakname, pakname, "");
|
||||
if (pak) //logically should have SPF_EXPLICIT set, but that would give it a worse gamedir depth
|
||||
FS_AddPathHandle(&oldpaths, "", pakname, pak, "", SPF_COPYPROTECTED, reloadflags);
|
||||
int i;
|
||||
static char *names[] = {"QuakeEX.kpf", "Q2Game.kpf"}; //need a better way to handle this rubbish. fucking mod-specific translations being stored in the engine-specific data.
|
||||
for (i = 0; i < countof(names); i++)
|
||||
{
|
||||
Q_snprintfz(pakname, sizeof(pakname), "%s%s", com_gamepath, names[i]);
|
||||
vfs = VFSOS_Open(pakname, "rb");
|
||||
pak = FSZIP_LoadArchive(vfs, NULL, pakname, pakname, "");
|
||||
if (pak) //logically should have SPF_EXPLICIT set, but that would give it a worse gamedir depth
|
||||
{
|
||||
FS_AddPathHandle(&oldpaths, "", pakname, pak, "", SPF_COPYPROTECTED, reloadflags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -292,13 +292,42 @@ vfsfile_t *FS_DecompressGZip(vfsfile_t *infile, vfsfile_t *outfile)
|
|||
}
|
||||
|
||||
|
||||
size_t ZLib_CompressBuffer(const qbyte *in, size_t insize, qbyte *out, size_t maxoutsize)
|
||||
{ //compresses... returns 0 if the data would have grown.
|
||||
z_stream strm = {
|
||||
(qbyte*)in,
|
||||
insize,
|
||||
0,
|
||||
|
||||
size_t ZLib_DecompressBuffer(qbyte *in, size_t insize, qbyte *out, size_t maxoutsize)
|
||||
out,
|
||||
maxoutsize,
|
||||
0,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
Z_UNKNOWN,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
qdeflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
|
||||
if (qdeflate(&strm, Z_FINISH) != Z_STREAM_END)
|
||||
strm.total_out = 0; //some sort of failure. probably needs more output buffer
|
||||
qdeflateEnd(&strm);
|
||||
|
||||
return strm.total_out;
|
||||
}
|
||||
size_t ZLib_DecompressBuffer(const qbyte *in, size_t insize, qbyte *out, size_t maxoutsize)
|
||||
{
|
||||
int ret;
|
||||
|
||||
z_stream strm = {
|
||||
in,
|
||||
(qbyte*)in,
|
||||
insize,
|
||||
0,
|
||||
|
||||
|
|
|
@ -4723,6 +4723,9 @@ static void CM_BuildBIH(model_t *mod, int submodel)
|
|||
BZ_Free(bihleaf);
|
||||
}
|
||||
|
||||
#ifdef AVAIL_ZLIB
|
||||
#include <zlib.h> //for crc32.
|
||||
#endif
|
||||
/*
|
||||
==================
|
||||
CM_LoadMap
|
||||
|
@ -4741,7 +4744,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
|
|||
char loadname[32];
|
||||
qbyte *mod_base = (qbyte *)filein;
|
||||
bspx_header_t *bspx = NULL;
|
||||
unsigned int checksum;
|
||||
unsigned int checksum1, checksum2;
|
||||
#ifdef Q3BSPS
|
||||
extern cvar_t gl_overbright;
|
||||
#endif
|
||||
|
@ -4786,7 +4789,12 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
|
|||
return NULL;
|
||||
}
|
||||
|
||||
checksum = LittleLong (CalcHashInt(&hash_md4, buf, length));
|
||||
checksum1 = LittleLong (CalcHashInt(&hash_md4, buf, length));
|
||||
#ifdef AVAIL_ZLIB
|
||||
checksum2 = crc32(0, (void*)buf, length); //q2rerelease uses crc32 instead... *sigh*
|
||||
#else
|
||||
checksum2 = checksum1; //we accept either, so wimp out.
|
||||
#endif
|
||||
|
||||
header = *(q2dheader_t *)(buf);
|
||||
header.ident = LittleLong(header.ident);
|
||||
|
@ -5198,7 +5206,8 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
|
|||
#endif
|
||||
FloodAreaConnections (prv);
|
||||
|
||||
mod->checksum = mod->checksum2 = checksum;
|
||||
mod->checksum = checksum1;
|
||||
mod->checksum2 = checksum2;
|
||||
|
||||
mod->nummodelsurfaces = mod->numsurfaces;
|
||||
memset(&mod->batches, 0, sizeof(mod->batches));
|
||||
|
|
|
@ -2106,7 +2106,6 @@ static void ICE_ParseSDPLine(struct icestate_s *con, const char *value)
|
|||
}
|
||||
}
|
||||
|
||||
void CL_Transfer(netadr_t *adr);
|
||||
static qboolean QDECL ICE_Set(struct icestate_s *con, const char *prop, const char *value)
|
||||
{
|
||||
if (!strcmp(prop, "state"))
|
||||
|
|
|
@ -1714,6 +1714,9 @@ static int GNUDTLS_GetPeerCertificate(void *ctx, enum certprops_e prop, char *ou
|
|||
}
|
||||
}
|
||||
return -1;
|
||||
case QCERT_LOBBYSTATUS:
|
||||
case QCERT_LOBBYSENDCHAT:
|
||||
return -1;
|
||||
safedefault:
|
||||
return -1; //dunno what you want from me.
|
||||
}
|
||||
|
|
|
@ -1647,6 +1647,8 @@ static int SSPI_DTLS_GetPeerCertificate(void *ctx, enum certprops_e prop, char *
|
|||
return crypt.pCertNameToStrA(cert->dwCertEncodingType, &cert->pCertInfo->Subject, CERT_X500_NAME_STR, out, outsize);
|
||||
return -1;
|
||||
case QCERT_LOCALCERTIFICATE:
|
||||
case QCERT_LOBBYSTATUS:
|
||||
case QCERT_LOBBYSENDCHAT:
|
||||
safedefault:
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -5034,16 +5034,12 @@ static int NET_KexLobby_GetPeerCertificate(void *ctx, enum certprops_e prop, cha
|
|||
NET_KexLobby_SendChat(peer, 0, out);
|
||||
return outsize;
|
||||
case QCERT_LOBBYSTATUS:
|
||||
map = InfoBuf_ValueForKey(&peer->rules, "map");
|
||||
map = TL_Translate(com_language, map);
|
||||
mode = InfoBuf_ValueForKey(&peer->rules, "gamemode");
|
||||
mode = TL_Translate(com_language, mode);
|
||||
|
||||
switch(peer->state)
|
||||
{
|
||||
case KEXLOBBY_PENDING:
|
||||
Q_snprintfz(out, outsize, "\nWaiting for response...\n");
|
||||
break;
|
||||
return 0;
|
||||
// Q_snprintfz(out, outsize, "\nWaiting for response...\n");
|
||||
// break;
|
||||
case KEXLOBBY_ESTABLISHED:
|
||||
Q_snprintfz(out, outsize, "\nWaiting for host to start...\n");
|
||||
break;
|
||||
|
@ -5055,6 +5051,11 @@ static int NET_KexLobby_GetPeerCertificate(void *ctx, enum certprops_e prop, cha
|
|||
break;
|
||||
}
|
||||
n = strlen(out); out += n; outsize -= n;
|
||||
|
||||
map = InfoBuf_ValueForKey(&peer->rules, "map");
|
||||
map = TL_Translate(com_language, map);
|
||||
mode = InfoBuf_ValueForKey(&peer->rules, "gamemode");
|
||||
mode = TL_Translate(com_language, mode);
|
||||
Q_snprintfz(out, outsize, "%s - %s\n\n", mode, map);
|
||||
n = strlen(out); out += n; outsize -= n;
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ typedef enum
|
|||
Q2TE_TUNNEL_SPARKS,
|
||||
//ROGUE
|
||||
Q2TE_BLASTER2, //30
|
||||
Q2TE_RAILTRAIL2,
|
||||
Q2TEEX_RAILTRAIL2,
|
||||
Q2TE_FLAME,
|
||||
Q2TE_LIGHTNING,
|
||||
Q2TE_DEBUGTRAIL,
|
||||
|
@ -108,9 +108,19 @@ typedef enum
|
|||
Q2TE_FLECHETTE,
|
||||
//ROGUE
|
||||
|
||||
//RERELEASE
|
||||
Q2TEEX_BLUEHYPERBLASTER=56,
|
||||
Q2TEEX_BFGZAP,
|
||||
Q2TEEX_BERSERK_SLAM,
|
||||
Q2TEEX_GRAPPLE_CABLE_2,
|
||||
Q2TEEX_POWER_SPLASH,
|
||||
Q2TEEX_LIGHTNING_BEAM,
|
||||
Q2TEEX_EXPLOSION1_NL,
|
||||
Q2TEEX_EXPLOSION2_NL,
|
||||
//RERELEASE
|
||||
|
||||
//CODERED
|
||||
CRTE_LEADERBLASTER, //56
|
||||
CRTE_LEADERBLASTER=56, //56
|
||||
CRTE_BLASTER_MUZZLEFLASH,
|
||||
CRTE_BLUE_MUZZLEFLASH,
|
||||
CRTE_SMART_MUZZLEFLASH,
|
||||
|
@ -133,7 +143,8 @@ typedef enum
|
|||
Q2SPLASH_SLIME, //4
|
||||
Q2SPLASH_LAVA, //5
|
||||
Q2SPLASH_BLOOD, //6
|
||||
#define Q2SPLASH_MAX Q2SPLASH_BLOOD
|
||||
Q2EXSPLASH_ELECTRIC, //7
|
||||
#define Q2SPLASH_MAX Q2EXSPLASH_ELECTRIC
|
||||
|
||||
/*free form*/
|
||||
/*WARNING: must match cl_tent.c*/
|
||||
|
@ -160,6 +171,8 @@ typedef enum
|
|||
Q2PT_RESPAWN,
|
||||
Q2PT_PLAYER_TELEPORT,
|
||||
Q2PT_FOOTSTEP,
|
||||
Q2PT_OTHER_FOOTSTEP,
|
||||
Q2PT_LADDER_STEP,
|
||||
|
||||
Q2PT_MAX
|
||||
} q2particleeffects_t;
|
||||
|
|
|
@ -653,7 +653,7 @@ void VARGS PR_BIError(pubprogfuncs_t *progfuncs, char *format, ...)
|
|||
if (developer.value || !progfuncs)
|
||||
{
|
||||
struct globalvars_s *pr_globals = PR_globals(progfuncs, PR_CURRENT);
|
||||
PR_RunWarning(progfuncs, "%s\n", string);
|
||||
PR_RunWarning(progfuncs, CON_ERROR"%s\n", string);
|
||||
G_INT(OFS_RETURN)=0; //just in case it was a float and should be an ent...
|
||||
G_INT(OFS_RETURN+1)=0;
|
||||
G_INT(OFS_RETURN+2)=0;
|
||||
|
@ -662,7 +662,7 @@ void VARGS PR_BIError(pubprogfuncs_t *progfuncs, char *format, ...)
|
|||
{
|
||||
PR_StackTrace(progfuncs, false);
|
||||
// PR_AbortStack(progfuncs);
|
||||
progfuncs->parms->Abort ("%s", string);
|
||||
progfuncs->parms->Abort (CON_ERROR"%s", string);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1684,26 +1684,40 @@ void QCBUILTIN PF_FindString (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
|
|||
return;
|
||||
}
|
||||
s = PR_GetStringOfs(prinst, OFS_PARM2);
|
||||
if (!s)
|
||||
{
|
||||
PR_BIError (prinst, "PF_FindString: bad search string");
|
||||
return;
|
||||
}
|
||||
|
||||
//FIXME: bound f
|
||||
|
||||
for (e++ ; e < *prinst->parms->num_edicts ; e++)
|
||||
{
|
||||
ed = WEDICT_NUM_PB(prinst, e);
|
||||
if (ED_ISFREE(ed))
|
||||
continue;
|
||||
t = ((string_t *)ed->v)[f];
|
||||
if (!t)
|
||||
continue;
|
||||
if (!strcmp(PR_GetString(prinst, t),s))
|
||||
if (!s || !*s)
|
||||
{ //checking for empty (and by extension null)
|
||||
//looking for an empty string is a bloody stupid thing to do, and basically always a bug, but existing code exists. either way it warrents a warning.
|
||||
if (developer.ival)
|
||||
PR_RunWarning(prinst, "PF_FindString: empty string\n");
|
||||
for (e++ ; e < *prinst->parms->num_edicts ; e++)
|
||||
{
|
||||
RETURN_EDICT(prinst, ed);
|
||||
return;
|
||||
ed = WEDICT_NUM_PB(prinst, e);
|
||||
if (ED_ISFREE(ed))
|
||||
continue;
|
||||
t = ((string_t *)ed->v)[f];
|
||||
if (!t || !*PR_GetString(prinst, t))
|
||||
{
|
||||
RETURN_EDICT(prinst, ed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //should be safe to assume that null is empty and thus never a match. speed
|
||||
for (e++ ; e < *prinst->parms->num_edicts ; e++)
|
||||
{
|
||||
ed = WEDICT_NUM_PB(prinst, e);
|
||||
if (ED_ISFREE(ed))
|
||||
continue;
|
||||
t = ((string_t *)ed->v)[f];
|
||||
if (!t)
|
||||
continue;
|
||||
if (!strcmp(PR_GetString(prinst, t),s))
|
||||
{
|
||||
RETURN_EDICT(prinst, ed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -136,6 +136,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define PROTOCOL_VERSION_Q2_DEMO_MIN 26 //we can parse this server
|
||||
#define PROTOCOL_VERSION_Q2_MIN 31 //we can join these outdated servers
|
||||
#define PROTOCOL_VERSION_Q2 34 //we host this
|
||||
#define PROTOCOL_VERSION_Q2EXDEMO 2022
|
||||
#define PROTOCOL_VERSION_Q2EX 2023
|
||||
#define PROTOCOL_VERSION_R1Q2 35
|
||||
#define PROTOCOL_VERSION_Q2PRO 36
|
||||
|
||||
|
@ -153,6 +155,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define PORT_Q2MASTER 27900
|
||||
#define PORT_Q2CLIENT 27901
|
||||
#define PORT_Q2SERVER 27910
|
||||
#define PORT_Q2EXSERVER 5069
|
||||
#define PORT_Q3MASTER 27950
|
||||
#define PORT_Q3SERVER 27960
|
||||
#define PORT_ICEBROKER PORT_DPMASTER
|
||||
|
@ -467,6 +470,20 @@ enum svcq2_ops_e
|
|||
svcq2_deltapacketentities,//19 // [...]
|
||||
svcq2_frame, //20 (the bastard to implement.)
|
||||
|
||||
svcq2ex_splitclient = 21,
|
||||
svcq2ex_configblast = 22,
|
||||
svcq2ex_spawnbaselineblast = 23,
|
||||
svcq2ex_levelrestart = 24,
|
||||
svcq2ex_danage = 25,
|
||||
svcq2ex_locprint = 26,
|
||||
svcq2ex_fog = 27,
|
||||
svcq2ex_waiting = 28,
|
||||
svcq2ex_botchat = 29,
|
||||
svcq2ex_mapmarker = 30,
|
||||
svcq2ex_routemarker = 31,
|
||||
svcq2ex_muzzleflash3 = 32,
|
||||
svcq2ex_achievement = 33,
|
||||
|
||||
|
||||
svcr1q2_zpacket = 21,
|
||||
svcr1q2_zdownload = 22,
|
||||
|
@ -891,19 +908,19 @@ enum {
|
|||
|
||||
|
||||
|
||||
#define Q2U_ORIGIN1 (1<<0)
|
||||
#define Q2U_ORIGIN2 (1<<1)
|
||||
#define Q2U_ANGLE2 (1<<2)
|
||||
#define Q2U_ANGLE3 (1<<3)
|
||||
#define Q2U_FRAME8 (1<<4) // frame is a qbyte
|
||||
#define Q2U_ORIGIN1 (1<<0)
|
||||
#define Q2U_ORIGIN2 (1<<1)
|
||||
#define Q2U_ANGLE2 (1<<2)
|
||||
#define Q2U_ANGLE3 (1<<3)
|
||||
#define Q2U_FRAME8 (1<<4) // frame is a qbyte
|
||||
#define Q2U_EVENT (1<<5)
|
||||
#define Q2U_REMOVE (1<<6) // REMOVE this entity, don't add it
|
||||
#define Q2U_REMOVE (1<<6) // REMOVE this entity, don't add it
|
||||
#define Q2U_MOREBITS1 (1<<7) // read one additional qbyte
|
||||
|
||||
// second qbyte
|
||||
#define Q2U_NUMBER16 (1<<8) // NUMBER8 is implicit if not set
|
||||
#define Q2U_ORIGIN3 (1<<9)
|
||||
#define Q2U_ANGLE1 (1<<10)
|
||||
#define Q2U_ORIGIN3 (1<<9)
|
||||
#define Q2U_ANGLE1 (1<<10)
|
||||
#define Q2U_MODEL (1<<11)
|
||||
#define Q2U_RENDERFX8 (1<<12) // fullbright, etc
|
||||
#define Q2UX_ANGLE16 (1<<13)
|
||||
|
@ -911,24 +928,28 @@ enum {
|
|||
#define Q2U_MOREBITS2 (1<<15) // read one additional qbyte
|
||||
|
||||
// third qbyte
|
||||
#define Q2U_SKIN8 (1<<16)
|
||||
#define Q2U_FRAME16 (1<<17) // frame is a short
|
||||
#define Q2U_RENDERFX16 (1<<18) // 8 + 16 = 32
|
||||
#define Q2U_EFFECTS16 (1<<19) // 8 + 16 = 32
|
||||
#define Q2U_MODEL2 (1<<20) // weapons, flags, etc
|
||||
#define Q2U_MODEL3 (1<<21)
|
||||
#define Q2U_MODEL4 (1<<22)
|
||||
#define Q2U_MOREBITS3 (1<<23) // read one additional qbyte
|
||||
#define Q2U_SKIN8 (1<<16)
|
||||
#define Q2U_FRAME16 (1<<17) // frame is a short
|
||||
#define Q2U_RENDERFX16 (1<<18) // 8 + 16 = 32
|
||||
#define Q2U_EFFECTS16 (1<<19) // 8 + 16 = 32
|
||||
#define Q2U_MODEL2 (1<<20) // weapons, flags, etc
|
||||
#define Q2U_MODEL3 (1<<21)
|
||||
#define Q2U_MODEL4 (1<<22)
|
||||
#define Q2U_MOREBITS3 (1<<23) // read one additional qbyte
|
||||
|
||||
// fourth qbyte
|
||||
#define Q2U_OLDORIGIN (1<<24) // FIXME: get rid of this
|
||||
#define Q2U_SKIN16 (1<<25)
|
||||
#define Q2U_SOUND (1<<26)
|
||||
#define Q2U_SOLID (1<<27)
|
||||
#define Q2UX_INDEX16 (1<<28) //model or sound is 16bit
|
||||
#define Q2UX_UNUSED3 (1<<29)
|
||||
#define Q2UX_UNUSED2 (1<<30)
|
||||
#define Q2UX_UNUSED1 (1<<31)
|
||||
#define Q2U_OLDORIGIN (1<<24) // FIXME: get rid of this
|
||||
#define Q2U_SKIN16 (1<<25)
|
||||
#define Q2U_SOUND (1<<26)
|
||||
#define Q2U_SOLID (1<<27)
|
||||
#define Q2UX_INDEX16 (1<<28) //model or sound is 16bit
|
||||
#define Q2UEX_EFFECTS64 (1<<29)
|
||||
#define Q2UEX_ALPHA (1<<30)
|
||||
#define Q2UEX_MOREBITS4 (1u<<31)
|
||||
#define Q2UEX_SCALE (1ull<<32)
|
||||
#define Q2UEX_INSTANCE (1ull<<33)
|
||||
#define Q2UEX_OWNER (1ull<<34)
|
||||
#define Q2UEX_OLDFRAME (1ull<<35)
|
||||
|
||||
#define Q2UX_UNUSED (Q2UX_UNUSED1|Q2UX_UNUSED2|Q2UX_UNUSED3|Q2UX_UNUSED4)
|
||||
|
||||
|
@ -1172,13 +1193,16 @@ typedef struct entity_state_s
|
|||
#if defined(Q2CLIENT) || defined(Q2SERVER)
|
||||
struct
|
||||
{
|
||||
int renderfx; //q2
|
||||
unsigned int renderfx; //q2
|
||||
vec3_t old_origin; //q2/q3
|
||||
|
||||
unsigned short modelindex3; //q2
|
||||
unsigned short modelindex4; //q2
|
||||
unsigned short sound; //q2
|
||||
qbyte event; //q2
|
||||
qbyte instance; //q2ex (splitcreen, so specific seats see it or not)
|
||||
unsigned short owner; //q2ex for splitscreen prediction I guess (can't just network it as non-solid).
|
||||
unsigned short oldframe; //q2ex
|
||||
} q2;
|
||||
#endif
|
||||
struct
|
||||
|
@ -1206,7 +1230,17 @@ typedef struct entity_state_s
|
|||
|
||||
unsigned short baseframe;
|
||||
qbyte basebone;
|
||||
qbyte pad;
|
||||
qbyte solidtype;
|
||||
#define EST_FTE 0 //q2pro/r1q2, also used for fte's replacement deltas etc.
|
||||
#define EST_Q2EX 1 //q2ex packs it differently.
|
||||
#define EST_Q2 2 //16bit
|
||||
|
||||
unsigned int solidsize;
|
||||
#define ES_SOLID_NOT 0
|
||||
#define ES_SOLID_BSP 31
|
||||
#define ES_SOLID_HULL1 0x80201810
|
||||
#define ES_SOLID_HULL2 0x80401820
|
||||
#define ES_SOLID_HAS_EXTRA_BITS(solid) ((solid&0x0707) || (((solid>>16)-32768+32) & 7)) //needs to be 32bit.
|
||||
|
||||
unsigned int skinnum; /*for q2 this often contains rgba*/
|
||||
|
||||
|
@ -1234,13 +1268,6 @@ typedef struct entity_state_s
|
|||
unsigned short tagindex; //~0 == weird portal thing.
|
||||
|
||||
unsigned int tagentity;
|
||||
|
||||
unsigned int solidsize;
|
||||
#define ES_SOLID_NOT 0
|
||||
#define ES_SOLID_BSP 31
|
||||
#define ES_SOLID_HULL1 0x80201810
|
||||
#define ES_SOLID_HULL2 0x80401820
|
||||
#define ES_SOLID_HAS_EXTRA_BITS(solid) ((solid&0x0707) || (((solid>>16)-32768+32) & 7))
|
||||
} entity_state_t;
|
||||
extern entity_state_t nullentitystate;
|
||||
|
||||
|
@ -1364,6 +1391,41 @@ typedef struct q1usercmd_s
|
|||
#define Q2MAX_CONFIGSTRINGS (Q2CS_GENERAL +Q2MAX_GENERAL)
|
||||
|
||||
|
||||
#define Q2EXMAX_CLIENTS Q2MAX_CLIENTS // absolute limit
|
||||
#define Q2EXMAX_EDICTS 8192 // must change protocol to increase more
|
||||
#define Q2EXMAX_LIGHTSTYLES 256
|
||||
#define Q2EXMAX_RTLIGHTS 256
|
||||
#define Q2EXMAX_MODELS 8192 // these are sent over the net as bytes
|
||||
#define Q2EXMAX_SOUNDS 2048 // so they cannot be blindly increased
|
||||
#define Q2EXMAX_IMAGES 512
|
||||
#define Q2EXMAX_ITEMS 256
|
||||
#define Q2EXMAX_WWHEEL 32
|
||||
#define Q2EXMAX_GENERAL (Q2EXMAX_CLIENTS*2) // general config strings
|
||||
|
||||
#define Q2EXCS_NAME Q2CS_NAME
|
||||
#define Q2EXCS_CDTRACK Q2CS_CDTRACK
|
||||
#define Q2EXCS_SKY Q2CS_SKY
|
||||
#define Q2EXCS_SKYAXIS Q2CS_SKYAXIS // %f %f %f format
|
||||
#define Q2EXCS_SKYROTATE Q2CS_SKYROTATE
|
||||
#define Q2EXCS_STATUSBAR Q2CS_STATUSBAR // display program string
|
||||
#define Q2EXCS_AIRACCEL 59 // air acceleration control
|
||||
#define Q2EXCS_MAXCLIENTS 60
|
||||
#define Q2EXCS_MAPCHECKSUM 61 // for catching cheater maps
|
||||
#define Q2EXCS_MODELS 62
|
||||
#define Q2EXCS_SOUNDS (Q2EXCS_MODELS +Q2EXMAX_MODELS)
|
||||
#define Q2EXCS_IMAGES (Q2EXCS_SOUNDS +Q2EXMAX_SOUNDS)
|
||||
#define Q2EXCS_LIGHTS (Q2EXCS_IMAGES +Q2EXMAX_IMAGES)
|
||||
#define Q2EXCS_RTLIGHTS (Q2EXCS_LIGHTS +Q2EXMAX_LIGHTSTYLES)
|
||||
#define Q2EXCS_ITEMS (Q2EXCS_RTLIGHTS +Q2EXMAX_RTLIGHTS)
|
||||
#define Q2EXCS_PLAYERSKINS (Q2EXCS_ITEMS +Q2EXMAX_ITEMS)
|
||||
#define Q2EXCS_GENERAL (Q2EXCS_PLAYERSKINS +Q2EXMAX_CLIENTS)
|
||||
#define Q2ECS_WHEEL_WEAPONS (Q2EXCS_GENERAL +Q2EXMAX_GENERAL) //item|icon|ammotype|minammo|powerup|sortid|warnammo|droppable
|
||||
#define Q2ECS_WHEEL_AMMO (Q2ECS_WHEEL_WEAPONS +Q2EXMAX_WWHEEL) //item|icon
|
||||
#define Q2ECS_WHEEL_POWERUPS (Q2ECS_WHEEL_AMMO +Q2EXMAX_WWHEEL) //item|icon|toggled|sortid|droppable|ammotype
|
||||
#define Q2ECS_CD_LOOP_COUNT (Q2ECS_WHEEL_POWERUPS +Q2EXMAX_WWHEEL)
|
||||
#define Q2ECS_GAME_STYLE (Q2ECS_CD_LOOP_COUNT +1)
|
||||
#define Q2EXMAX_CONFIGSTRINGS (Q2ECS_GAME_STYLE +1)
|
||||
|
||||
// player_state->stats[] indexes
|
||||
#define Q2STAT_HEALTH_ICON 0
|
||||
#define Q2STAT_HEALTH 1
|
||||
|
@ -1404,8 +1466,10 @@ typedef struct q1usercmd_s
|
|||
#define Q2PS_WEAPONFRAME (1<<13)
|
||||
#define Q2PS_RDFLAGS (1<<14)
|
||||
#define Q2PS_EXTRABITS (1<<15)
|
||||
#define Q2PS_INDEX16 (1<<16)
|
||||
#define Q2PS_CLIENTNUM (1<<17)
|
||||
#define Q2FTEPS_INDEX16 (1<<16)
|
||||
#define Q2EXPS_DAMAGEBLEND (1<<16)
|
||||
#define Q2FTEPS_CLIENTNUM (1<<17)
|
||||
#define Q2EXPS_TEAMID (1<<17)
|
||||
#define Q2PS_UNUSED6 (1<<18)
|
||||
#define Q2PS_UNUSED5 (1<<19)
|
||||
#define Q2PS_UNUSED4 (1<<20)
|
||||
|
@ -1432,27 +1496,36 @@ typedef struct q1usercmd_s
|
|||
#define RF_TRANSLUCENT (1u<<5) //forces shader sort order and BEF_FORCETRANSPARENT
|
||||
#define Q2RF_FRAMELERP (1u<<6) //q2only
|
||||
#define Q2RF_BEAM (1u<<7) //mostly q2only
|
||||
|
||||
//
|
||||
#define Q2RF_CUSTOMSKIN (1u<<8) //not even in q2 skin is an index in image_precache
|
||||
#define Q2RF_GLOW (1u<<9) //i pulse lighting for bonus items
|
||||
#define Q2RF_SHELL_RED (1u<<10) //q2only
|
||||
#define Q2RF_SHELL_GREEN (1u<<11) //q2only
|
||||
#define Q2RF_SHELL_BLUE (1u<<12) //q2only
|
||||
|
||||
//ROGUE
|
||||
//
|
||||
#define RF_NOSHADOW (1u<<13)
|
||||
#define Q2REX_CASTSHADOW (1u<<14)
|
||||
//ROGUE start
|
||||
#define Q2RF_IR_VISIBLE (1u<<15) // shows red with Q2RDF_IRGOGGLES
|
||||
#define Q2RF_SHELL_DOUBLE (1u<<16) //q2only
|
||||
#define Q2RF_SHELL_HALF_DAM (1u<<17) //q2only
|
||||
#define Q2RF_USE_DISGUISE (1u<<18) //ni entity is displayed with skin 'players/$MODEL/disguise.pcx' instead
|
||||
//ROGUE
|
||||
//ROGUE end
|
||||
//#define Q2EXRF_SHELL_LITE_GREEN (1u<<19)
|
||||
#define Q2EXRF_CUSTOM_LIGHT (1u<<20)
|
||||
#define Q2EXRF_FLARE (1u<<21) //changes the interpretation of a lot of fields, basically replacing the entire ent.
|
||||
//#define Q2EXRF_OLD_FRAME_LERP (1u<<22) //This flag signals that `s.old_frame` should be used for the next frame and respected by the client. This can be used for custom frame interpolation; its use in this engine is specific to fixing interpolation bugs on certain monster animations.
|
||||
//#define Q2EXRF_BLOB_SHADOW (1u<<23) //
|
||||
//#define Q2EXRF_LOW_PRIORITY (1u<<24) //
|
||||
//#define Q2EXRF_NO_LOD (1u<<25) //
|
||||
//#define Q2EXRF_STAIRSTEP (1u<<26) //
|
||||
|
||||
#define RF_ADDITIVE (1u<<19) //forces shader sort order and BEF_FORCEADDITIVE
|
||||
#define RF_NOSHADOW (1u<<20) //disables shadow casting
|
||||
#define RF_NODEPTHTEST (1u<<21) //forces shader sort order and BEF_FORCENODEPTH
|
||||
#define RF_FORCECOLOURMOD (1u<<22) //forces BEF_FORCECOLOURMOD
|
||||
#define RF_WEAPONMODELNOBOB (1u<<23)
|
||||
#define RF_FIRSTPERSON (1u<<24) //only draw through eyes
|
||||
#define RF_XFLIP (1u<<25) //flip horizontally (for q2's left-handed weapons)
|
||||
#define RF_ADDITIVE (1u<<27) //forces shader sort order and BEF_FORCEADDITIVE
|
||||
#define RF_NODEPTHTEST (1u<<28) //forces shader sort order and BEF_FORCENODEPTH
|
||||
#define RF_FORCECOLOURMOD (1u<<29) //forces BEF_FORCECOLOURMOD
|
||||
#define RF_WEAPONMODELNOBOB (1u<<30)
|
||||
#define RF_FIRSTPERSON (1u<<31) //only draw through eyes
|
||||
#define RF_XFLIP Q2EXRF_FLARE //flip horizontally (for q2's left-handed weapons)
|
||||
|
||||
// player_state_t->refdef flags
|
||||
#define RDF_UNDERWATER (1u<<0) // warp the screen as apropriate (fov trick)
|
||||
|
@ -1484,8 +1557,9 @@ typedef struct q1usercmd_s
|
|||
#define Q2SND_POS (1u<<2) // three coordinates
|
||||
#define Q2SND_ENT (1u<<3) // a short 0-2: channel, 3-12: entity
|
||||
#define Q2SND_OFFSET (1u<<4) // a qbyte, msec offset from frame start
|
||||
#define Q2SND_LARGEIDX (1u<<5) // idx is a short
|
||||
#define Q2SND_LARGEPOS (1u<<6) // float coord
|
||||
#define Q2SNDFTE_LARGEIDX (1u<<5) // idx is a short
|
||||
#define Q2SNDEX_EXPLICITPOS (1u<<5) // ?
|
||||
#define Q2SNDEX_LARGEENT (1u<<6) // 32bit index
|
||||
#define Q2SND_EXTRABITS (1u<<7) // unused for now, reserved.
|
||||
|
||||
#define Q2DEFAULT_SOUND_PACKET_VOLUME 1.0
|
||||
|
@ -1524,7 +1598,7 @@ typedef struct q1usercmd_s
|
|||
|
||||
//ROGUE
|
||||
#define Q2MZ_ETF_RIFLE 30
|
||||
#define Q2MZ_UNUSED 31
|
||||
//#define Q2MZ_UNUSED 31
|
||||
#define Q2MZ_SHOTGUN2 32
|
||||
#define Q2MZ_HEATBEAM 33
|
||||
#define Q2MZ_BLASTER2 34
|
||||
|
@ -1535,6 +1609,12 @@ typedef struct q1usercmd_s
|
|||
#define Q2MZ_NUKE8 39
|
||||
//ROGUE
|
||||
|
||||
#define Q2EXMZ_BFG2 19
|
||||
#define Q2EXMZ_PHALANX2 20
|
||||
#define Q2EXMZ_PROX 31
|
||||
#define Q2EXMZ_ETF_RIFLE_2 32
|
||||
|
||||
|
||||
//
|
||||
// monster muzzle flashes
|
||||
//
|
||||
|
|
|
@ -631,7 +631,7 @@ void Mod_ClipDecal(struct model_s *mod, vec3_t center, vec3_t normal, vec3_t tan
|
|||
Q1BSP_ClipDecalToNodes(mod, &dec, mod->rootnode);
|
||||
#endif
|
||||
#ifdef Q3BSPS
|
||||
else if (mod->fromgame == fg_quake3)
|
||||
else if (mod->fromgame == fg_quake3 || mod->fromgame == fg_quake2)
|
||||
{
|
||||
if (mod->submodelof)
|
||||
{
|
||||
|
@ -3197,9 +3197,9 @@ void Mod_BSPX_List_f(void)
|
|||
{
|
||||
Con_Printf("%s:\n", fname);
|
||||
for (i = 0; i < ctx.corelumps; i++)
|
||||
Con_Printf("\t%s: %u\n", ctx.lumps[i].lumpname, (unsigned int)ctx.lumps[i].filelen);
|
||||
Con_Printf("\t%20s: %-12u csum:%08x\n", ctx.lumps[i].lumpname, (unsigned int)ctx.lumps[i].filelen, LittleLong (CalcHashInt(&hash_md4, ctx.lumps[i].data, ctx.lumps[i].filelen)));
|
||||
for ( ; i < ctx.totallumps; i++)
|
||||
Con_Printf("\t%s: %u\n", ctx.lumps[i].lumpname, (unsigned int)ctx.lumps[i].filelen);
|
||||
Con_Printf("\t%20s: %-12u csum:%08x\n", ctx.lumps[i].lumpname, (unsigned int)ctx.lumps[i].filelen, LittleLong (CalcHashInt(&hash_md4, ctx.lumps[i].data, ctx.lumps[i].filelen)));
|
||||
Mod_BSPXRW_Free(&ctx);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,20 +51,20 @@ typedef struct
|
|||
qboolean ladder;
|
||||
} q2pml_t;
|
||||
|
||||
q2pmove_t *q2pm;
|
||||
static q2pmove_t *q2pm;
|
||||
static q2pml_t q2pml;
|
||||
|
||||
|
||||
// movement parameters
|
||||
float pm_stopspeed = 100;
|
||||
float pm_maxspeed = 300;
|
||||
float pm_duckspeed = 100;
|
||||
float pm_accelerate = 10;
|
||||
static float pm_stopspeed = 100;
|
||||
static float pm_maxspeed = 300;
|
||||
static float pm_duckspeed = 100;
|
||||
static float pm_accelerate = 10;
|
||||
float pm_airaccelerate = 0;
|
||||
float pm_wateraccelerate = 10;
|
||||
float pm_friction = 6;
|
||||
float pm_waterfriction = 1;
|
||||
float pm_waterspeed = 400;
|
||||
static float pm_wateraccelerate = 10;
|
||||
static float pm_friction = 6;
|
||||
static float pm_waterfriction = 1;
|
||||
static float pm_waterspeed = 400;
|
||||
//float pm_stepheight;
|
||||
|
||||
/*
|
||||
|
|
|
@ -2329,7 +2329,9 @@ struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scal
|
|||
char *parms;
|
||||
int height = ((vheight * vid.rotpixelheight)/vid.height) + 0.5;
|
||||
char facename[MAX_QPATH*12];
|
||||
#ifdef AVAIL_FREETYPE
|
||||
char *styles = NULL;
|
||||
#endif
|
||||
struct charcache_s *c;
|
||||
float aspect = 1;
|
||||
enum fontfmt_e fmt = FMT_AUTO;
|
||||
|
@ -2401,6 +2403,7 @@ struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scal
|
|||
aspect = strtod(t, &t);
|
||||
parms = t;
|
||||
}
|
||||
#ifdef AVAIL_FREETYPE
|
||||
if (!strncmp(parms, "style=", 6))
|
||||
{
|
||||
char *t = parms+6;
|
||||
|
@ -2413,6 +2416,7 @@ struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scal
|
|||
}
|
||||
parms = t;
|
||||
}
|
||||
#endif
|
||||
|
||||
while(*parms && *parms != '&')
|
||||
parms++;
|
||||
|
|
|
@ -1113,8 +1113,8 @@ typedef struct model_s
|
|||
qboolean deluxemapping_modelspace; //deluxemaps are in modelspace - we need different glsl.
|
||||
} lightmaps;
|
||||
|
||||
unsigned checksum;
|
||||
unsigned checksum2;
|
||||
unsigned checksum; //the legacy checksum (excludes ent lump)
|
||||
unsigned checksum2; //the watervis checksum (excludes ent lump and vis stuff). this is the one that's sent over the network.
|
||||
|
||||
portal_t *portal;
|
||||
unsigned int numportals;
|
||||
|
|
|
@ -1437,6 +1437,7 @@ qboolean R_LoadRTLights(void)
|
|||
dl->lightcolourscales[2] = specularscale;
|
||||
dl->fade[0] = fade[0];
|
||||
dl->fade[1] = fade[1];
|
||||
VectorCopy(angles, dl->angles);
|
||||
AngleVectorsFLU(angles, dl->axis[0], dl->axis[1], dl->axis[2]);
|
||||
VectorCopy(avel, dl->rotation);
|
||||
|
||||
|
|
|
@ -498,7 +498,7 @@ static void SHM_BeginShadowMesh(dlight_t *dl, int type)
|
|||
sh_vertnum = 0;
|
||||
|
||||
lb = (cl.worldmodel->numclusters+7)/8;
|
||||
if (!dl->die || !dl->key)
|
||||
if (!dl->die || !dl->key || (dl->flags&LFLAG_FORCECACHE))
|
||||
{
|
||||
sh_shmesh = dl->worldshadowmesh;
|
||||
if (!sh_shmesh || sh_shmesh->leafbytes != lb)
|
||||
|
|
|
@ -18,22 +18,6 @@ r_part pe_default
|
|||
scalefactor 0.8
|
||||
}
|
||||
|
||||
r_part placeholder
|
||||
{ //FIXME: fix the things that assoc this!
|
||||
texture "classicparticle"
|
||||
tcoords 0 0 16 16 32
|
||||
count 1
|
||||
scale 1
|
||||
alpha 1
|
||||
die 0.3 0.8
|
||||
randomvel 20
|
||||
orgadd 0 31
|
||||
spawnorg 4
|
||||
gravity 40
|
||||
scalefactor 0.8
|
||||
colorindex 0 255 //something that makes it obviously a placeholder.
|
||||
}
|
||||
|
||||
r_part te_splashsparks
|
||||
{
|
||||
texture "classicparticle"
|
||||
|
@ -128,6 +112,21 @@ r_part te_splashlava
|
|||
scalefactor 0.8
|
||||
colorindex 0xe0
|
||||
}
|
||||
r_part te_splashelect
|
||||
{
|
||||
texture "classicparticle"
|
||||
tcoords 0 0 16 16 32
|
||||
count 20
|
||||
scale 1
|
||||
alpha 1
|
||||
die 0.3 0.5
|
||||
randomvel 20
|
||||
orgadd 0 31
|
||||
spawnorg 4
|
||||
gravity 40
|
||||
scalefactor 0.8
|
||||
colorindex 0xb0
|
||||
}
|
||||
r_part te_splashblood
|
||||
{
|
||||
texture "classicparticle"
|
||||
|
@ -704,20 +703,52 @@ r_part teq2_tracker_explosion
|
|||
sound "weapons/disrupthit.wav" 1 1 0 0
|
||||
}
|
||||
r_part teq2_teleport_effect
|
||||
{ //FIXME
|
||||
assoc placeholder
|
||||
{
|
||||
texture "classicparticle"
|
||||
tcoords 0 0 16 16 32
|
||||
count 400
|
||||
scale 1
|
||||
alpha 1
|
||||
die 0.5 0.8
|
||||
orgadd 8 -48
|
||||
veladd -100 -0
|
||||
spawnmode circle
|
||||
spawnorg 0 0
|
||||
spawnvel -50 30
|
||||
randomvel -32 -31
|
||||
gravity 0
|
||||
colorindex 15
|
||||
scalefactor 0.8
|
||||
}
|
||||
r_part teq2_dball_goal
|
||||
{ //FIXME
|
||||
assoc placeholder
|
||||
{ // same as teq2_teleport_effect
|
||||
assoc teq2_teleport_effect
|
||||
}
|
||||
r_part teq2_widowsplash
|
||||
{ //FIXME
|
||||
assoc placeholder
|
||||
{ // particle ball that slowly expands
|
||||
texture "classicparticle"
|
||||
tcoords 0 0 16 16 32
|
||||
count 400
|
||||
scale 1
|
||||
alpha 1
|
||||
die 3 3
|
||||
veladd 10 10
|
||||
spawnmode circle
|
||||
spawnorg 0 0
|
||||
randomvel -10 10
|
||||
gravity 0
|
||||
colorindex 104 7
|
||||
scalefactor 0.8
|
||||
}
|
||||
r_part teq2_debugtrail
|
||||
{ //FIXME
|
||||
assoc placeholder
|
||||
{
|
||||
texture "classicparticle"
|
||||
tcoords 0 0 16 16 32
|
||||
scale 1
|
||||
alpha 1
|
||||
step 5
|
||||
die 5 5
|
||||
colorindex 111
|
||||
}
|
||||
r_part teq2_chainfist_smoke
|
||||
{
|
||||
|
@ -848,11 +879,41 @@ r_part tr_tagtrail
|
|||
}
|
||||
|
||||
r_part tr_trap
|
||||
{ //FIXME: add particles
|
||||
{
|
||||
texture "classicparticle"
|
||||
tcoords 0 0 16 16 32
|
||||
count 30
|
||||
scale 1
|
||||
alpha 1
|
||||
die 0.4 0.8
|
||||
randomvel 8
|
||||
veladd 48
|
||||
colorindex 0xe0 7
|
||||
spawnmode telebox 0 4
|
||||
spawnorg 8 16
|
||||
lighttime 0
|
||||
lightradius 100 200
|
||||
lightrgb 1.0 0.8 0.25
|
||||
assoc placeholder
|
||||
}
|
||||
|
||||
r_part +tr_trap
|
||||
{
|
||||
texture "classicparticle"
|
||||
tcoords 0 0 16 16 32
|
||||
count 128
|
||||
scale 1
|
||||
alpha 1
|
||||
die 0.4 0.8
|
||||
randomvel 8
|
||||
veladd 20
|
||||
colorindex 58
|
||||
spawnmode telebox 0 4
|
||||
spawnorg 1 48
|
||||
}
|
||||
|
||||
r_part ef_trap
|
||||
{ //FIXME
|
||||
placeholder
|
||||
}
|
||||
|
||||
//flags do NOT use coronas, because it obscures the holding player's skin colour
|
||||
|
@ -961,6 +1022,13 @@ r_part ev_footstep
|
|||
sound "player/step3.wav" 1 1 0 0 1
|
||||
sound "player/step4.wav" 1 1 0 0 1
|
||||
}
|
||||
r_part ev_other_footstep
|
||||
{ //q2e - same but with idle attenuation
|
||||
sound "player/step1.wav" 1 2 0 0 1
|
||||
sound "player/step2.wav" 1 2 0 0 1
|
||||
sound "player/step3.wav" 1 2 0 0 1
|
||||
sound "player/step4.wav" 1 2 0 0 1
|
||||
}
|
||||
|
||||
//central explosion
|
||||
r_part teq2_bfg_bigexplosion
|
||||
|
@ -1015,12 +1083,35 @@ r_part TEQ2_BOSSTPORT
|
|||
}
|
||||
|
||||
r_part teq2_heatbeam_sparks
|
||||
{ //FIXME
|
||||
assoc placeholder
|
||||
{
|
||||
texture "classicparticle"
|
||||
tcoords 0 0 16 16 32
|
||||
count 30
|
||||
scale 1
|
||||
alpha 1
|
||||
die 0.3 0.8
|
||||
veladd 64
|
||||
orgadd 0 16
|
||||
spawnorg 4
|
||||
gravity 40
|
||||
scalefactor 0.8
|
||||
colorindex 9 7
|
||||
}
|
||||
r_part teq2_heatbeam_steam
|
||||
{ //FIXME
|
||||
assoc placeholder
|
||||
{
|
||||
texture "classicparticle"
|
||||
tcoords 0 0 16 16 32
|
||||
count 30
|
||||
scale 1
|
||||
alpha 1
|
||||
die 0.2 0.4
|
||||
randomvel 40
|
||||
orgadd 0 15
|
||||
veladd 30
|
||||
spawnorg 4
|
||||
gravity 40
|
||||
scalefactor 0.8
|
||||
colorindex 0xe0 7
|
||||
}
|
||||
|
||||
//r_part teq2_heatbeam_steam
|
||||
|
@ -1055,3 +1146,135 @@ r_part teq2_forcewall
|
|||
randomvel 5
|
||||
die 3 3.5
|
||||
}
|
||||
|
||||
r_part teq2ex_bluehyperblaster_puff
|
||||
{
|
||||
count 0 0 1
|
||||
model "models/objects/explode/tris.md2" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=1
|
||||
}
|
||||
|
||||
r_part teq2ex_bluehyperblaster
|
||||
{
|
||||
texture "classicparticle"
|
||||
tcoords 0 0 16 16 32
|
||||
count 60
|
||||
scale 1
|
||||
alpha 1
|
||||
die 0.3 0.8
|
||||
randomvel 40
|
||||
orgadd 0 15
|
||||
veladd 30
|
||||
spawnorg 4
|
||||
gravity 40
|
||||
scalefactor 0.8
|
||||
colorindex 111 108
|
||||
assoc teq2ex_bluehyperblaster_puff
|
||||
lightradius 150
|
||||
lightradiusfade 400
|
||||
lightrgb 0 0 1
|
||||
lightshadows 1
|
||||
sound "weapons/lashit.wav" 1 1 0 0
|
||||
}
|
||||
|
||||
r_part teq2ex_bfgzap_end
|
||||
{
|
||||
assoc teq2_bfg_explosion
|
||||
}
|
||||
|
||||
r_part teq2ex_bfgzap
|
||||
{ // green bolt-beam with small green explosion sprite at the end
|
||||
texture "particles/fteparticlefont.tga"
|
||||
tcoords 97 97 191 191 256
|
||||
scale 4
|
||||
alpha 1.0
|
||||
step 4
|
||||
randomvel 0
|
||||
type beam
|
||||
die 1
|
||||
colorindex 0xd0
|
||||
}
|
||||
|
||||
r_part teq2ex_berserk_slampuff
|
||||
{
|
||||
count 0 0 1
|
||||
model "models/objects/explode/tris.md2" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=3
|
||||
}
|
||||
r_part teq2ex_berserk_slam
|
||||
{
|
||||
texture "classicparticle"
|
||||
tcoords 0 0 16 16 32
|
||||
count 256
|
||||
scale 1
|
||||
alpha 1
|
||||
die 0.625 1
|
||||
spawnmode ball
|
||||
spawnorg 16
|
||||
spawnvel 192
|
||||
scalefactor 0.8
|
||||
gravity 40
|
||||
colorindex 111 108
|
||||
assoc teq2ex_berserk_slampuff
|
||||
}
|
||||
r_part teq2ex_grapple_cable_2
|
||||
{
|
||||
texture "particles/fteparticlefont.tga"
|
||||
tcoords 97 97 191 191 256
|
||||
scale 2
|
||||
alpha 1.0
|
||||
step 4
|
||||
randomvel 0
|
||||
type beam
|
||||
die 0.25
|
||||
colorindex 6
|
||||
}
|
||||
r_part teq2ex_power_splash
|
||||
{
|
||||
texture "classicparticle"
|
||||
tcoords 0 0 16 16 32
|
||||
count 256
|
||||
scale 4
|
||||
alpha 0.4
|
||||
die 1 0.625
|
||||
spawnmode ball
|
||||
spawnorg 16
|
||||
spawnvel 192
|
||||
scalefactor 0.8
|
||||
gravity 40
|
||||
colorindex 208 209
|
||||
}
|
||||
r_part teq2ex_lightning_beam
|
||||
{
|
||||
texture "particles/fteparticlefont.tga"
|
||||
tcoords 97 97 191 191 256
|
||||
scale 2
|
||||
alpha 1.0
|
||||
step 4
|
||||
randomvel 0
|
||||
type beam
|
||||
die 0.25
|
||||
colorindex 108
|
||||
}
|
||||
r_part teq2ex_explosion1_nl
|
||||
{ // the _nl stands for 'no light'
|
||||
assoc std_explosion_particles
|
||||
sound "weapons/rocklx1a.wav" 1 1 0 0
|
||||
model "models/objects/r_explode/tris.md2" framestart=0 frames=15 skin=-1 fullbright noshadow
|
||||
}
|
||||
r_part teq2ex_explosion2_nl
|
||||
{ // ditto
|
||||
assoc std_explosion_particles
|
||||
sound "weapons/rocklx1a.wav" 1 1 0 0
|
||||
model "models/objects/r_explode/tris.md2" framestart=15 frames=15 skin=-1 fullbright noshadow
|
||||
}
|
||||
r_part ef_trackershell
|
||||
{ // the black glob model thing
|
||||
model "models/objects/r_explode/tris.md2" framestart=30 frames=19 skin=-1 fullbright noshadow
|
||||
}
|
||||
r_part ev_ladder_step
|
||||
{
|
||||
sound "player/steps/ladder1.wav" 1 1 0 0 1
|
||||
sound "player/steps/ladder2.wav" 1 1 0 0 1
|
||||
sound "player/steps/ladder3.wav" 1 1 0 0 1
|
||||
sound "player/steps/ladder4.wav" 1 1 0 0 1
|
||||
sound "player/steps/ladder5.wav" 1 1 0 0 1
|
||||
}
|
||||
|
|
|
@ -6513,6 +6513,9 @@ char *PF_infokey_Internal (int entnum, const char *key)
|
|||
else
|
||||
value = "quakeworld+";
|
||||
break;
|
||||
case SCP_QUAKE2EX:
|
||||
value = "q2e"; //shouldn't happen
|
||||
break;
|
||||
case SCP_QUAKE2:
|
||||
value = "quake2"; //shouldn't happen
|
||||
break;
|
||||
|
@ -7888,15 +7891,16 @@ const char *SV_CheckRejectConnection(netadr_t *adr, const char *uinfo, unsigned
|
|||
*clfeatures = 0;
|
||||
safeswitch(protocol)
|
||||
{
|
||||
safedefault: bp = "unknown"; break;
|
||||
case SCP_QUAKEWORLD: bp = "qw"; break;
|
||||
case SCP_QUAKE2: bp = "q2"; break;
|
||||
case SCP_QUAKE2EX: bp = "q2ex"; break;
|
||||
case SCP_QUAKE3: bp = "q3"; break;
|
||||
case SCP_NETQUAKE: bp = "nq"; break;
|
||||
case SCP_BJP3: bp = "bjp3"; break;
|
||||
case SCP_FITZ666: bp = "fitz666"; break;
|
||||
case SCP_DARKPLACES6: bp = "dpp6"; break;
|
||||
case SCP_DARKPLACES7: bp = "dpp7"; break;
|
||||
safedefault: bp = "unknown"; break;
|
||||
}
|
||||
Info_SetValueForKey(clfeatures, "basicprotocol", bp, sizeof(clfeatures));
|
||||
Info_SetValueForKey(clfeatures, "guid", guid, sizeof(clfeatures));
|
||||
|
|
|
@ -207,8 +207,9 @@ typedef struct server_s
|
|||
#endif
|
||||
|
||||
#ifdef Q2SERVER
|
||||
sizebuf_t q2multicast;
|
||||
qbyte q2multicast_buf[MAX_Q2MSGLEN];
|
||||
sizebuf_t q2multicast[2]; //0=little/legacy coords, 1=big coords (used for q2e compat)
|
||||
qbyte q2multicast_lcbuf[MAX_Q2MSGLEN];
|
||||
qbyte q2multicast_bcbuf[MAX_Q2MSGLEN*2];
|
||||
#endif
|
||||
|
||||
// the master buffer is used for building log packets
|
||||
|
@ -441,6 +442,7 @@ enum serverprotocols_e
|
|||
SCP_BAD, //don't send (a bot)
|
||||
SCP_QUAKEWORLD,
|
||||
SCP_QUAKE2,
|
||||
SCP_QUAKE2EX,
|
||||
SCP_QUAKE3,
|
||||
//all the below are considered netquake clients.
|
||||
SCP_NETQUAKE,
|
||||
|
@ -748,7 +750,7 @@ typedef struct client_s
|
|||
|
||||
#if defined(NQPROT) || defined(Q2SERVER) || defined(Q3SERVER)
|
||||
#define ISQWCLIENT(cl) ((cl)->protocol == SCP_QUAKEWORLD)
|
||||
#define ISQ2CLIENT(cl) ((cl)->protocol == SCP_QUAKE2)
|
||||
#define ISQ2CLIENT(cl) ((cl)->protocol >= SCP_QUAKE2 && (cl)->protocol <= SCP_QUAKE2EX)
|
||||
#define ISQ3CLIENT(cl) ((cl)->protocol == SCP_QUAKE3)
|
||||
#define ISNQCLIENT(cl) ((cl)->protocol >= SCP_NETQUAKE)
|
||||
#define ISDPCLIENT(cl) ((cl)->protocol >= SCP_DARKPLACES6)
|
||||
|
@ -1190,7 +1192,10 @@ typedef struct
|
|||
#endif
|
||||
int challenge; //the challenge used at connect. remembered to make life harder for proxies.
|
||||
int mtu; //allowed fragment size (also signifies that it supports fragmented qw packets)
|
||||
char userinfo[2048]; //random userinfo data. no blobs, obviously.
|
||||
int seats;
|
||||
struct {
|
||||
char info[2048]; //random userinfo data. no blobs, obviously.
|
||||
} seat[MAX_SPLITS];
|
||||
char guid[128]; //user's guid data
|
||||
netadr_t adr; //the address the connect request came from (so we can check passwords before accepting)
|
||||
} svconnectinfo_t;
|
||||
|
@ -1282,7 +1287,7 @@ void VARGS PFQ2_Configstring (int i, const char *val); //for engine cheats.
|
|||
void SVQ2_BuildClientFrame (client_t *client);
|
||||
void SVQ2_WriteFrameToClient (client_t *client, sizebuf_t *msg);
|
||||
#ifdef Q2SERVER
|
||||
void MSGQ2_WriteDeltaEntity (q2entity_state_t *from, q2entity_state_t *to, sizebuf_t *msg, qboolean force, qboolean newentity);
|
||||
void MSGQ2_WriteDeltaEntity (q2entity_state_t *from, q2entity_state_t *to, sizebuf_t *msg, qboolean force, qboolean newentity, qboolean q2ex);
|
||||
void SVQ2_BuildBaselines(void);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1915,7 +1915,9 @@ void SV_AutoAddPenalty (client_t *cl, unsigned int banflag, int duration, char *
|
|||
proto.adrmask.type = proto.adr.type;
|
||||
|
||||
SV_AddBanEntry(&proto, reason);
|
||||
SV_EvaluatePenalties(cl);
|
||||
|
||||
for (cl = (cl->controller?cl->controller:cl); cl; cl = cl->controlled)
|
||||
SV_EvaluatePenalties(cl);
|
||||
}
|
||||
void SV_AutoBanSender (int duration, char *reason)
|
||||
{
|
||||
|
@ -2188,12 +2190,14 @@ static char *ShowTime(unsigned int seconds)
|
|||
SV_Status_f
|
||||
================
|
||||
*/
|
||||
const char *SV_ProtocolNameForClient(client_t *cl);
|
||||
static void SV_Status_f (void)
|
||||
{
|
||||
int i;
|
||||
client_t *cl;
|
||||
float cpu;
|
||||
char *s, *p, *sec;
|
||||
char *s, *sec;
|
||||
const char *p;
|
||||
char adr[MAX_ADR_SIZE];
|
||||
float pi, po, bi, bo;
|
||||
|
||||
|
@ -2496,21 +2500,7 @@ static void SV_Status_f (void)
|
|||
else
|
||||
sec = S_COLOR_RED;
|
||||
|
||||
safeswitch(cl->protocol)
|
||||
{
|
||||
case SCP_BAD: p = "-----"; break;
|
||||
case SCP_QUAKEWORLD: p = (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)?"fteqw":"qw"; break;
|
||||
case SCP_QUAKE2: p = "q2"; break;
|
||||
case SCP_QUAKE3: p = "q3"; break;
|
||||
case SCP_NETQUAKE: p = (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)?"ftenq":(cl->qex?"qe15":"nq"); break;
|
||||
case SCP_BJP3: p = (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)?"ftenq":"bjp3"; break;
|
||||
case SCP_FITZ666: p = (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)?"ftenq":(cl->qex?"qe666":"fitz"); break;
|
||||
case SCP_DARKPLACES6: p = "dpp6"; break;
|
||||
case SCP_DARKPLACES7: p = "dpp7"; break;
|
||||
safedefault:
|
||||
p = "";
|
||||
break;
|
||||
}
|
||||
p = SV_ProtocolNameForClient(cl);
|
||||
if (cl->state == cs_connected && cl->protocol>=SCP_NETQUAKE)
|
||||
p = "nq"; //not actually known yet.
|
||||
else if (cl->state == cs_zombie || cl->state == cs_loadzombie)
|
||||
|
@ -2811,7 +2801,7 @@ void SV_User_f (void)
|
|||
Con_TPrintf("Userinfo (%i):\n", cl->userid);
|
||||
InfoBuf_Print (&cl->userinfo, " ");
|
||||
Con_Printf("[%u/%i, %u/%i]\n", (unsigned)cl->userinfo.totalsize, sv_userinfo_bytelimit.ival, (unsigned)cl->userinfo.numkeys, sv_userinfo_keylimit.ival);
|
||||
switch(cl->protocol)
|
||||
safeswitch(cl->protocol)
|
||||
{
|
||||
case SCP_BAD:
|
||||
Con_Printf("protocol: bot/invalid\n");
|
||||
|
@ -2825,6 +2815,9 @@ void SV_User_f (void)
|
|||
case SCP_QUAKE2:
|
||||
Con_Printf("protocol: quake2\n");
|
||||
break;
|
||||
case SCP_QUAKE2EX:
|
||||
Con_Printf("protocol: quake2ex\n");
|
||||
break;
|
||||
case SCP_QUAKE3:
|
||||
Con_Printf("protocol: quake3\n");
|
||||
break;
|
||||
|
@ -2849,7 +2842,7 @@ void SV_User_f (void)
|
|||
case SCP_DARKPLACES7:
|
||||
Con_Printf("protocol: dpp7\n");
|
||||
break;
|
||||
default:
|
||||
safedefault:
|
||||
Con_Printf("protocol: other (fixme)\n");
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1807,7 +1807,7 @@ qboolean MSV_ClusterLoginSQLResult(queryrequest_t *req, int firstrow, int numrow
|
|||
if (!playerid)
|
||||
SV_RejectMessage(info->protocol, "Bad username or password.\n");
|
||||
else if (sv.state == ss_clustermode)
|
||||
MSV_ClusterLoginReply(NULL, serverid, playerid, Info_ValueForKey(info->userinfo, "name"), info->guid, &info->adr, statsblob, blobsize);
|
||||
MSV_ClusterLoginReply(NULL, serverid, playerid, Info_ValueForKey(info->seat[0].info, "name"), info->guid, &info->adr, statsblob, blobsize);
|
||||
else
|
||||
SV_DoDirectConnect(info);
|
||||
Z_Free(info);
|
||||
|
@ -1876,8 +1876,8 @@ qboolean MSV_ClusterLogin(svconnectinfo_t *info)
|
|||
sql = SQL_GetServer(&sv, sv.logindatabase, false);
|
||||
if (!sql)
|
||||
return true; //connection was killed? o.O
|
||||
SQL_Escape(sql, Info_ValueForKey(info->userinfo, "name"), escname, sizeof(escname));
|
||||
SQL_Escape(sql, Info_ValueForKey(info->userinfo, "password"), escpasswd, sizeof(escpasswd));
|
||||
SQL_Escape(sql, Info_ValueForKey(info->seat[0].info, "name"), escname, sizeof(escname));
|
||||
SQL_Escape(sql, Info_ValueForKey(info->seat[0].info, "password"), escpasswd, sizeof(escpasswd));
|
||||
if (SQL_NewQuery(sql, MSV_ClusterLoginSQLResult, va("SELECT playerid,serverid,parms,parmstring FROM accounts WHERE name='%s' AND password='%s';", escname, escpasswd), &req) != -1)
|
||||
{
|
||||
pendinglookups++;
|
||||
|
@ -1902,7 +1902,7 @@ qboolean MSV_ClusterLogin(svconnectinfo_t *info)
|
|||
return true;
|
||||
}
|
||||
else*/
|
||||
MSV_ClusterLoginReply(NULL, 0, ++nextuserid, Info_ValueForKey(info->userinfo, "name"), info->guid, &net_from, NULL, 0);
|
||||
MSV_ClusterLoginReply(NULL, 0, ++nextuserid, Info_ValueForKey(info->seat[0].info, "name"), info->guid, &net_from, NULL, 0);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -752,6 +752,8 @@ void SV_SetupNetworkBuffers(qboolean bigcoords)
|
|||
for (i = 0; i < svs.allocated_client_slots; i++)
|
||||
{
|
||||
svs.clients[i].netchan.netprim = svs.netprim;
|
||||
if (svs.clients[i].protocol == SCP_QUAKE2EX)
|
||||
svs.clients[i].netchan.netprim.coordtype = COORDTYPE_FLOAT_32; //forced to floats. we have multiple multicast buffers. woo.
|
||||
|
||||
//make sure those are kept up to date too.
|
||||
svs.clients[i].datagram.prim =
|
||||
|
@ -789,9 +791,13 @@ void SV_SetupNetworkBuffers(qboolean bigcoords)
|
|||
#endif
|
||||
|
||||
#ifdef Q2SERVER
|
||||
sv.q2multicast.maxsize = sizeof(sv.q2multicast_buf);
|
||||
sv.q2multicast.data = sv.q2multicast_buf;
|
||||
sv.q2multicast.prim = svs.netprim;
|
||||
sv.q2multicast[0].maxsize = sizeof(sv.q2multicast_lcbuf);
|
||||
sv.q2multicast[0].data = sv.q2multicast_lcbuf;
|
||||
sv.q2multicast[0].prim = svs.netprim;
|
||||
sv.q2multicast[1].maxsize = sizeof(sv.q2multicast_bcbuf);
|
||||
sv.q2multicast[1].data = sv.q2multicast_bcbuf;
|
||||
sv.q2multicast[1].prim = svs.netprim;
|
||||
sv.q2multicast[1].prim.coordtype = COORDTYPE_FLOAT_32;
|
||||
#endif
|
||||
|
||||
sv.master.maxsize = sizeof(sv.master_buf);
|
||||
|
@ -1316,7 +1322,7 @@ MSV_OpenUserDatabase();
|
|||
sv.strings.configstring[Q2CS_AIRACCEL] = Z_StrDup("0");
|
||||
|
||||
// init map checksum config string but only for Q2/Q3 maps
|
||||
sv.strings.configstring[Q2CS_MAPCHECKSUM] = Z_StrDupf("%i", sv.world.worldmodel->checksum);
|
||||
sv.strings.configstring[Q2CS_MAPCHECKSUM] = Z_StrDupf("%i %i", sv.world.worldmodel->checksum, sv.world.worldmodel->checksum2);
|
||||
|
||||
subs = sv.world.worldmodel->numsubmodels;
|
||||
if (subs > MAX_PRECACHE_MODELS-1)
|
||||
|
|
|
@ -507,6 +507,7 @@ void SV_DropClient (client_t *drop)
|
|||
switch (drop->protocol)
|
||||
{
|
||||
case SCP_QUAKE2:
|
||||
case SCP_QUAKE2EX:
|
||||
MSG_WriteByte (&drop->netchan.message, svcq2_disconnect);
|
||||
break;
|
||||
case SCP_QUAKEWORLD:
|
||||
|
@ -917,13 +918,11 @@ int SV_CalcPing (client_t *cl, qboolean forcecalc)
|
|||
if (!cl->frameunion.frames)
|
||||
return 0;
|
||||
|
||||
switch (cl->protocol)
|
||||
safeswitch (cl->protocol)
|
||||
{
|
||||
default:
|
||||
case SCP_BAD:
|
||||
break;
|
||||
#ifdef Q2SERVER
|
||||
case SCP_QUAKE2:
|
||||
case SCP_QUAKE2EX:
|
||||
{
|
||||
q2client_frame_t *frame;
|
||||
ping = 0;
|
||||
|
@ -968,6 +967,9 @@ int SV_CalcPing (client_t *cl, qboolean forcecalc)
|
|||
ping /= count;
|
||||
}
|
||||
return ping*1000;
|
||||
case SCP_BAD:
|
||||
safedefault:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1127,21 +1129,23 @@ const char *SV_ProtocolNameForClient(client_t *cl)
|
|||
case SCP_QUAKEWORLD:
|
||||
if (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
|
||||
return "fteqw"; //changes enough to be significant. assumed to include csqc.
|
||||
return "quakeworld";
|
||||
return "qw";
|
||||
case SCP_BAD:
|
||||
return "bot";
|
||||
case SCP_QUAKE2:
|
||||
return "quake2";
|
||||
return "q2";
|
||||
case SCP_QUAKE2EX:
|
||||
return "q2ex";
|
||||
case SCP_QUAKE3:
|
||||
return "quake3";
|
||||
return "q3";
|
||||
case SCP_NETQUAKE:
|
||||
if (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
|
||||
return "ftenq"; //changes enough to be significant. assumed to include csqc.
|
||||
if (cl->qex)
|
||||
return "qex";
|
||||
if (cl->proquake_angles_hack)
|
||||
return "proquake";
|
||||
return "vanilla";
|
||||
return "pq";
|
||||
return "nq";
|
||||
case SCP_BJP3:
|
||||
return "bjp3";
|
||||
case SCP_FITZ666:
|
||||
|
@ -1158,7 +1162,7 @@ const char *SV_ProtocolNameForClient(client_t *cl)
|
|||
case SCP_DARKPLACES7:
|
||||
return "dp7";
|
||||
safedefault:
|
||||
return "unknown";
|
||||
return "unk";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1734,7 +1738,7 @@ qboolean SVC_GetChallenge (qboolean respond_dp)
|
|||
#endif
|
||||
#ifdef Q2SERVER
|
||||
case GT_QUAKE2:
|
||||
buf = va("challenge %i", challenge); //quake 2 servers give a different challenge response
|
||||
buf = va("challenge %i p="STRINGIFY(PROTOCOL_VERSION_Q2EX), challenge); //quake 2 servers give a different challenge response
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -2019,7 +2023,7 @@ void SV_AcceptMessage(client_t *newcl)
|
|||
sb.maxsize = sizeof(string);
|
||||
sb.data = string;
|
||||
|
||||
switch(newcl->protocol)
|
||||
safeswitch(newcl->protocol)
|
||||
{
|
||||
#ifdef NQPROT
|
||||
case SCP_NETQUAKE:
|
||||
|
@ -2066,13 +2070,16 @@ void SV_AcceptMessage(client_t *newcl)
|
|||
len = strlen(string);
|
||||
break;
|
||||
case SCP_QUAKE2:
|
||||
default:
|
||||
Q_snprintfz(string, sizeof(string), "client_connect%s\n",
|
||||
case SCP_QUAKE2EX:
|
||||
Q_snprintfz(string, sizeof(string), "client_connect%s%s\n",
|
||||
(newcl->protocol==SCP_QUAKE2EX)?" "STRINGIFY(PROTOCOL_VERSION_Q2EX):"",
|
||||
(*fs_dlURL.string?va(" dlserver=%s", fs_dlURL.string):"") //q2pro's dlserver hint
|
||||
);
|
||||
len = strlen(string);
|
||||
break;
|
||||
|
||||
safedefault:
|
||||
case SCP_BAD:
|
||||
case SCP_QUAKEWORLD:
|
||||
string[0] = S2C_CONNECTION;
|
||||
string[1] = '\n';
|
||||
|
@ -2415,12 +2422,6 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id)
|
|||
unsigned int clients = 0, spectators = 0;
|
||||
qboolean asspec;
|
||||
|
||||
if (!(controller->fteprotocolextensions & PEXT_SPLITSCREEN))
|
||||
{
|
||||
SV_PrintToClient(controller, PRINT_HIGH, "Your client doesn't support splitscreen\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (curclients = 0, prev = cl = controller; cl; cl = cl->controlled)
|
||||
{
|
||||
prev = cl;
|
||||
|
@ -2651,7 +2652,7 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
// check for password or spectator_password
|
||||
if (svprogfuncs)
|
||||
{
|
||||
s = Info_ValueForKey (info->userinfo, "spectator");
|
||||
s = Info_ValueForKey (info->seat[0].info, "spectator");
|
||||
if (s[0] && strcmp(s, "0"))
|
||||
{
|
||||
if (spectator_password.string[0] &&
|
||||
|
@ -2663,8 +2664,8 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
SV_RejectMessage (info->protocol, "requires a spectator password\n\n");
|
||||
return;
|
||||
}
|
||||
Info_RemoveKey (info->userinfo, "spectator"); // remove key
|
||||
Info_SetValueForStarKey (info->userinfo, "*spectator", "1", sizeof(info->userinfo));
|
||||
Info_RemoveKey (info->seat[0].info, "spectator"); // remove key
|
||||
Info_SetValueForStarKey (info->seat[0].info, "*spectator", "1", sizeof(info->seat[0].info));
|
||||
spectator = true;
|
||||
}
|
||||
else
|
||||
|
@ -2676,7 +2677,7 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
else if (info->protocol == SCP_NETQUAKE)
|
||||
{ //if its a proquake client then use numeric passwords, which take a bit of processing
|
||||
char *e;
|
||||
int got = strtol(Info_ValueForKey (info->userinfo, "password"), NULL, 0);
|
||||
int got = strtol(Info_ValueForKey (info->seat[0].info, "password"), NULL, 0);
|
||||
int need = strtol(password.string, &e, 0);
|
||||
if (*e)
|
||||
need = CalcHashInt(&hash_md4, password.string, strlen(password.string));
|
||||
|
@ -2689,7 +2690,7 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
}
|
||||
else
|
||||
{
|
||||
s = Info_ValueForKey (info->userinfo, "password");
|
||||
s = Info_ValueForKey (info->seat[0].info, "password");
|
||||
if (strcmp(password.string, s))
|
||||
{
|
||||
Con_TPrintf ("%s:password failed\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &info->adr));
|
||||
|
@ -2698,8 +2699,8 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
}
|
||||
}
|
||||
spectator = false;
|
||||
Info_RemoveKey (info->userinfo, "password"); // remove passwd
|
||||
Info_RemoveKey (info->userinfo, "*spectator"); // remove key
|
||||
Info_RemoveKey (info->seat[0].info, "password"); // remove passwd
|
||||
Info_RemoveKey (info->seat[0].info, "*spectator"); // remove key
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2807,7 +2808,7 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
}
|
||||
}
|
||||
|
||||
name = Info_ValueForKey (info->userinfo, "name");
|
||||
name = Info_ValueForKey (info->seat[0].info, "name");
|
||||
|
||||
/*
|
||||
if (sv.world.worldmodel && info->protocol == SCP_QUAKEWORLD &&!atoi(Info_ValueForKey (info->userinfo, "iknow")))
|
||||
|
@ -3045,7 +3046,7 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
temp.edict = ent;
|
||||
|
||||
{
|
||||
const char *reject = SV_CheckRejectConnection(&info->adr, info->userinfo, info->protocol, info->ftepext1, info->ftepext2, info->ezpext1, info->guid);
|
||||
const char *reject = SV_CheckRejectConnection(&info->adr, info->seat[0].info, info->protocol, info->ftepext1, info->ftepext2, info->ezpext1, info->guid);
|
||||
if (reject)
|
||||
{
|
||||
SV_RejectMessage(info->protocol, "%s", reject);
|
||||
|
@ -3058,7 +3059,7 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
|
||||
#ifdef Q2SERVER
|
||||
case GT_QUAKE2:
|
||||
if (info->protocol != SCP_QUAKE2)
|
||||
if (info->protocol != SCP_QUAKE2 && info->protocol != SCP_QUAKE2EX)
|
||||
{
|
||||
SV_RejectMessage(info->protocol, "This is a %s server.", fs_manifest->formalname);
|
||||
Con_DPrintf ("* Rejected non-q2 client.\n");
|
||||
|
@ -3068,9 +3069,9 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
temp.edict = NULL;
|
||||
temp.q2edict = q2ent;
|
||||
|
||||
if (!ge->ClientConnect(q2ent, info->userinfo))
|
||||
if (!ge->ClientConnect(q2ent, info->seat[0].info))
|
||||
{
|
||||
const char *reject = Info_ValueForKey(info->userinfo, "rejmsg");
|
||||
const char *reject = Info_ValueForKey(info->seat[0].info, "rejmsg");
|
||||
if (*reject)
|
||||
SV_RejectMessage(info->protocol, "%s\nConnection Refused.", reject);
|
||||
else
|
||||
|
@ -3079,7 +3080,7 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
return;
|
||||
}
|
||||
|
||||
ge->ClientUserinfoChanged(q2ent, info->userinfo);
|
||||
ge->ClientUserinfoChanged(q2ent, info->seat[0].info);
|
||||
|
||||
|
||||
break;
|
||||
|
@ -3102,7 +3103,7 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
*newcl = temp;
|
||||
newcl->userinfo.ChangeCB = svs.info.ChangeCB;
|
||||
newcl->userinfo.ChangeCTX = &newcl->userinfo;
|
||||
InfoBuf_FromString(&newcl->userinfo, info->userinfo, false);
|
||||
InfoBuf_FromString(&newcl->userinfo, info->seat[0].info, false);
|
||||
|
||||
newcl->challenge = info->challenge;
|
||||
newcl->zquake_extensions = atoi(InfoBuf_ValueForKey(&newcl->userinfo, "*z_ext"));
|
||||
|
@ -3142,7 +3143,7 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
else
|
||||
{ //otherwise we can't fragment the packets, and the only way to honour the mtu is to send less data. yay for more round-trips.
|
||||
int mtu;
|
||||
mtu = atoi(Info_ValueForKey (info->userinfo, "mtu"));
|
||||
mtu = atoi(Info_ValueForKey (info->seat[0].info, "mtu"));
|
||||
if (mtu)
|
||||
newcl->netchan.mtu = mtu; //locked mtu size, because not everyone has a working connection (we need icmp would-fragment responses for mtu detection)
|
||||
else //if its not set then use some 'safe' fallback.
|
||||
|
@ -3171,10 +3172,20 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
else
|
||||
newcl->datagram.maxsize = MAX_DATAGRAM;
|
||||
|
||||
newcl->netchan.netprim =
|
||||
newcl->datagram.prim =
|
||||
newcl->backbuf.prim =
|
||||
newcl->netchan.message.prim = svs.netprim;
|
||||
if (newcl->protocol == SCP_QUAKE2EX)
|
||||
{
|
||||
newcl->netchan.netprim =
|
||||
newcl->datagram.prim =
|
||||
newcl->backbuf.prim =
|
||||
newcl->netchan.message.prim = sv.q2multicast[1].prim;
|
||||
}
|
||||
else
|
||||
{
|
||||
newcl->netchan.netprim =
|
||||
newcl->datagram.prim =
|
||||
newcl->backbuf.prim =
|
||||
newcl->netchan.message.prim = svs.netprim;
|
||||
}
|
||||
|
||||
SV_ClientProtocolExtensionsChanged(newcl);
|
||||
|
||||
|
@ -3371,8 +3382,31 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
if (sv_use_dns.ival)
|
||||
NET_AdrToStringResolve(&info->adr, SV_UserDNSResolved, NULL, newcl-svs.clients, newcl->userid);
|
||||
|
||||
for (i = 1; i < info->seats; i++)
|
||||
SV_AddSplit(newcl, info->seat[i].info, i);
|
||||
}
|
||||
|
||||
#ifdef Q2SERVER
|
||||
void Q2EFixupInfo(void *vctx, const char *key, const char *value)
|
||||
{
|
||||
int seat = -1;
|
||||
svconnectinfo_t *ctx = vctx;
|
||||
int l = strlen(key);
|
||||
if (l > 2 && key[l-2] == '_' && key[l-1] >= '0' && key[l-1] < '0'+MAX_SPLITS)
|
||||
{
|
||||
seat = key[l-1]-'0';
|
||||
((char*)key)[l-2] = 0; //strip out the annoying _0s
|
||||
}
|
||||
if (seat < 0)
|
||||
{
|
||||
for(seat = 0; seat < ctx->seats; seat++)
|
||||
Info_SetValueForStarKey(ctx->seat[seat].info, key, value, sizeof(ctx->seat[seat].info));
|
||||
}
|
||||
else
|
||||
Info_SetValueForStarKey(ctx->seat[seat].info, key, value, sizeof(ctx->seat[seat].info));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
==================
|
||||
SVC_DirectConnect
|
||||
|
@ -3411,7 +3445,7 @@ void SVC_DirectConnect(int expectedreliablesequence)
|
|||
info.ftepext2 = 0;
|
||||
info.ezpext1 = 0;
|
||||
*info.guid = 0;
|
||||
|
||||
info.seats = 1;
|
||||
if (*Cmd_Argv(1) == '\\')
|
||||
{ //q3: connect "\key\val"
|
||||
#ifndef QWOVERQ3
|
||||
|
@ -3477,9 +3511,9 @@ void SVC_DirectConnect(int expectedreliablesequence)
|
|||
Con_TPrintf ("* rejected connect from dp client (because of hexen2)\n");
|
||||
return;
|
||||
}
|
||||
Q_strncpyz (info.userinfo, net_message.data + 11, sizeof(info.userinfo)-1);
|
||||
Q_strncpyz (info.seat[0].info, net_message.data + 11, sizeof(info.seat[0].info)-1);
|
||||
|
||||
if (strcmp(Info_ValueForKey(info.userinfo, "protocol"), "darkplaces "STRINGIFY(NQ_NETCHAN_VERSION)))
|
||||
if (strcmp(Info_ValueForKey(info.seat[0].info, "protocol"), "darkplaces "STRINGIFY(NQ_NETCHAN_VERSION)))
|
||||
{
|
||||
SV_RejectMessage (SCP_BAD, "Server is %s.\n", version_string());
|
||||
Con_TPrintf ("* rejected connect from incompatible client\n");
|
||||
|
@ -3487,7 +3521,7 @@ void SVC_DirectConnect(int expectedreliablesequence)
|
|||
}
|
||||
//it's a darkplaces client.
|
||||
|
||||
s = Info_ValueForKey(info.userinfo, "protocols");
|
||||
s = Info_ValueForKey(info.seat[0].info, "protocols");
|
||||
|
||||
while(s && *s)
|
||||
{
|
||||
|
@ -3535,25 +3569,55 @@ void SVC_DirectConnect(int expectedreliablesequence)
|
|||
|
||||
info.protocol = SCP_DARKPLACES7;
|
||||
|
||||
s = Info_ValueForKey(info.userinfo, "challenge");
|
||||
s = Info_ValueForKey(info.seat[0].info, "challenge");
|
||||
if (!strncmp(s, "FTE", strlen("FTE"))) //cope with our mangling of the challenge.
|
||||
info.challenge = atoi(s+strlen("FTE"));
|
||||
else
|
||||
info.challenge = atoi(s);
|
||||
|
||||
Info_RemoveKey(info.userinfo, "protocol");
|
||||
Info_RemoveKey(info.userinfo, "protocols");
|
||||
Info_RemoveKey(info.userinfo, "challenge");
|
||||
Info_RemoveKey(info.seat[0].info, "protocol");
|
||||
Info_RemoveKey(info.seat[0].info, "protocols");
|
||||
Info_RemoveKey(info.seat[0].info, "challenge");
|
||||
|
||||
s = Info_ValueForKey(info.userinfo, "name");
|
||||
s = Info_ValueForKey(info.seat[0].info, "name");
|
||||
if (!*s)
|
||||
Info_SetValueForKey(info.userinfo, "name", "CONNECTING", sizeof(info.userinfo));
|
||||
Info_SetValueForKey(info.seat[0].info, "name", "CONNECTING", sizeof(info.seat[0].info));
|
||||
|
||||
info.qport = 0;
|
||||
info.proquakeanglehack = false; //NOTE: DP clients fuck up here due to a DP client bug.
|
||||
//DP clients will use 16bit angles if it has previously connected to a proquake-handshake server,
|
||||
//and 8bit angles otherwise (or a non-proquake/non-dp/non-qw server more recently than the proquake one).
|
||||
}
|
||||
#endif
|
||||
#ifdef Q2SERVER
|
||||
else if (atoi(Cmd_Argv(1)) == PROTOCOL_VERSION_Q2EX)
|
||||
{
|
||||
int i, numseats;
|
||||
info.seats = numseats = atoi(Cmd_Argv(2));
|
||||
version = atoi(Cmd_Argv(1));
|
||||
info.protocol = SCP_QUAKE2EX;
|
||||
info.seats = bound(1, numseats, countof(info.seat));
|
||||
if (info.seats < 1 || info.seats > MAX_SPLITS)
|
||||
{ //no splitscreen(yet)
|
||||
SV_RejectMessage (info.protocol, "bad number of seats\n", PROTOCOL_VERSION_Q2, version);
|
||||
Con_TPrintf ("* rejected connect from version %i\n", version);
|
||||
return;
|
||||
}
|
||||
Q_strncpyz(info.guid, Cmd_Argv(3), sizeof(info.guid));
|
||||
//Socials - Cmd_Argv(3 ... 3+numseats-1); fuck that spyware
|
||||
for (i = 0; i < info.seats; i++)
|
||||
*info.seat[i].info = 0;
|
||||
Info_Enumerate(va("\\%s", Cmd_Argv(3+numseats)), &info, Q2EFixupInfo);
|
||||
|
||||
//hide a challenge in there, in case we're not using the lobby stuff.
|
||||
info.challenge = atoi(Info_ValueForKey(info.seat[0].info, "challenge"));
|
||||
info.qport = atoi(Info_ValueForKey(info.seat[0].info, "qport"));
|
||||
for (i = 0; i < info.seats; i++)
|
||||
{
|
||||
Info_RemoveKey(info.seat[i].info, "challenge");
|
||||
Info_RemoveKey(info.seat[i].info, "qport");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
|
@ -3611,12 +3675,12 @@ void SVC_DirectConnect(int expectedreliablesequence)
|
|||
info.challenge = atoi(Cmd_Argv(3));
|
||||
|
||||
// note an extra qbyte is needed to replace spectator key
|
||||
Q_strncpyz (info.userinfo, Cmd_Argv(4), sizeof(info.userinfo)-1);
|
||||
Q_strncpyz (info.seat[0].info, Cmd_Argv(4), sizeof(info.seat[0].info)-1);
|
||||
if (info.protocol >= SCP_NETQUAKE)
|
||||
{
|
||||
Info_RemoveKey(info.userinfo, "mod"); //its served its purpose.
|
||||
Info_RemoveKey(info.userinfo, "modver"); //its served its purpose.
|
||||
Info_RemoveKey(info.userinfo, "flags"); //its served its purpose.
|
||||
Info_RemoveKey(info.seat[0].info, "mod"); //its served its purpose.
|
||||
Info_RemoveKey(info.seat[0].info, "modver"); //its served its purpose.
|
||||
Info_RemoveKey(info.seat[0].info, "flags"); //its served its purpose.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3673,19 +3737,19 @@ void SVC_DirectConnect(int expectedreliablesequence)
|
|||
if (sv_banproxies.ival)
|
||||
{
|
||||
//FIXME: allow them to spectate but not join
|
||||
if (*Info_ValueForKey(info.userinfo, "*qwfwd"))
|
||||
if (*Info_ValueForKey(info.seat[0].info, "*qwfwd"))
|
||||
{
|
||||
SV_RejectMessage (info.protocol, "Proxies are not permitted on this server.\n");
|
||||
Con_TPrintf ("* rejected connect from qwfwd proxy\n");
|
||||
return;
|
||||
}
|
||||
if (*Info_ValueForKey(info.userinfo, "Qizmo"))
|
||||
if (*Info_ValueForKey(info.seat[0].info, "Qizmo"))
|
||||
{
|
||||
SV_RejectMessage (info.protocol, "Proxies are not permitted on this server.\n");
|
||||
Con_TPrintf ("* rejected connect from qizmo proxy\n");
|
||||
return;
|
||||
}
|
||||
if (*Info_ValueForKey(info.userinfo, "*qtv"))
|
||||
if (*Info_ValueForKey(info.seat[0].info, "*qtv"))
|
||||
{
|
||||
SV_RejectMessage (info.protocol, "Proxies are not permitted on this server.\n");
|
||||
Con_TPrintf ("* rejected connect from qtv proxy (udp)\n");
|
||||
|
@ -4903,7 +4967,7 @@ void SV_ReadPacket(void)
|
|||
// check for packets from connected clients
|
||||
for (i=0, cl=svs.clients ; i<svs.allocated_client_slots ; i++,cl++)
|
||||
{
|
||||
if (cl->state == cs_free)
|
||||
if (cl->state == cs_free || cl->controller)
|
||||
continue;
|
||||
if (!NET_CompareBaseAdr (&net_from, &cl->netchan.remote_address))
|
||||
continue;
|
||||
|
|
|
@ -282,14 +282,7 @@ void ClientReliableWrite_SZ(client_t *cl, const void *data, int len)
|
|||
|
||||
|
||||
#ifdef PEXT_ZLIBDL
|
||||
|
||||
#ifdef WIN32
|
||||
#define ZEXPORT VARGS
|
||||
#include "../zip/zlib.h"
|
||||
//# pragma comment (lib, "zip/zlib.lib")
|
||||
#else
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
void ClientReliableWrite_ZLib(client_t *cl, void *data, int len)
|
||||
{
|
||||
|
|
|
@ -165,6 +165,7 @@ void SV_PrintToClient(client_t *cl, int level, const char *string)
|
|||
case SCP_BAD: //bot
|
||||
break;
|
||||
case SCP_QUAKE2:
|
||||
case SCP_QUAKE2EX:
|
||||
#ifdef Q2SERVER
|
||||
ClientReliableWrite_Begin (cl, svcq2_print, strlen(string)+3);
|
||||
ClientReliableWrite_Byte (cl, level);
|
||||
|
@ -206,6 +207,7 @@ void SV_StuffcmdToClient(client_t *cl, const char *string)
|
|||
case SCP_BAD: //bot
|
||||
break;
|
||||
case SCP_QUAKE2:
|
||||
case SCP_QUAKE2EX:
|
||||
#ifdef Q2SERVER
|
||||
ClientReliableWrite_Begin (cl, svcq2_stufftext, strlen(string)+3);
|
||||
ClientReliableWrite_String (cl, string);
|
||||
|
@ -252,6 +254,7 @@ void SV_StuffcmdToClient_Unreliable(client_t *cl, const char *string)
|
|||
case SCP_BAD: //bot
|
||||
break;
|
||||
case SCP_QUAKE2:
|
||||
case SCP_QUAKE2EX:
|
||||
#ifdef Q2SERVER
|
||||
ClientReliableWrite_Begin (cl, svcq2_stufftext, strlen(string)+3);
|
||||
ClientReliableWrite_String (cl, string);
|
||||
|
@ -604,7 +607,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
|
|||
&& !sv.nqmulticast.cursize
|
||||
#endif
|
||||
#ifdef Q2SERVER
|
||||
&& !sv.q2multicast.cursize
|
||||
&& !sv.q2multicast[0].cursize
|
||||
#endif
|
||||
)
|
||||
return;
|
||||
|
@ -780,11 +783,11 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
|
|||
if (!split)
|
||||
continue;
|
||||
|
||||
switch (client->protocol)
|
||||
safeswitch (client->protocol)
|
||||
{
|
||||
case SCP_BAD:
|
||||
continue; //a bot.
|
||||
default:
|
||||
safedefault:
|
||||
SV_Error("multicast: Client is using a bad protocol");
|
||||
|
||||
case SCP_QUAKE3:
|
||||
|
@ -811,11 +814,20 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
|
|||
case SCP_QUAKE2:
|
||||
if (reliable)
|
||||
{
|
||||
ClientReliableCheckBlock(client, sv.q2multicast.cursize);
|
||||
ClientReliableWrite_SZ(client, sv.q2multicast.data, sv.q2multicast.cursize);
|
||||
ClientReliableCheckBlock(client, sv.q2multicast[0].cursize);
|
||||
ClientReliableWrite_SZ(client, sv.q2multicast[0].data, sv.q2multicast[0].cursize);
|
||||
}
|
||||
else
|
||||
SZ_Write (&client->datagram, sv.q2multicast.data, sv.q2multicast.cursize);
|
||||
SZ_Write (&client->datagram, sv.q2multicast[0].data, sv.q2multicast[0].cursize);
|
||||
break;
|
||||
case SCP_QUAKE2EX:
|
||||
if (reliable)
|
||||
{
|
||||
ClientReliableCheckBlock(client, sv.q2multicast[1].cursize);
|
||||
ClientReliableWrite_SZ(client, sv.q2multicast[1].data, sv.q2multicast[1].cursize);
|
||||
}
|
||||
else
|
||||
SZ_Write (&client->datagram, sv.q2multicast[1].data, sv.q2multicast[1].cursize);
|
||||
break;
|
||||
#endif
|
||||
case SCP_QUAKEWORLD:
|
||||
|
@ -901,7 +913,8 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
|
|||
SZ_Clear (&sv.nqmulticast);
|
||||
#endif
|
||||
#ifdef Q2SERVER
|
||||
SZ_Clear (&sv.q2multicast);
|
||||
SZ_Clear (&sv.q2multicast[0]);
|
||||
SZ_Clear (&sv.q2multicast[1]);
|
||||
#endif
|
||||
SZ_Clear (&sv.multicast);
|
||||
}
|
||||
|
@ -3151,6 +3164,7 @@ void SV_UpdateToReliableMessages (void)
|
|||
{
|
||||
case SCP_BAD: //bots
|
||||
case SCP_QUAKE2:
|
||||
case SCP_QUAKE2EX:
|
||||
case SCP_QUAKE3:
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -245,7 +245,7 @@ void SV_New_f (void)
|
|||
int playernum;
|
||||
int splitnum;
|
||||
client_t *split;
|
||||
unsigned int fteext1, fteext2, ezext1; //reported to client
|
||||
unsigned int fteext1, fteext2, ezext1, vers; //reported to client
|
||||
|
||||
host_client->prespawn_stage = PRESPAWN_INVALID;
|
||||
host_client->prespawn_idx = 0;
|
||||
|
@ -306,18 +306,39 @@ void SV_New_f (void)
|
|||
fteext1 = host_client->fteprotocolextensions;
|
||||
fteext2 = host_client->fteprotocolextensions2;
|
||||
ezext1 = host_client->ezprotocolextensions1;
|
||||
|
||||
if (ISQ2CLIENT(host_client))
|
||||
{
|
||||
if (host_client->protocol==SCP_QUAKE2EX)
|
||||
{
|
||||
// if (svs.netprim.coordtype == COORDTYPE_FLOAT_32)
|
||||
vers = PROTOCOL_VERSION_Q2EX;
|
||||
// else
|
||||
// vers = PROTOCOL_VERSION_Q2EXDEMO; //has some explicitly bigger sizes without using generic primatives.
|
||||
}
|
||||
else
|
||||
vers = PROTOCOL_VERSION_Q2;
|
||||
}
|
||||
else
|
||||
vers = PROTOCOL_VERSION_QW;
|
||||
|
||||
switch(svs.netprim.coordtype)
|
||||
{
|
||||
case COORDTYPE_FLOAT_32:
|
||||
fteext1 |= PEXT_FLOATCOORDS;
|
||||
ezext1 &= ~EZPEXT1_FLOATENTCOORDS; //redundant.
|
||||
if (!(host_client->fteprotocolextensions & PEXT_FLOATCOORDS))
|
||||
if (host_client->protocol==SCP_QUAKE2EX)
|
||||
fteext1 &= ~PEXT_FLOATCOORDS;
|
||||
else
|
||||
{
|
||||
SV_ClientPrintf(host_client, 2, "\nForcing bigcoords.\nIf this doesn't work, please update your engine\n");
|
||||
host_client->fteprotocolextensions |= PEXT_FLOATCOORDS;
|
||||
// Con_Printf("%s does not support bigcoords\n", host_client->name);
|
||||
// host_client->drop = true;
|
||||
// return;
|
||||
fteext1 |= PEXT_FLOATCOORDS;
|
||||
ezext1 &= ~EZPEXT1_FLOATENTCOORDS; //redundant.
|
||||
if (!(host_client->fteprotocolextensions & PEXT_FLOATCOORDS))
|
||||
{
|
||||
SV_ClientPrintf(host_client, 2, "\nForcing bigcoords.\nIf this doesn't work, please update your engine\n");
|
||||
host_client->fteprotocolextensions |= PEXT_FLOATCOORDS;
|
||||
// Con_Printf("%s does not support bigcoords\n", host_client->name);
|
||||
// host_client->drop = true;
|
||||
// return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case COORDTYPE_FIXED_13_3:
|
||||
|
@ -350,10 +371,14 @@ void SV_New_f (void)
|
|||
ClientReliableWrite_Long (host_client, PROTOCOL_VERSION_EZQUAKE1);
|
||||
ClientReliableWrite_Long (host_client, ezext1);
|
||||
}
|
||||
ClientReliableWrite_Long (host_client, ISQ2CLIENT(host_client)?PROTOCOL_VERSION_Q2:PROTOCOL_VERSION_QW);
|
||||
ClientReliableWrite_Long (host_client, vers);
|
||||
ClientReliableWrite_Long (host_client, svs.spawncount);
|
||||
if (ISQ2CLIENT(host_client))
|
||||
ClientReliableWrite_Byte (host_client, 0);
|
||||
{
|
||||
ClientReliableWrite_Byte (host_client, 0); //demo mode.
|
||||
if (host_client->protocol==SCP_QUAKE2EX)
|
||||
ClientReliableWrite_Byte (host_client, 10); //tick rate.
|
||||
}
|
||||
ClientReliableWrite_String (host_client, gamedir);
|
||||
|
||||
if (fteext2 & PEXT2_MAXPLAYERS)
|
||||
|
@ -382,6 +407,18 @@ void SV_New_f (void)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (host_client->protocol==SCP_QUAKE2EX)
|
||||
{ //let it know how many to expect
|
||||
for (split = host_client, splitnum=0; split; split = split->controlled)
|
||||
splitnum++;
|
||||
|
||||
if (splitnum != 1)
|
||||
{
|
||||
ClientReliableWrite_Short (host_client, -2);
|
||||
ClientReliableWrite_Short (host_client, splitnum);
|
||||
}
|
||||
}
|
||||
|
||||
splitnum = 0;
|
||||
for (split = host_client; split; split = split->controlled)
|
||||
{
|
||||
|
@ -421,7 +458,8 @@ void SV_New_f (void)
|
|||
if (sv.state == ss_cinematic)
|
||||
playernum = -1;
|
||||
ClientReliableWrite_Short (host_client, playernum);
|
||||
break;
|
||||
if (host_client->protocol!=SCP_QUAKE2EX)
|
||||
break;
|
||||
}
|
||||
else
|
||||
ClientReliableWrite_Byte (host_client, playernum);
|
||||
|
@ -892,6 +930,33 @@ void SVNQ_New_f (void)
|
|||
|
||||
|
||||
#ifdef Q2SERVER
|
||||
|
||||
static const char *SVQ2_GetQ2EXConfigString(int i)
|
||||
{ //remap from vanilla to q2e
|
||||
if (i == Q2EXCS_MAPCHECKSUM && sv.world.worldmodel)
|
||||
return va("%i", sv.world.worldmodel->checksum2);
|
||||
#define REMAPR(n,l) if (i >= Q2EXCS_##n && i < Q2EXCS_##n+Q2MAX_##l) return sv.strings.configstring[i-Q2EXCS_##n+Q2CS_##n]; else
|
||||
#define REMAPS(n) if (i == Q2EXCS_##n) return sv.strings.configstring[i-Q2EXCS_##n+Q2CS_##n]; else
|
||||
#define Q2MAX_STATUSBAR 1//(Q2EXCS_AIRACCEL-Q2EXCS_STATUSBAR)
|
||||
REMAPS(NAME)
|
||||
REMAPS(CDTRACK)
|
||||
REMAPS(SKY)
|
||||
REMAPS(SKYAXIS)
|
||||
REMAPS(SKYROTATE)
|
||||
REMAPR(STATUSBAR, STATUSBAR)
|
||||
REMAPS(AIRACCEL)
|
||||
REMAPS(MAXCLIENTS)
|
||||
REMAPS(MAPCHECKSUM)
|
||||
REMAPR(MODELS, MODELS)
|
||||
REMAPR(SOUNDS, SOUNDS)
|
||||
REMAPR(IMAGES, IMAGES)
|
||||
REMAPR(LIGHTS, LIGHTSTYLES)
|
||||
REMAPR(ITEMS, ITEMS)
|
||||
REMAPR(PLAYERSKINS, CLIENTS)
|
||||
REMAPR(GENERAL, GENERAL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SVQ2_ConfigStrings_f (void)
|
||||
{
|
||||
unsigned int start;
|
||||
|
@ -916,50 +981,70 @@ void SVQ2_ConfigStrings_f (void)
|
|||
start = strtoul(Cmd_Argv(2), NULL, 0);
|
||||
|
||||
// write a packet full of data
|
||||
|
||||
while ( host_client->netchan.message.cursize < host_client->netchan.message.maxsize/2
|
||||
&& start < Q2MAX_CONFIGSTRINGS)
|
||||
if (host_client->protocol == SCP_QUAKE2EX)
|
||||
{
|
||||
str = sv.strings.configstring[start];
|
||||
if (str && *str)
|
||||
while ( host_client->netchan.message.cursize < host_client->netchan.message.maxsize/2
|
||||
&& start < Q2EXMAX_CONFIGSTRINGS)
|
||||
{
|
||||
MSG_WriteByte (&host_client->netchan.message, svcq2_configstring);
|
||||
MSG_WriteShort (&host_client->netchan.message, (unsigned short)start);
|
||||
MSG_WriteString (&host_client->netchan.message, str);
|
||||
str = SVQ2_GetQ2EXConfigString(start);
|
||||
if (str && *str)
|
||||
{
|
||||
MSG_WriteByte (&host_client->netchan.message, svcq2_configstring);
|
||||
MSG_WriteShort (&host_client->netchan.message, (unsigned short)start);
|
||||
MSG_WriteString (&host_client->netchan.message, str);
|
||||
}
|
||||
start++;
|
||||
}
|
||||
start++;
|
||||
|
||||
if (start == Q2EXMAX_CONFIGSTRINGS)
|
||||
start = 0xc000+MAX_PRECACHE_SOUNDS;
|
||||
}
|
||||
|
||||
//model overflows
|
||||
if (start == Q2MAX_CONFIGSTRINGS)
|
||||
start = 0x8000;
|
||||
while ( host_client->netchan.message.cursize < host_client->netchan.message.maxsize/2
|
||||
&& start < 0x8000+MAX_PRECACHE_MODELS)
|
||||
else
|
||||
{
|
||||
str = sv.strings.q2_extramodels[start-0x8000];
|
||||
if (str && *str)
|
||||
while ( host_client->netchan.message.cursize < host_client->netchan.message.maxsize/2
|
||||
&& start < Q2MAX_CONFIGSTRINGS)
|
||||
{
|
||||
MSG_WriteByte (&host_client->netchan.message, svcq2_configstring);
|
||||
MSG_WriteShort (&host_client->netchan.message, start);
|
||||
MSG_WriteString (&host_client->netchan.message, str);
|
||||
str = sv.strings.configstring[start];
|
||||
if (str && *str)
|
||||
{
|
||||
MSG_WriteByte (&host_client->netchan.message, svcq2_configstring);
|
||||
MSG_WriteShort (&host_client->netchan.message, (unsigned short)start);
|
||||
MSG_WriteString (&host_client->netchan.message, str);
|
||||
}
|
||||
start++;
|
||||
}
|
||||
start++;
|
||||
}
|
||||
|
||||
//sound overflows
|
||||
if (start == 0x8000+MAX_PRECACHE_MODELS)
|
||||
start = 0xc000;
|
||||
while ( host_client->netchan.message.cursize < host_client->netchan.message.maxsize/2
|
||||
&& start < 0xc000+MAX_PRECACHE_SOUNDS)
|
||||
{
|
||||
str = sv.strings.q2_extrasounds[start-0xc000];
|
||||
if (str && *str)
|
||||
//model overflows
|
||||
if (start == Q2MAX_CONFIGSTRINGS)
|
||||
start = 0x8000;
|
||||
while ( host_client->netchan.message.cursize < host_client->netchan.message.maxsize/2
|
||||
&& start < 0x8000+MAX_PRECACHE_MODELS)
|
||||
{
|
||||
MSG_WriteByte (&host_client->netchan.message, svcq2_configstring);
|
||||
MSG_WriteShort (&host_client->netchan.message, start);
|
||||
MSG_WriteString (&host_client->netchan.message, str);
|
||||
str = sv.strings.q2_extramodels[start-0x8000];
|
||||
if (str && *str)
|
||||
{
|
||||
MSG_WriteByte (&host_client->netchan.message, svcq2_configstring);
|
||||
MSG_WriteShort (&host_client->netchan.message, start);
|
||||
MSG_WriteString (&host_client->netchan.message, str);
|
||||
}
|
||||
start++;
|
||||
}
|
||||
|
||||
//sound overflows
|
||||
if (start == 0x8000+MAX_PRECACHE_MODELS)
|
||||
start = 0xc000;
|
||||
while ( host_client->netchan.message.cursize < host_client->netchan.message.maxsize/2
|
||||
&& start < 0xc000+MAX_PRECACHE_SOUNDS)
|
||||
{
|
||||
str = sv.strings.q2_extrasounds[start-0xc000];
|
||||
if (str && *str)
|
||||
{
|
||||
MSG_WriteByte (&host_client->netchan.message, svcq2_configstring);
|
||||
MSG_WriteShort (&host_client->netchan.message, start);
|
||||
MSG_WriteString (&host_client->netchan.message, str);
|
||||
}
|
||||
start++;
|
||||
}
|
||||
start++;
|
||||
}
|
||||
|
||||
// send next command
|
||||
|
@ -1015,7 +1100,7 @@ void SVQ2_BaseLines_f (void)
|
|||
if (base->modelindex || base->sound || base->effects)
|
||||
{
|
||||
MSG_WriteByte (&host_client->netchan.message, svcq2_spawnbaseline);
|
||||
MSGQ2_WriteDeltaEntity (&nullstate, base, &host_client->netchan.message, true, true);
|
||||
MSGQ2_WriteDeltaEntity (&nullstate, base, &host_client->netchan.message, true, true, host_client->protocol==SCP_QUAKE2EX);
|
||||
}
|
||||
start++;
|
||||
}
|
||||
|
@ -2417,7 +2502,7 @@ void SV_Begin_f (void)
|
|||
|
||||
if (!SV_CheckRealIP(host_client, true))
|
||||
{
|
||||
if (host_client->protocol == SCP_QUAKE2)
|
||||
if (ISQ2CLIENT(host_client))
|
||||
ClientReliableWrite_Begin (host_client, svcq2_stufftext, 13+strlen(Cmd_Args()));
|
||||
else
|
||||
ClientReliableWrite_Begin (host_client, svc_stufftext, 13+strlen(Cmd_Args()));
|
||||
|
@ -4094,6 +4179,8 @@ static void SV_SendQEXChat(client_t *to, int clcolour, int chatcolour, const cha
|
|||
case SCP_QUAKE3:
|
||||
case SCP_QUAKEWORLD:
|
||||
break; //doesn't make sense.
|
||||
case SCP_QUAKE2EX:
|
||||
break; //send it via the lobby...
|
||||
case SCP_DARKPLACES6:
|
||||
case SCP_DARKPLACES7:
|
||||
case SCP_NETQUAKE:
|
||||
|
@ -4511,7 +4598,7 @@ static void SV_UpdateSeats(client_t *controller)
|
|||
client_t *cl;
|
||||
int curclients;
|
||||
|
||||
if (controller->protocol == SCP_QUAKE2)
|
||||
if (ISQ2CLIENT(controller))
|
||||
return; //wait for the clientinfo stuff instead.
|
||||
|
||||
for (curclients = 0, cl = controller; cl; cl = cl->controlled)
|
||||
|
@ -5870,17 +5957,19 @@ static void Cmd_FPSList_f(void)
|
|||
|
||||
SV_CalcNetRates(cl, &ftime, &frames, &minf, &maxf);
|
||||
|
||||
switch(cl->protocol)
|
||||
safeswitch(cl->protocol)
|
||||
{
|
||||
case SCP_QUAKEWORLD: protoname = (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)?"fteqw":(cl->fteprotocolextensions||cl->fteprotocolextensions2?"qw":"qwid"); break;
|
||||
case SCP_QUAKE2: protoname = "q2"; break;
|
||||
case SCP_QUAKE2EX: protoname = "q2"; break;
|
||||
case SCP_QUAKE3: protoname = "q3"; break;
|
||||
case SCP_NETQUAKE: protoname = (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)?"ftenq":"nq"; break;
|
||||
case SCP_BJP3: protoname = (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)?"ftenq":"bjp3"; break;
|
||||
case SCP_FITZ666: protoname = (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)?"ftenq":"fitz"; break;
|
||||
case SCP_DARKPLACES6: protoname = "dpp6"; break;
|
||||
case SCP_DARKPLACES7: protoname = "dpp7"; break;
|
||||
default: protoname = "?"; break;
|
||||
case SCP_BAD: protoname = "bot"; break;
|
||||
safedefault: protoname = "?"; break;
|
||||
}
|
||||
|
||||
if (frames)
|
||||
|
@ -8588,9 +8677,67 @@ static void SVQ2_ClientThink(q2edict_t *ed, usercmd_t *cmd)
|
|||
q2.lightlevel = cmd->lightlevel;
|
||||
ge->ClientThink (ed, &q2);
|
||||
}
|
||||
void InfoBuf_FromString_Q2EX(infobuf_t *info, const char *infostring, int seat)
|
||||
{
|
||||
qboolean match;
|
||||
int foundseat;
|
||||
char *postfix, *end;
|
||||
InfoBuf_Clear(info, true);
|
||||
if (*infostring && *infostring == '\\')
|
||||
infostring++;
|
||||
|
||||
//all keys must start with a backslash
|
||||
do
|
||||
{
|
||||
const char *keystart = infostring;
|
||||
const char *keyend;
|
||||
const char *valstart;
|
||||
const char *valend;
|
||||
char *key;
|
||||
char *val;
|
||||
size_t keysize, valsize;
|
||||
while (*infostring)
|
||||
{
|
||||
if (*infostring == '\\')
|
||||
break;
|
||||
else infostring += 1;
|
||||
}
|
||||
keyend = infostring;
|
||||
if (*infostring++ != '\\')
|
||||
break; //missing value...
|
||||
valstart = infostring;
|
||||
while (*infostring)
|
||||
{
|
||||
if (*infostring == '\\')
|
||||
break;
|
||||
else infostring += 1;
|
||||
}
|
||||
valend = infostring;
|
||||
|
||||
key = InfoBuf_DecodeString(keystart, keyend, &keysize);
|
||||
match = true; //all, if there's no _#
|
||||
postfix = strrchr(key, '_');
|
||||
if (postfix && postfix[1])
|
||||
{
|
||||
foundseat = strtol(postfix+1, &end, 10);
|
||||
if (!*end)
|
||||
{
|
||||
*postfix = 0; //strip the trailing part of the key name.
|
||||
match = foundseat == seat; //there's an underscore, and a number, and nothing else after it...
|
||||
}
|
||||
}
|
||||
if (match)
|
||||
{
|
||||
val = InfoBuf_DecodeString(valstart, valend, &valsize);
|
||||
InfoBuf_SetStarBlobKey(info, key, val, valsize);
|
||||
Z_Free(val);
|
||||
}
|
||||
Z_Free(key);
|
||||
} while (*infostring++ == '\\');
|
||||
}
|
||||
void SVQ2_ExecuteClientMessage (client_t *cl)
|
||||
{
|
||||
int c;
|
||||
int c, lc=-1;
|
||||
char *s;
|
||||
usercmd_t oldest, oldcmd, newcmd;
|
||||
q2client_frame_t *frame;
|
||||
|
@ -8609,10 +8756,11 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
|
|||
|
||||
// make sure the reply sequence number matches the incoming
|
||||
// sequence number
|
||||
if (cl->netchan.incoming_sequence >= cl->netchan.outgoing_sequence)
|
||||
//FIXME: is this actually needed?
|
||||
/*if (cl->netchan.incoming_sequence >= cl->netchan.outgoing_sequence)
|
||||
cl->netchan.outgoing_sequence = cl->netchan.incoming_sequence;
|
||||
else
|
||||
cl->send_message = false; // don't reply, sequences have slipped
|
||||
cl->send_message = false; // don't reply, sequences have slipped*/
|
||||
|
||||
// calc ping time
|
||||
if (cl->netchan.outgoing_sequence - cl->netchan.incoming_acknowledged > Q2UPDATE_MASK)
|
||||
|
@ -8661,7 +8809,7 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
|
|||
{
|
||||
if (msg_badread)
|
||||
{
|
||||
Con_Printf ("SVQ2_ExecuteClientMessage: badread\n");
|
||||
Con_Printf ("SVQ2_ExecuteClientMessage: badread (parsing q2clc_%i)\n", lc);
|
||||
SV_DropClient (cl);
|
||||
return;
|
||||
}
|
||||
|
@ -8670,6 +8818,9 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
|
|||
if (c == -1)
|
||||
break;
|
||||
|
||||
// if (sv_shownet.ival)
|
||||
// Con_Printf("%i: %i\n", (net_message.currentbit>>3)-1, c);
|
||||
|
||||
safeswitch ((enum clcq2_ops_e)c)
|
||||
{
|
||||
case clcq2_nop:
|
||||
|
@ -8682,7 +8833,19 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
|
|||
for (checksumIndex = 0, split = cl; split && checksumIndex < move_issued; checksumIndex++)
|
||||
split = split->controlled;
|
||||
|
||||
if (move_issued)
|
||||
if (cl->protocol == SCP_QUAKE2EX)
|
||||
{
|
||||
if (move_issued)
|
||||
return; //no dupes.
|
||||
lastframe = MSG_ReadLong();
|
||||
if (lastframe != split->delta_sequence)
|
||||
split->delta_sequence = lastframe;
|
||||
|
||||
nextseat:
|
||||
checksumIndex = MSG_GetReadCount();
|
||||
checksum = (qbyte)MSG_ReadByte ();
|
||||
}
|
||||
else if (move_issued)
|
||||
{
|
||||
checksumIndex = -1;
|
||||
checksum = 0;
|
||||
|
@ -8692,7 +8855,6 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
|
|||
checksumIndex = MSG_GetReadCount();
|
||||
checksum = (qbyte)MSG_ReadByte ();
|
||||
|
||||
|
||||
lastframe = MSG_ReadLong();
|
||||
if (lastframe != split->delta_sequence)
|
||||
{
|
||||
|
@ -8700,9 +8862,9 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
|
|||
}
|
||||
}
|
||||
|
||||
MSGQ2_ReadDeltaUsercmd (&nullcmd, &oldest);
|
||||
MSGQ2_ReadDeltaUsercmd (&oldest, &oldcmd);
|
||||
MSGQ2_ReadDeltaUsercmd (&oldcmd, &newcmd);
|
||||
MSGQ2_ReadDeltaUsercmd (cl, &nullcmd, &oldest);
|
||||
MSGQ2_ReadDeltaUsercmd (cl, &oldest, &oldcmd);
|
||||
MSGQ2_ReadDeltaUsercmd (cl, &oldcmd, &newcmd);
|
||||
|
||||
if ( split && split->state == cs_spawned )
|
||||
{
|
||||
|
@ -8758,24 +8920,53 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
|
|||
split->lastcmd = newcmd;
|
||||
}
|
||||
move_issued++;
|
||||
|
||||
if (cl->protocol == SCP_QUAKE2EX && split->controlled)
|
||||
{ //q2ex needs them all upfront.
|
||||
split = split->controlled;
|
||||
//with each seat having its own private checksum, for some reason.
|
||||
goto nextseat;
|
||||
}
|
||||
break;
|
||||
|
||||
case clcq2_userinfo:
|
||||
//FIXME: allows the client to set * keys mid-game.
|
||||
s = MSG_ReadString();
|
||||
InfoBuf_FromString(&cl->userinfo, s, false);
|
||||
SV_ExtractFromUserinfo(cl, true); //let the server routines know
|
||||
ge->ClientUserinfoChanged (cl->q2edict, s); //tell the gamecode
|
||||
if (cl->protocol == SCP_QUAKE2EX)
|
||||
{
|
||||
int seat;
|
||||
char useruserinfo[1024];
|
||||
for (split = cl, seat = 0; split; split = split->controlled, seat++)
|
||||
{
|
||||
InfoBuf_FromString_Q2EX(&split->userinfo, s, seat);
|
||||
InfoBuf_ToString(&split->userinfo, useruserinfo, sizeof(useruserinfo), NULL, NULL, NULL, NULL, NULL);
|
||||
SV_ExtractFromUserinfo(split, true); //let the server routines know
|
||||
ge->ClientUserinfoChanged (split->q2edict, useruserinfo); //tell the gamecode
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InfoBuf_FromString(&cl->userinfo, s, false);
|
||||
SV_ExtractFromUserinfo(cl, true); //let the server routines know
|
||||
ge->ClientUserinfoChanged (cl->q2edict, s); //tell the gamecode
|
||||
}
|
||||
break;
|
||||
|
||||
case clcq2_stringcmd:
|
||||
case clcq2_stringcmd_seat:
|
||||
c = MSG_ReadByte();
|
||||
if (c == clcq2_stringcmd_seat)
|
||||
c = MSG_ReadByte();
|
||||
else if (cl->protocol == SCP_QUAKE2EX)
|
||||
c = MSG_ReadByte()-1;
|
||||
else
|
||||
c = 0;
|
||||
|
||||
host_client = cl;
|
||||
while (c --> 0 && host_client->controlled)
|
||||
host_client = host_client->controlled;
|
||||
sv_player = host_client->edict;
|
||||
//fall through
|
||||
case clcq2_stringcmd:
|
||||
|
||||
//regular stringcmd
|
||||
s = MSG_ReadString ();
|
||||
SV_ExecuteUserCommand (s, false);
|
||||
|
||||
|
@ -8796,10 +8987,11 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
|
|||
case clcr1q2_setting:
|
||||
case clcr1q2_multimoves:
|
||||
safedefault:
|
||||
Con_Printf ("SVQ2_ReadClientMessage: unknown command char %i\n", c);
|
||||
Con_Printf ("SVQ2_ReadClientMessage: unknown command char %i (last was q2clc_%i)\n", c, lc);
|
||||
SV_DropClient (cl);
|
||||
return;
|
||||
}
|
||||
lc = c;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -9146,6 +9338,7 @@ void SVNQ_ExecuteClientMessage (client_t *cl)
|
|||
case SCP_BAD:
|
||||
case SCP_QUAKEWORLD:
|
||||
case SCP_QUAKE2:
|
||||
case SCP_QUAKE2EX:
|
||||
case SCP_QUAKE3:
|
||||
case SCP_DARKPLACES6:
|
||||
case SCP_DARKPLACES7:
|
||||
|
|
|
@ -27,6 +27,15 @@ Encode a client frame onto the network channel
|
|||
=============================================================================
|
||||
*/
|
||||
|
||||
static void MSG_WriteSizeQ2E(sizebuf_t *sb, int solid)
|
||||
{ //urgh...
|
||||
if (solid != ES_SOLID_BSP && solid != ES_SOLID_NOT)
|
||||
solid = ((solid & 255)<<0) //recode fte's sizes to q2ex's...
|
||||
| ((solid & 255)<<8)
|
||||
| (((solid>>8) & 255)<<16)
|
||||
| ((((solid>>16) & 65535) - 32768+32)<<24);
|
||||
MSG_WriteLong(sb, solid);
|
||||
}
|
||||
/*
|
||||
==================
|
||||
MSG_WriteDeltaEntity
|
||||
|
@ -35,9 +44,9 @@ Writes part of a packetentities message.
|
|||
Can delta from either a baseline or a previous packet_entity
|
||||
==================
|
||||
*/
|
||||
void MSGQ2_WriteDeltaEntity (q2entity_state_t *from, q2entity_state_t *to, sizebuf_t *msg, qboolean force, qboolean newentity)
|
||||
void MSGQ2_WriteDeltaEntity (q2entity_state_t *from, q2entity_state_t *to, sizebuf_t *msg, qboolean force, qboolean newentity, qboolean q2ex)
|
||||
{
|
||||
int bits;
|
||||
quint64_t bits;
|
||||
|
||||
if (!to->number)
|
||||
Sys_Error ("Unset entity number");
|
||||
|
@ -84,7 +93,16 @@ void MSGQ2_WriteDeltaEntity (q2entity_state_t *from, q2entity_state_t *to, sizeb
|
|||
|
||||
if ( to->effects != from->effects )
|
||||
{
|
||||
if (to->effects < 256)
|
||||
if ((uint64_t)to->effects > 0xffffffffu)
|
||||
{ //this encoding is weird, Q2UEX_EFFECTS64 without any of the other flags is equivelent to the 8|16==32bit flags, so is pointless without the extra ones.
|
||||
if (to->effects < (uint64_t)256<<32)
|
||||
bits |= Q2U_EFFECTS8|Q2UEX_EFFECTS64;
|
||||
else if (to->effects < (uint64_t)0x8000<<32)
|
||||
bits |= Q2U_EFFECTS16|Q2UEX_EFFECTS64;
|
||||
else
|
||||
bits |= Q2U_EFFECTS8|Q2U_EFFECTS16|Q2UEX_EFFECTS64;
|
||||
}
|
||||
else if (to->effects < 256)
|
||||
bits |= Q2U_EFFECTS8;
|
||||
else if (to->effects < 0x8000)
|
||||
bits |= Q2U_EFFECTS16;
|
||||
|
@ -134,13 +152,20 @@ void MSGQ2_WriteDeltaEntity (q2entity_state_t *from, q2entity_state_t *to, sizeb
|
|||
bits |= Q2UX_INDEX16;
|
||||
}
|
||||
|
||||
if ( to->sound != from->sound )
|
||||
if ( to->sound != from->sound /*||vol or attn*/)
|
||||
{
|
||||
bits |= Q2U_SOUND;
|
||||
if (to->sound > 0xff)
|
||||
if (to->sound > 0xff && !q2ex)
|
||||
bits |= Q2UX_INDEX16;
|
||||
}
|
||||
|
||||
|
||||
// if (to->alpha != from->alpha) bits |= Q2UEX_ALPHA;
|
||||
// if (to->scale != from->scale)bits |= Q2UEX_SCALE;
|
||||
// if (to->instance != from->instance) bits |= Q2UEX_INSTANCE;
|
||||
// if (to->owner != from->owner) bits |= Q2UEX_OWNER;
|
||||
// if (to->oldframe != from->oldframe) bits |= Q2UEX_OLDFRAME;
|
||||
|
||||
if (newentity || (to->renderfx & Q2RF_BEAM))
|
||||
bits |= Q2U_OLDORIGIN;
|
||||
|
||||
|
@ -152,7 +177,9 @@ void MSGQ2_WriteDeltaEntity (q2entity_state_t *from, q2entity_state_t *to, sizeb
|
|||
|
||||
//----------
|
||||
|
||||
if (bits & 0xff000000)
|
||||
if (bits & 0xff00000000)
|
||||
bits |= Q2UEX_MOREBITS4 | Q2U_MOREBITS3 | Q2U_MOREBITS2 | Q2U_MOREBITS1;
|
||||
else if (bits & 0xff000000)
|
||||
bits |= Q2U_MOREBITS3 | Q2U_MOREBITS2 | Q2U_MOREBITS1;
|
||||
else if (bits & 0x00ff0000)
|
||||
bits |= Q2U_MOREBITS2 | Q2U_MOREBITS1;
|
||||
|
@ -161,7 +188,14 @@ void MSGQ2_WriteDeltaEntity (q2entity_state_t *from, q2entity_state_t *to, sizeb
|
|||
|
||||
MSG_WriteByte (msg, bits&255 );
|
||||
|
||||
if (bits & 0xff000000)
|
||||
if (bits & 0xff00000000)
|
||||
{
|
||||
MSG_WriteByte (msg, (bits>>8)&255 );
|
||||
MSG_WriteByte (msg, (bits>>16)&255 );
|
||||
MSG_WriteByte (msg, (bits>>24)&255 );
|
||||
MSG_WriteByte (msg, (bits>>32)&255 );
|
||||
}
|
||||
else if (bits & 0xff000000)
|
||||
{
|
||||
MSG_WriteByte (msg, (bits>>8)&255 );
|
||||
MSG_WriteByte (msg, (bits>>16)&255 );
|
||||
|
@ -225,13 +259,25 @@ void MSGQ2_WriteDeltaEntity (q2entity_state_t *from, q2entity_state_t *to, sizeb
|
|||
else if (bits & Q2U_SKIN16)
|
||||
MSG_WriteShort (msg, to->skinnum);
|
||||
|
||||
|
||||
if ( (bits & (Q2U_EFFECTS8|Q2U_EFFECTS16)) == (Q2U_EFFECTS8|Q2U_EFFECTS16) )
|
||||
if (bits & Q2UEX_EFFECTS64)
|
||||
{
|
||||
MSG_WriteLong (msg, to->effects);
|
||||
else if (bits & Q2U_EFFECTS8)
|
||||
MSG_WriteByte (msg, to->effects);
|
||||
else if (bits & Q2U_EFFECTS16)
|
||||
MSG_WriteShort (msg, to->effects);
|
||||
if ( (bits & (Q2U_EFFECTS8|Q2U_EFFECTS16)) == (Q2U_EFFECTS8|Q2U_EFFECTS16) )
|
||||
MSG_WriteLong (msg, (quint64_t)to->effects>>32);
|
||||
else if (bits & Q2U_EFFECTS8)
|
||||
MSG_WriteByte (msg, (quint64_t)to->effects>>32);
|
||||
else if (bits & Q2U_EFFECTS16)
|
||||
MSG_WriteShort (msg, (quint64_t)to->effects>>32);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (bits & (Q2U_EFFECTS8|Q2U_EFFECTS16)) == (Q2U_EFFECTS8|Q2U_EFFECTS16) )
|
||||
MSG_WriteLong (msg, to->effects);
|
||||
else if (bits & Q2U_EFFECTS8)
|
||||
MSG_WriteByte (msg, to->effects);
|
||||
else if (bits & Q2U_EFFECTS16)
|
||||
MSG_WriteShort (msg, to->effects);
|
||||
}
|
||||
|
||||
if ( (bits & (Q2U_RENDERFX8|Q2U_RENDERFX16)) == (Q2U_RENDERFX8|Q2U_RENDERFX16) )
|
||||
MSG_WriteLong (msg, to->renderfx);
|
||||
|
@ -240,44 +286,113 @@ void MSGQ2_WriteDeltaEntity (q2entity_state_t *from, q2entity_state_t *to, sizeb
|
|||
else if (bits & Q2U_RENDERFX16)
|
||||
MSG_WriteShort (msg, to->renderfx);
|
||||
|
||||
if (bits & Q2U_ORIGIN1)
|
||||
MSG_WriteCoord (msg, to->origin[0]);
|
||||
if (bits & Q2U_ORIGIN2)
|
||||
MSG_WriteCoord (msg, to->origin[1]);
|
||||
if (bits & Q2U_ORIGIN3)
|
||||
MSG_WriteCoord (msg, to->origin[2]);
|
||||
|
||||
if (bits & Q2U_ANGLE1)
|
||||
MSG_WriteAngle(msg, to->angles[0]);
|
||||
if (bits & Q2U_ANGLE2)
|
||||
MSG_WriteAngle(msg, to->angles[1]);
|
||||
if (bits & Q2U_ANGLE3)
|
||||
MSG_WriteAngle(msg, to->angles[2]);
|
||||
|
||||
if (bits & Q2U_OLDORIGIN)
|
||||
if (q2ex)
|
||||
{
|
||||
MSG_WriteCoord (msg, to->old_origin[0]);
|
||||
MSG_WriteCoord (msg, to->old_origin[1]);
|
||||
MSG_WriteCoord (msg, to->old_origin[2]);
|
||||
if (bits & Q2U_SOLID)
|
||||
MSG_WriteSizeQ2E(msg, to->solid);
|
||||
|
||||
if (!to->solid)
|
||||
{ //demos reportedly compress these... not that it makes a difference.
|
||||
if (bits & Q2U_ORIGIN1)
|
||||
MSG_WriteCoord (msg, to->origin[0]);
|
||||
if (bits & Q2U_ORIGIN2)
|
||||
MSG_WriteCoord (msg, to->origin[1]);
|
||||
if (bits & Q2U_ORIGIN3)
|
||||
MSG_WriteCoord (msg, to->origin[2]);
|
||||
|
||||
if (bits & Q2U_OLDORIGIN)
|
||||
{
|
||||
MSG_WriteCoord (msg, to->old_origin[0]);
|
||||
MSG_WriteCoord (msg, to->old_origin[1]);
|
||||
MSG_WriteCoord (msg, to->old_origin[2]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bits & Q2U_ORIGIN1)
|
||||
MSG_WriteFloat (msg, to->origin[0]);
|
||||
if (bits & Q2U_ORIGIN2)
|
||||
MSG_WriteFloat (msg, to->origin[1]);
|
||||
if (bits & Q2U_ORIGIN3)
|
||||
MSG_WriteFloat (msg, to->origin[2]);
|
||||
|
||||
if (bits & Q2U_OLDORIGIN)
|
||||
{
|
||||
MSG_WriteFloat (msg, to->old_origin[0]);
|
||||
MSG_WriteFloat (msg, to->old_origin[1]);
|
||||
MSG_WriteFloat (msg, to->old_origin[2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (bits & Q2U_ANGLE1)
|
||||
MSG_WriteFloat(msg, to->angles[0]); //blatent overkill.
|
||||
if (bits & Q2U_ANGLE2)
|
||||
MSG_WriteFloat(msg, to->angles[1]);
|
||||
if (bits & Q2U_ANGLE3)
|
||||
MSG_WriteFloat(msg, to->angles[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bits & Q2U_ORIGIN1)
|
||||
MSG_WriteCoord (msg, to->origin[0]);
|
||||
if (bits & Q2U_ORIGIN2)
|
||||
MSG_WriteCoord (msg, to->origin[1]);
|
||||
if (bits & Q2U_ORIGIN3)
|
||||
MSG_WriteCoord (msg, to->origin[2]);
|
||||
|
||||
if (bits & Q2U_ANGLE1)
|
||||
MSG_WriteAngle(msg, to->angles[0]);
|
||||
if (bits & Q2U_ANGLE2)
|
||||
MSG_WriteAngle(msg, to->angles[1]);
|
||||
if (bits & Q2U_ANGLE3)
|
||||
MSG_WriteAngle(msg, to->angles[2]);
|
||||
|
||||
if (bits & Q2U_OLDORIGIN)
|
||||
{
|
||||
MSG_WriteCoord (msg, to->old_origin[0]);
|
||||
MSG_WriteCoord (msg, to->old_origin[1]);
|
||||
MSG_WriteCoord (msg, to->old_origin[2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (bits & Q2U_SOUND)
|
||||
{
|
||||
if (bits & Q2UX_INDEX16)
|
||||
MSG_WriteShort (msg, to->sound);
|
||||
if (q2ex)
|
||||
{
|
||||
#if 1
|
||||
MSG_WriteShort (msg, to->sound&0x3fff);
|
||||
#else
|
||||
MSG_WriteShort (msg, to->sound&0x3fff | ((to->soundvol!=1)?0x4000:0)) | ((to->soundattn!=3)?0x8000:0));
|
||||
MSG_WriteByte (msg, to->soundvol*255);
|
||||
MSG_WriteByte (msg, to->soundattn); //this is normally a /64, but oh well...
|
||||
#endif
|
||||
}
|
||||
else
|
||||
MSG_WriteByte (msg, to->sound);
|
||||
{
|
||||
if (bits & Q2UX_INDEX16)
|
||||
MSG_WriteShort (msg, to->sound);
|
||||
else
|
||||
MSG_WriteByte (msg, to->sound);
|
||||
}
|
||||
}
|
||||
|
||||
if (bits & Q2U_EVENT)
|
||||
MSG_WriteByte (msg, to->event);
|
||||
if (bits & Q2U_SOLID)
|
||||
{
|
||||
if (msg->prim.flags & NPQ2_SOLID32)
|
||||
MSG_WriteLong(msg, to->solid);
|
||||
else
|
||||
MSG_WriteSize16(msg, to->solid);
|
||||
}
|
||||
|
||||
if (!q2ex)
|
||||
if (bits & Q2U_SOLID)
|
||||
{
|
||||
if (msg->prim.flags & NPQ2_SOLID32)
|
||||
MSG_WriteLong(msg, to->solid);
|
||||
else
|
||||
MSG_WriteSize16(msg, to->solid);
|
||||
}
|
||||
|
||||
if (bits & Q2UEX_ALPHA) MSG_WriteByte(msg, 0);
|
||||
if (bits & Q2UEX_SCALE) MSG_WriteByte(msg, 0);
|
||||
if (bits & Q2UEX_INSTANCE) MSG_WriteByte(msg, 0);
|
||||
if (bits & Q2UEX_OWNER) MSG_WriteShort(msg, 0);
|
||||
if (bits & Q2UEX_OLDFRAME) MSG_WriteShort(msg, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -288,7 +403,7 @@ SV_EmitPacketEntities
|
|||
Writes a delta update of an entity_state_t list to the message.
|
||||
=============
|
||||
*/
|
||||
void SVQ2_EmitPacketEntities (q2client_frame_t *from, q2client_frame_t *to, sizebuf_t *msg)
|
||||
void SVQ2_EmitPacketEntities (q2client_frame_t *from, q2client_frame_t *to, sizebuf_t *msg, qboolean q2ex)
|
||||
{
|
||||
q2entity_state_t *oldent, *newent;
|
||||
int oldindex, newindex;
|
||||
|
@ -338,7 +453,7 @@ void SVQ2_EmitPacketEntities (q2client_frame_t *from, q2client_frame_t *to, size
|
|||
if (msg->cursize+128 > msg->maxsize)
|
||||
memcpy(newent, oldent, sizeof(*newent)); //too much data, so set the ent up as the same as the old, so it's sent next frame
|
||||
else
|
||||
MSGQ2_WriteDeltaEntity (oldent, newent, msg, false, newent->number <= svs.allocated_client_slots);
|
||||
MSGQ2_WriteDeltaEntity (oldent, newent, msg, false, newent->number <= svs.allocated_client_slots, q2ex);
|
||||
oldindex++;
|
||||
newindex++;
|
||||
continue;
|
||||
|
@ -355,7 +470,7 @@ void SVQ2_EmitPacketEntities (q2client_frame_t *from, q2client_frame_t *to, size
|
|||
}
|
||||
else
|
||||
{
|
||||
MSGQ2_WriteDeltaEntity (&sv_baselines[newnum], newent, msg, true, true);
|
||||
MSGQ2_WriteDeltaEntity (&sv_baselines[newnum], newent, msg, true, true, q2ex);
|
||||
newindex++;
|
||||
}
|
||||
continue;
|
||||
|
@ -397,13 +512,16 @@ SV_WritePlayerstateToClient
|
|||
|
||||
=============
|
||||
*/
|
||||
void SVQ2_WritePlayerstateToClient (unsigned int pext, int seat, int extflags, q2client_frame_t *from, q2client_frame_t *to, sizebuf_t *msg)
|
||||
void SVQ2_WritePlayerstateToClient (client_t *client, int seat, int extflags, q2client_frame_t *from, q2client_frame_t *to, sizebuf_t *msg)
|
||||
{
|
||||
int i;
|
||||
int pflags;
|
||||
q2player_state_t *ps, *ops;
|
||||
q2player_state_t dummy;
|
||||
int statbits;
|
||||
unsigned int pext = client->fteprotocolextensions;
|
||||
unsigned int q2e = client->protocol == SCP_QUAKE2EX;
|
||||
|
||||
|
||||
ps = &to->ps[seat];
|
||||
if (!from)
|
||||
|
@ -421,7 +539,7 @@ void SVQ2_WritePlayerstateToClient (unsigned int pext, int seat, int extflags, q
|
|||
|
||||
if (pext & PEXT_SPLITSCREEN)
|
||||
if (!from || from->clientnum[seat] != to->clientnum[seat])
|
||||
pflags |= Q2PS_CLIENTNUM;
|
||||
pflags |= Q2FTEPS_CLIENTNUM;
|
||||
|
||||
if (ps->pmove.pm_type != ops->pmove.pm_type)
|
||||
pflags |= Q2PS_M_TYPE;
|
||||
|
@ -487,9 +605,9 @@ void SVQ2_WritePlayerstateToClient (unsigned int pext, int seat, int extflags, q
|
|||
if (pext & PEXT_MODELDBL)
|
||||
{
|
||||
if ((pflags & Q2PS_WEAPONINDEX) && ps->gunindex > 0xff)
|
||||
pflags |= Q2PS_INDEX16;
|
||||
pflags |= Q2FTEPS_INDEX16;
|
||||
if ((pflags & Q2PS_WEAPONFRAME) && ps->gunframe > 0xff)
|
||||
pflags |= Q2PS_INDEX16;
|
||||
pflags |= Q2FTEPS_INDEX16;
|
||||
}
|
||||
|
||||
if (pflags > 0xffff)
|
||||
|
@ -501,42 +619,101 @@ void SVQ2_WritePlayerstateToClient (unsigned int pext, int seat, int extflags, q
|
|||
MSG_WriteByte (msg, svcq2_playerinfo);
|
||||
MSG_WriteShort (msg, pflags&0xffff);
|
||||
if (pflags & Q2PS_EXTRABITS)
|
||||
MSG_WriteByte (msg, pflags>>16);
|
||||
{
|
||||
if (q2e)
|
||||
MSG_WriteShort (msg, pflags>>16);
|
||||
else
|
||||
MSG_WriteByte (msg, pflags>>16);
|
||||
}
|
||||
|
||||
//
|
||||
// write the pmove_state_t
|
||||
//
|
||||
if (pflags & Q2PS_M_TYPE)
|
||||
MSG_WriteByte (msg, ps->pmove.pm_type);
|
||||
|
||||
if (pflags & Q2PS_M_ORIGIN)
|
||||
{
|
||||
MSG_WriteShort (msg, ps->pmove.origin[0]);
|
||||
MSG_WriteShort (msg, ps->pmove.origin[1]);
|
||||
MSG_WriteShort (msg, ps->pmove.origin[2]);
|
||||
i = ps->pmove.pm_type;
|
||||
if (q2e)
|
||||
{ //sigh... q2e added some extra pmove types that we don't support, and not on the end. :(
|
||||
switch((q2pmtype_t)i)
|
||||
{
|
||||
case Q2PM_NORMAL: i = Q2EPM_NORMAL; break;
|
||||
//case Q2PM_GRAPPLE: i = Q2EPM_GRAPPLE; break;
|
||||
case Q2PM_SPECTATOR: i = Q2EPM_SPECTATOR; break;
|
||||
//case Q2PM_SPECTATOR2: i = Q2EPM_SPECTATOR2; break;
|
||||
case Q2PM_DEAD: i = Q2EPM_DEAD; break;
|
||||
case Q2PM_GIB: i = Q2EPM_GIB; break;
|
||||
case Q2PM_FREEZE: i = Q2EPM_FREEZE; break;
|
||||
}
|
||||
}
|
||||
MSG_WriteByte (msg, i);
|
||||
}
|
||||
|
||||
if (pflags & Q2PS_M_VELOCITY)
|
||||
if (q2e)
|
||||
{
|
||||
MSG_WriteShort (msg, ps->pmove.velocity[0]);
|
||||
MSG_WriteShort (msg, ps->pmove.velocity[1]);
|
||||
MSG_WriteShort (msg, ps->pmove.velocity[2]);
|
||||
if (pflags & Q2PS_M_ORIGIN)
|
||||
{
|
||||
MSG_WriteFloat (msg, ps->pmove.origin[0]/8.0);
|
||||
MSG_WriteFloat (msg, ps->pmove.origin[1]/8.0);
|
||||
MSG_WriteFloat (msg, ps->pmove.origin[2]/8.0);
|
||||
}
|
||||
|
||||
if (pflags & Q2PS_M_VELOCITY)
|
||||
{
|
||||
MSG_WriteFloat (msg, ps->pmove.velocity[0]/8.0);
|
||||
MSG_WriteFloat (msg, ps->pmove.velocity[1]/8.0);
|
||||
MSG_WriteFloat (msg, ps->pmove.velocity[2]/8.0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pflags & Q2PS_M_ORIGIN)
|
||||
{
|
||||
MSG_WriteShort (msg, ps->pmove.origin[0]);
|
||||
MSG_WriteShort (msg, ps->pmove.origin[1]);
|
||||
MSG_WriteShort (msg, ps->pmove.origin[2]);
|
||||
}
|
||||
|
||||
if (pflags & Q2PS_M_VELOCITY)
|
||||
{
|
||||
MSG_WriteShort (msg, ps->pmove.velocity[0]);
|
||||
MSG_WriteShort (msg, ps->pmove.velocity[1]);
|
||||
MSG_WriteShort (msg, ps->pmove.velocity[2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (pflags & Q2PS_M_TIME)
|
||||
MSG_WriteByte (msg, ps->pmove.pm_time);
|
||||
{
|
||||
if (q2e)
|
||||
MSG_WriteShort (msg, ps->pmove.pm_time);
|
||||
else
|
||||
MSG_WriteByte (msg, ps->pmove.pm_time);
|
||||
}
|
||||
|
||||
if (pflags & Q2PS_M_FLAGS)
|
||||
MSG_WriteByte (msg, ps->pmove.pm_flags);
|
||||
{
|
||||
if (q2e)
|
||||
MSG_WriteShort (msg, ps->pmove.pm_flags);
|
||||
else
|
||||
MSG_WriteByte (msg, ps->pmove.pm_flags);
|
||||
}
|
||||
|
||||
if (pflags & Q2PS_M_GRAVITY)
|
||||
MSG_WriteShort (msg, ps->pmove.gravity);
|
||||
|
||||
if (pflags & Q2PS_M_DELTA_ANGLES)
|
||||
{
|
||||
MSG_WriteShort (msg, ps->pmove.delta_angles[0]);
|
||||
MSG_WriteShort (msg, ps->pmove.delta_angles[1]);
|
||||
MSG_WriteShort (msg, ps->pmove.delta_angles[2]);
|
||||
if (q2e)
|
||||
{
|
||||
MSG_WriteFloat (msg, SHORT2ANGLE(ps->pmove.delta_angles[0]));
|
||||
MSG_WriteFloat (msg, SHORT2ANGLE(ps->pmove.delta_angles[1]));
|
||||
MSG_WriteFloat (msg, SHORT2ANGLE(ps->pmove.delta_angles[2]));
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteShort (msg, ps->pmove.delta_angles[0]);
|
||||
MSG_WriteShort (msg, ps->pmove.delta_angles[1]);
|
||||
MSG_WriteShort (msg, ps->pmove.delta_angles[2]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -544,46 +721,102 @@ void SVQ2_WritePlayerstateToClient (unsigned int pext, int seat, int extflags, q
|
|||
//
|
||||
if (pflags & Q2PS_VIEWOFFSET)
|
||||
{
|
||||
MSG_WriteChar (msg, ps->viewoffset[0]*4);
|
||||
MSG_WriteChar (msg, ps->viewoffset[1]*4);
|
||||
MSG_WriteChar (msg, ps->viewoffset[2]*4);
|
||||
if (q2e)
|
||||
{
|
||||
MSG_WriteShort (msg, ps->viewoffset[0]*16);
|
||||
MSG_WriteShort (msg, ps->viewoffset[1]*16);
|
||||
MSG_WriteShort (msg, (ps->viewoffset[2]-DEFAULT_VIEWHEIGHT)*16);
|
||||
MSG_WriteChar (msg, DEFAULT_VIEWHEIGHT/*ps->pmove.viewheight*/);
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteChar (msg, ps->viewoffset[0]*4);
|
||||
MSG_WriteChar (msg, ps->viewoffset[1]*4);
|
||||
MSG_WriteChar (msg, ps->viewoffset[2]*4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (pflags & Q2PS_VIEWANGLES)
|
||||
{
|
||||
MSG_WriteAngle16 (msg, ps->viewangles[0]);
|
||||
MSG_WriteAngle16 (msg, ps->viewangles[1]);
|
||||
MSG_WriteAngle16 (msg, ps->viewangles[2]);
|
||||
if (q2e)
|
||||
{
|
||||
MSG_WriteFloat (msg, ps->viewangles[0]);
|
||||
MSG_WriteFloat (msg, ps->viewangles[1]);
|
||||
MSG_WriteFloat (msg, ps->viewangles[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteAngle16 (msg, ps->viewangles[0]);
|
||||
MSG_WriteAngle16 (msg, ps->viewangles[1]);
|
||||
MSG_WriteAngle16 (msg, ps->viewangles[2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (pflags & Q2PS_KICKANGLES)
|
||||
{
|
||||
MSG_WriteChar (msg, ps->kick_angles[0]*4);
|
||||
MSG_WriteChar (msg, ps->kick_angles[1]*4);
|
||||
MSG_WriteChar (msg, ps->kick_angles[2]*4);
|
||||
if (q2e)
|
||||
{
|
||||
MSG_WriteShort (msg, ps->kick_angles[0]*1024);
|
||||
MSG_WriteShort (msg, ps->kick_angles[1]*1024);
|
||||
MSG_WriteShort (msg, ps->kick_angles[2]*1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteChar (msg, ps->kick_angles[0]*4);
|
||||
MSG_WriteChar (msg, ps->kick_angles[1]*4);
|
||||
MSG_WriteChar (msg, ps->kick_angles[2]*4);
|
||||
}
|
||||
}
|
||||
|
||||
if (pflags & Q2PS_WEAPONINDEX)
|
||||
{
|
||||
if (pflags & Q2PS_INDEX16)
|
||||
MSG_WriteShort(msg, ps->gunindex);
|
||||
if (q2e)
|
||||
MSG_WriteShort(msg, (0/*gunskin*/<<13) | ps->gunindex);
|
||||
else
|
||||
MSG_WriteByte (msg, ps->gunindex);
|
||||
{
|
||||
if (pflags & Q2FTEPS_INDEX16)
|
||||
MSG_WriteShort(msg, ps->gunindex);
|
||||
else
|
||||
MSG_WriteByte (msg, ps->gunindex);
|
||||
}
|
||||
}
|
||||
|
||||
if (pflags & Q2PS_WEAPONFRAME)
|
||||
{
|
||||
if (pflags & Q2PS_INDEX16)
|
||||
MSG_WriteShort (msg, ps->gunframe);
|
||||
if (q2e)
|
||||
{
|
||||
unsigned short fl = ps->gunframe&0x1ff;
|
||||
if (ps->gunoffset[0]) fl |= 1<<9;
|
||||
if (ps->gunoffset[1]) fl |= 1<<10;
|
||||
if (ps->gunoffset[2]) fl |= 1<<11;
|
||||
if (ps->gunangles[0]) fl |= 1<<12;
|
||||
if (ps->gunangles[1]) fl |= 1<<13;
|
||||
if (ps->gunangles[2]) fl |= 1<<14;
|
||||
//if (ps->gunrate[2]) fl |= 1<<15;
|
||||
|
||||
MSG_WriteShort (msg, fl);
|
||||
if (fl & (1<<9)) MSG_WriteFloat(msg, ps->gunoffset[0]);
|
||||
if (fl & (1<<10)) MSG_WriteFloat(msg, ps->gunoffset[1]);
|
||||
if (fl & (1<<11)) MSG_WriteFloat(msg, ps->gunoffset[2]);
|
||||
if (fl & (1<<12)) MSG_WriteFloat(msg, ps->gunangles[0]);
|
||||
if (fl & (1<<13)) MSG_WriteFloat(msg, ps->gunangles[1]);
|
||||
if (fl & (1<<14)) MSG_WriteFloat(msg, ps->gunangles[2]);
|
||||
//if (fl & (1<<15)) MSG_WriteByte(msg, ps->gunrate);
|
||||
}
|
||||
else
|
||||
MSG_WriteByte (msg, ps->gunframe);
|
||||
MSG_WriteChar (msg, ps->gunoffset[0]*4);
|
||||
MSG_WriteChar (msg, ps->gunoffset[1]*4);
|
||||
MSG_WriteChar (msg, ps->gunoffset[2]*4);
|
||||
MSG_WriteChar (msg, ps->gunangles[0]*4);
|
||||
MSG_WriteChar (msg, ps->gunangles[1]*4);
|
||||
MSG_WriteChar (msg, ps->gunangles[2]*4);
|
||||
{
|
||||
if (pflags & Q2FTEPS_INDEX16)
|
||||
MSG_WriteShort (msg, ps->gunframe);
|
||||
else
|
||||
MSG_WriteByte (msg, ps->gunframe);
|
||||
MSG_WriteChar (msg, ps->gunoffset[0]*4);
|
||||
MSG_WriteChar (msg, ps->gunoffset[1]*4);
|
||||
MSG_WriteChar (msg, ps->gunoffset[2]*4);
|
||||
MSG_WriteChar (msg, ps->gunangles[0]*4);
|
||||
MSG_WriteChar (msg, ps->gunangles[1]*4);
|
||||
MSG_WriteChar (msg, ps->gunangles[2]*4);
|
||||
}
|
||||
}
|
||||
|
||||
if (pflags & Q2PS_BLEND)
|
||||
|
@ -601,16 +834,40 @@ void SVQ2_WritePlayerstateToClient (unsigned int pext, int seat, int extflags, q
|
|||
|
||||
// send stats
|
||||
statbits = 0;
|
||||
for (i=0 ; i<Q2MAX_STATS ; i++)
|
||||
for (i=0 ; i<min(32,Q2MAX_STATS); i++)
|
||||
if (ps->stats[i] != ops->stats[i])
|
||||
statbits |= 1<<i;
|
||||
MSG_WriteLong (msg, statbits);
|
||||
for (i=0 ; i<Q2MAX_STATS ; i++)
|
||||
for (i=0 ; i<min(32,Q2MAX_STATS) ; i++)
|
||||
if (statbits & (1<<i) )
|
||||
MSG_WriteShort (msg, ps->stats[i]);
|
||||
|
||||
if ((extflags & Q2PSX_CLIENTNUM) || (pflags & Q2PS_CLIENTNUM))
|
||||
MSG_WriteByte(msg, to->clientnum[seat]);
|
||||
if (q2e)
|
||||
{
|
||||
statbits = 0;
|
||||
for (i=0 ; i<Q2MAX_STATS-32 ; i++)
|
||||
if (ps->stats[32+i] != ops->stats[32+i])
|
||||
statbits |= 1<<i;
|
||||
MSG_WriteLong (msg, statbits);
|
||||
for (i=0 ; i<Q2MAX_STATS-32 ; i++)
|
||||
if (statbits & (1<<i) )
|
||||
MSG_WriteShort (msg, ps->stats[32+i]);
|
||||
|
||||
if (pflags & Q2EXPS_DAMAGEBLEND)
|
||||
{
|
||||
MSG_WriteByte(msg, 0*255);
|
||||
MSG_WriteByte(msg, 0*255);
|
||||
MSG_WriteByte(msg, 0*255);
|
||||
MSG_WriteByte(msg, 0*255);
|
||||
}
|
||||
if (pflags & Q2EXPS_TEAMID)
|
||||
MSG_WriteByte(msg, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((extflags & Q2PSX_CLIENTNUM) || (pflags & Q2FTEPS_CLIENTNUM))
|
||||
MSG_WriteByte(msg, to->clientnum[seat]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -655,16 +912,31 @@ void SVQ2_WriteFrameToClient (client_t *client, sizebuf_t *msg)
|
|||
extflags |= Q2PSX_OLD;
|
||||
client->chokecount = 0;
|
||||
|
||||
// send over the areabits
|
||||
MSG_WriteByte (msg, frame->areabytes);
|
||||
SZ_Write (msg, frame->areabits, frame->areabytes);
|
||||
if (client->protocol == SCP_QUAKE2EX)
|
||||
{
|
||||
for (split = client, seat = 0; split; split = split->controlled, seat++)
|
||||
{
|
||||
// send over the areabits, private per-seat
|
||||
MSG_WriteByte (msg, frame->areabytes);
|
||||
SZ_Write (msg, frame->areabits, frame->areabytes);
|
||||
|
||||
// delta encode the playerstate
|
||||
for (split = client, seat = 0; split; split = split->controlled, seat++)
|
||||
SVQ2_WritePlayerstateToClient (client->fteprotocolextensions, seat, extflags, oldframe, frame, msg);
|
||||
// delta encode the playerstate
|
||||
SVQ2_WritePlayerstateToClient (client, seat, extflags, oldframe, frame, msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// send over the areabits, shared between all seats
|
||||
MSG_WriteByte (msg, frame->areabytes);
|
||||
SZ_Write (msg, frame->areabits, frame->areabytes);
|
||||
|
||||
// delta encode the playerstate
|
||||
for (split = client, seat = 0; split; split = split->controlled, seat++)
|
||||
SVQ2_WritePlayerstateToClient (client, seat, extflags, oldframe, frame, msg);
|
||||
}
|
||||
|
||||
// delta encode the entities
|
||||
SVQ2_EmitPacketEntities (oldframe, frame, msg);
|
||||
SVQ2_EmitPacketEntities (oldframe, frame, msg, client->protocol==SCP_QUAKE2EX);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ int svq2_maxclients;
|
|||
dllhandle_t *q2gamedll;
|
||||
void SVQ2_UnloadGame (void)
|
||||
{
|
||||
ge = NULL;
|
||||
if (q2gamedll)
|
||||
Sys_CloseLibrary(q2gamedll);
|
||||
q2gamedll = NULL;
|
||||
|
@ -138,6 +139,7 @@ Sends the contents of the mutlicast buffer to a single client
|
|||
static void VARGS PFQ2_Unicast (q2edict_t *ent, qboolean reliable)
|
||||
{
|
||||
int p;
|
||||
int ctype;
|
||||
client_t *client;
|
||||
|
||||
if (!ent)
|
||||
|
@ -151,6 +153,7 @@ static void VARGS PFQ2_Unicast (q2edict_t *ent, qboolean reliable)
|
|||
|
||||
if (client->state < cs_connected)
|
||||
return;
|
||||
ctype = client->netchan.message.prim.coordtype==COORDTYPE_FLOAT_32;
|
||||
|
||||
if (client->controller)
|
||||
{
|
||||
|
@ -162,20 +165,30 @@ static void VARGS PFQ2_Unicast (q2edict_t *ent, qboolean reliable)
|
|||
}
|
||||
client = client->controller;
|
||||
|
||||
//svcq2_playerinfo is not normally valid except within the svc_frame message.
|
||||
//this means its 'free' to repurpose for things like splitscreen. woot.
|
||||
MSG_WriteShort(&sv.q2multicast, 0);
|
||||
memmove(sv.q2multicast.data+2, sv.q2multicast.data, sv.q2multicast.cursize-2);
|
||||
sv.q2multicast.data[0] = svcq2_playerinfo;
|
||||
sv.q2multicast.data[1] = p;
|
||||
MSG_WriteShort(&sv.q2multicast[ctype], 0);
|
||||
memmove(sv.q2multicast[ctype].data+2, sv.q2multicast[ctype].data, sv.q2multicast[ctype].cursize-2);
|
||||
if (client->protocol == SCP_QUAKE2EX)
|
||||
{
|
||||
//has a dedicated svc. seats are 1-based.
|
||||
sv.q2multicast[ctype].data[0] = svcq2ex_splitclient;
|
||||
sv.q2multicast[ctype].data[1] = p+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//svcq2_playerinfo is not normally valid except within the svc_frame message.
|
||||
//this means its 'free' to repurpose for things like splitscreen. woot.
|
||||
sv.q2multicast[ctype].data[0] = svcq2_playerinfo;
|
||||
sv.q2multicast[ctype].data[1] = p;
|
||||
}
|
||||
}
|
||||
|
||||
if (reliable)
|
||||
SZ_Write (&client->netchan.message, sv.q2multicast.data, sv.q2multicast.cursize);
|
||||
SZ_Write (&client->netchan.message, sv.q2multicast[ctype].data, sv.q2multicast[ctype].cursize);
|
||||
else
|
||||
SZ_Write (&client->datagram, sv.q2multicast.data, sv.q2multicast.cursize);
|
||||
SZ_Write (&client->datagram, sv.q2multicast[ctype].data, sv.q2multicast[ctype].cursize);
|
||||
|
||||
SZ_Clear (&sv.q2multicast);
|
||||
SZ_Clear (&sv.q2multicast[0]);
|
||||
SZ_Clear (&sv.q2multicast[1]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -263,8 +276,10 @@ static void VARGS PFQ2_centerprintf (q2edict_t *ent, const char *fmt, ...)
|
|||
vsprintf (msg, fmt, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
MSG_WriteByte (&sv.q2multicast,svcq2_centerprint);
|
||||
MSG_WriteString (&sv.q2multicast,msg);
|
||||
MSG_WriteByte (&sv.q2multicast[0],svcq2_centerprint);
|
||||
MSG_WriteString (&sv.q2multicast[0],msg);
|
||||
MSG_WriteByte (&sv.q2multicast[1],svcq2_centerprint);
|
||||
MSG_WriteString (&sv.q2multicast[1],msg);
|
||||
PFQ2_Unicast (ent, true);
|
||||
}
|
||||
|
||||
|
@ -288,6 +303,8 @@ static void VARGS PFQ2_error (const char *fmt, ...)
|
|||
SV_Error("Game Error: %s", msg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
PF_Configstring
|
||||
|
@ -296,11 +313,40 @@ PF_Configstring
|
|||
*/
|
||||
void VARGS PFQ2_Configstring (int i, const char *val)
|
||||
{
|
||||
int msgsize;
|
||||
int j;
|
||||
int q2exremap;
|
||||
client_t *cl;
|
||||
if (i < 0 || i >= Q2MAX_CONFIGSTRINGS)
|
||||
Sys_Error ("configstring: bad index %i\n", i);
|
||||
Host_EndGame ("configstring: bad index %i\n", i);
|
||||
|
||||
if (!val)
|
||||
val = "";
|
||||
msgsize = 3+ strlen(val)+1;
|
||||
|
||||
{ //remap from vanilla to q2e
|
||||
#define PASTE(a,b) (a##b)
|
||||
#define REMAPR(n,l) if (i >= Q2CS_##n && i < Q2CS_##n+Q2MAX_##l) q2exremap = i-Q2CS_##n+Q2EXCS_##n; else
|
||||
#define REMAPS(n) if (i == PASTE(Q2CS_,n)) q2exremap = i-PASTE(Q2CS_,n)+PASTE(Q2EXCS_,n); else
|
||||
#define Q2MAX_STATUSBAR (Q2CS_AIRACCEL-Q2CS_STATUSBAR)
|
||||
REMAPS(NAME)
|
||||
REMAPS(CDTRACK)
|
||||
REMAPS(SKY)
|
||||
REMAPS(SKYAXIS)
|
||||
REMAPS(SKYROTATE)
|
||||
REMAPR(STATUSBAR, STATUSBAR)
|
||||
REMAPS(AIRACCEL)
|
||||
REMAPS(MAXCLIENTS)
|
||||
REMAPS(MAPCHECKSUM)
|
||||
REMAPR(MODELS, MODELS)
|
||||
REMAPR(SOUNDS, SOUNDS)
|
||||
REMAPR(IMAGES, IMAGES)
|
||||
REMAPR(LIGHTS, LIGHTSTYLES)
|
||||
REMAPR(ITEMS, ITEMS)
|
||||
REMAPR(PLAYERSKINS, CLIENTS)
|
||||
REMAPR(GENERAL, GENERAL)
|
||||
Host_EndGame ("configstring %i > Q2MAX_CONFIGSTRINGS", i);
|
||||
}
|
||||
|
||||
Z_Free((char*)sv.strings.configstring[i]);
|
||||
sv.strings.configstring[i] = Z_StrDup(val);
|
||||
|
@ -310,12 +356,25 @@ void VARGS PFQ2_Configstring (int i, const char *val)
|
|||
|
||||
if (sv.state != ss_loading)
|
||||
{ // send the update to everyone
|
||||
SZ_Clear (&sv.q2multicast);
|
||||
MSG_WriteChar (&sv.q2multicast, svcq2_configstring);
|
||||
MSG_WriteShort (&sv.q2multicast, i);
|
||||
MSG_WriteString (&sv.q2multicast, val);
|
||||
|
||||
SV_Multicast (vec3_origin, MULTICAST_ALL_R);
|
||||
for (j = 0, cl = svs.clients; j < sv.allocated_client_slots; j++, cl++)
|
||||
{
|
||||
if (cl->state != cs_spawned)
|
||||
continue;
|
||||
if (cl->controller)
|
||||
continue;
|
||||
if (cl->protocol == SCP_QUAKE2)
|
||||
{
|
||||
ClientReliableWrite_Begin(cl, svcq2_configstring, msgsize);
|
||||
ClientReliableWrite_Short(cl, i);
|
||||
ClientReliableWrite_String(cl, val);
|
||||
}
|
||||
else if (cl->protocol == SCP_QUAKE2EX)
|
||||
{
|
||||
ClientReliableWrite_Begin(cl, svcq2_configstring, msgsize);
|
||||
ClientReliableWrite_Short(cl, q2exremap);
|
||||
ClientReliableWrite_String(cl, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,6 +400,7 @@ static int SVQ2_FindIndex (const char *name, int start, int max, int overflowtyp
|
|||
if (overflowtype)
|
||||
{
|
||||
const char **overflowstrings;
|
||||
int startq2e;
|
||||
switch(overflowtype)
|
||||
{
|
||||
case 1:
|
||||
|
@ -348,15 +408,18 @@ static int SVQ2_FindIndex (const char *name, int start, int max, int overflowtyp
|
|||
max = countof(sv.strings.q2_extramodels);
|
||||
i++; //do not allow 255 to be allocated, ever. just live with the gap (255 means special things).
|
||||
start = 0x8000;
|
||||
startq2e = Q2EXCS_MODELS;
|
||||
break;
|
||||
case 2:
|
||||
overflowstrings = sv.strings.q2_extrasounds;
|
||||
max = countof(sv.strings.q2_extrasounds);
|
||||
start = 0x8000|0x4000;
|
||||
startq2e = Q2EXCS_SOUNDS;
|
||||
break;
|
||||
default:
|
||||
overflowstrings = NULL; //ssh
|
||||
max = i;
|
||||
startq2e=0;//just to kill warnings
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -368,10 +431,14 @@ static int SVQ2_FindIndex (const char *name, int start, int max, int overflowtyp
|
|||
overflowstrings[i] = Z_StrDup(name);
|
||||
if (sv.state != ss_loading)
|
||||
{
|
||||
SZ_Clear (&sv.q2multicast);
|
||||
MSG_WriteChar (&sv.q2multicast, svcq2_configstring);
|
||||
MSG_WriteShort (&sv.q2multicast, start+i);
|
||||
MSG_WriteString (&sv.q2multicast, name);
|
||||
SZ_Clear (&sv.q2multicast[0]);
|
||||
MSG_WriteChar (&sv.q2multicast[0], svcq2_configstring);
|
||||
MSG_WriteShort (&sv.q2multicast[0], start+i);
|
||||
MSG_WriteString (&sv.q2multicast[0], name);
|
||||
SZ_Clear (&sv.q2multicast[1]);
|
||||
MSG_WriteChar (&sv.q2multicast[1], svcq2_configstring);
|
||||
MSG_WriteShort (&sv.q2multicast[1], startq2e+i);
|
||||
MSG_WriteString (&sv.q2multicast[1], name);
|
||||
SV_Multicast (vec3_origin, MULTICAST_ALL_R);
|
||||
}
|
||||
return i;
|
||||
|
@ -380,7 +447,7 @@ static int SVQ2_FindIndex (const char *name, int start, int max, int overflowtyp
|
|||
return i;
|
||||
}
|
||||
}
|
||||
Sys_Error ("*Index: overflow");
|
||||
Host_EndGame ("*Index: overflow");
|
||||
}
|
||||
|
||||
PFQ2_Configstring(start + i, name);
|
||||
|
@ -453,18 +520,21 @@ static qboolean CMQ2_Q1BSP_SetAreaPortalState (int portalnum, qboolean open)
|
|||
return true;
|
||||
}*/
|
||||
|
||||
static void VARGS PFQ2_WriteChar (int c) {MSG_WriteChar (&sv.q2multicast, c & 0xff);}
|
||||
static void VARGS PFQ2_WriteByte (int c) {MSG_WriteByte (&sv.q2multicast, c & 0xff);}
|
||||
static void VARGS PFQ2_WriteShort (int c) {MSG_WriteShort (&sv.q2multicast, c & 0xffff);}
|
||||
static void VARGS PFQ2_WriteLong (int c) {MSG_WriteLong (&sv.q2multicast, c);}
|
||||
static void VARGS PFQ2_WriteFloat (float f) {MSG_WriteFloat (&sv.q2multicast, f);}
|
||||
static void VARGS PFQ2_WriteString (const char *s) {MSG_WriteString (&sv.q2multicast, s);}
|
||||
static void VARGS PFQ2_WriteAngle (float f) {MSG_WriteAngle (&sv.q2multicast, f);}
|
||||
static void VARGS PFQ2_WritePos (vec3_t pos) { MSG_WriteCoord (&sv.q2multicast, pos[0]);
|
||||
MSG_WriteCoord (&sv.q2multicast, pos[1]);
|
||||
MSG_WriteCoord (&sv.q2multicast, pos[2]);
|
||||
}
|
||||
static void VARGS PFQ2_WriteDir (vec3_t dir) {MSG_WriteDir (&sv.q2multicast, dir);}
|
||||
static void VARGS PFQ2_WriteChar (int c) {c&=0xff;MSG_WriteChar (&sv.q2multicast[0], c);MSG_WriteChar (&sv.q2multicast[1], c);}
|
||||
static void VARGS PFQ2_WriteByte (int c) {c&=0xff;MSG_WriteByte (&sv.q2multicast[0], c);MSG_WriteByte (&sv.q2multicast[1], c);}
|
||||
static void VARGS PFQ2_WriteShort (int c) {c&=0xffff;MSG_WriteShort (&sv.q2multicast[0], c);MSG_WriteShort (&sv.q2multicast[1], c);}
|
||||
static void VARGS PFQ2_WriteLong (int c) {MSG_WriteLong (&sv.q2multicast[0], c);MSG_WriteLong (&sv.q2multicast[1], c);}
|
||||
static void VARGS PFQ2_WriteFloat (float f) {MSG_WriteFloat (&sv.q2multicast[0], f);MSG_WriteFloat (&sv.q2multicast[1], f);}
|
||||
static void VARGS PFQ2_WriteString (const char *s) {MSG_WriteString (&sv.q2multicast[0], s);MSG_WriteString (&sv.q2multicast[1], s);}
|
||||
static void VARGS PFQ2_WriteAngle (float f) {MSG_WriteAngle (&sv.q2multicast[0], f);MSG_WriteAngle (&sv.q2multicast[1], f);}
|
||||
static void VARGS PFQ2_WritePos (vec3_t pos) { MSG_WriteCoord (&sv.q2multicast[0], pos[0]);
|
||||
MSG_WriteCoord (&sv.q2multicast[0], pos[1]);
|
||||
MSG_WriteCoord (&sv.q2multicast[0], pos[2]);
|
||||
MSG_WriteCoord (&sv.q2multicast[1], pos[0]);
|
||||
MSG_WriteCoord (&sv.q2multicast[1], pos[1]);
|
||||
MSG_WriteCoord (&sv.q2multicast[1], pos[2]);
|
||||
}
|
||||
static void VARGS PFQ2_WriteDir (vec3_t dir) {MSG_WriteDir (&sv.q2multicast[0], dir);MSG_WriteDir (&sv.q2multicast[1], dir);}
|
||||
|
||||
/*
|
||||
=================
|
||||
|
@ -546,6 +616,7 @@ static void VARGS SVQ2_StartSound (vec3_t origin, q2edict_t *entity, int channel
|
|||
vec3_t origin_v;
|
||||
qboolean use_phs;
|
||||
unsigned int needext = 0;
|
||||
qboolean q2e;
|
||||
|
||||
if (volume < 0 || volume > 1.0)
|
||||
Sys_Error ("SV_StartSound: volume = %f", volume);
|
||||
|
@ -575,7 +646,7 @@ static void VARGS SVQ2_StartSound (vec3_t origin, q2edict_t *entity, int channel
|
|||
flags |= Q2SND_ATTENUATION;
|
||||
if (soundindex > 0xff)
|
||||
{
|
||||
flags |= Q2SND_LARGEIDX;
|
||||
flags |= Q2SNDFTE_LARGEIDX;
|
||||
needext |= PEXT_SOUNDDBL;
|
||||
}
|
||||
|
||||
|
@ -605,49 +676,50 @@ static void VARGS SVQ2_StartSound (vec3_t origin, q2edict_t *entity, int channel
|
|||
{
|
||||
VectorCopy (entity->s.origin, origin_v);
|
||||
}
|
||||
}
|
||||
|
||||
for(q2e=0; ; q2e++)
|
||||
{
|
||||
MSG_WriteByte (&sv.q2multicast[q2e], svcq2_sound);
|
||||
MSG_WriteByte (&sv.q2multicast[q2e], flags);
|
||||
if (q2e || (flags & Q2SNDFTE_LARGEIDX))
|
||||
MSG_WriteShort (&sv.q2multicast[q2e], soundindex);
|
||||
else
|
||||
MSG_WriteByte (&sv.q2multicast[q2e], soundindex);
|
||||
|
||||
if (flags & Q2SND_VOLUME)
|
||||
MSG_WriteByte (&sv.q2multicast[q2e], volume*255);
|
||||
if (flags & Q2SND_ATTENUATION)
|
||||
MSG_WriteByte (&sv.q2multicast[q2e], attenuation*64);
|
||||
if (flags & Q2SND_OFFSET)
|
||||
MSG_WriteByte (&sv.q2multicast[q2e], timeofs*1000);
|
||||
|
||||
if (flags & Q2SND_ENT)
|
||||
{
|
||||
if (q2e && (flags & Q2SNDEX_LARGEENT))
|
||||
MSG_WriteLong (&sv.q2multicast[q2e], sendchan);
|
||||
else
|
||||
MSG_WriteShort (&sv.q2multicast[q2e], sendchan);
|
||||
}
|
||||
|
||||
if (flags & Q2SND_POS)
|
||||
{
|
||||
for (i=0 ; i<3 ; i++)
|
||||
if (-32768/8.0 > origin_v[i] || origin_v[i] > 32767/8.0)
|
||||
{
|
||||
flags |= Q2SND_LARGEPOS;
|
||||
needext |= PEXT_FLOATCOORDS;
|
||||
break;
|
||||
}
|
||||
MSG_WriteCoord (&sv.q2multicast[q2e], origin[0]);
|
||||
MSG_WriteCoord (&sv.q2multicast[q2e], origin[1]);
|
||||
MSG_WriteCoord (&sv.q2multicast[q2e], origin[2]);
|
||||
}
|
||||
}
|
||||
|
||||
MSG_WriteByte (&sv.q2multicast, svcq2_sound);
|
||||
MSG_WriteByte (&sv.q2multicast, flags);
|
||||
if (flags & Q2SND_LARGEIDX)
|
||||
MSG_WriteShort (&sv.q2multicast, soundindex);
|
||||
else
|
||||
MSG_WriteByte (&sv.q2multicast, soundindex);
|
||||
|
||||
if (flags & Q2SND_VOLUME)
|
||||
MSG_WriteByte (&sv.q2multicast, volume*255);
|
||||
if (flags & Q2SND_ATTENUATION)
|
||||
MSG_WriteByte (&sv.q2multicast, attenuation*64);
|
||||
if (flags & Q2SND_OFFSET)
|
||||
MSG_WriteByte (&sv.q2multicast, timeofs*1000);
|
||||
|
||||
if (flags & Q2SND_ENT)
|
||||
MSG_WriteShort (&sv.q2multicast, sendchan);
|
||||
|
||||
if (flags & Q2SND_POS)
|
||||
{
|
||||
if (flags & Q2SND_LARGEPOS)
|
||||
{
|
||||
MSG_WriteFloat (&sv.q2multicast, origin[0]);
|
||||
MSG_WriteFloat (&sv.q2multicast, origin[1]);
|
||||
MSG_WriteFloat (&sv.q2multicast, origin[2]);
|
||||
}
|
||||
if (q2e)
|
||||
break;
|
||||
else
|
||||
{
|
||||
MSG_WriteCoord (&sv.q2multicast, origin[0]);
|
||||
MSG_WriteCoord (&sv.q2multicast, origin[1]);
|
||||
MSG_WriteCoord (&sv.q2multicast, origin[2]);
|
||||
flags &= ~(Q2SNDFTE_LARGEIDX|Q2SNDEX_LARGEENT);
|
||||
if (origin)
|
||||
flags |= Q2SNDEX_EXPLICITPOS;
|
||||
flags |= Q2SND_POS; //always sends a pos to avoid issues when the ent is not in the client's phs
|
||||
|
||||
if (sendchan > 0xffff)
|
||||
flags |= Q2SNDEX_LARGEENT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -895,7 +967,8 @@ qboolean SVQ2_InitGameProgs(void)
|
|||
return false;
|
||||
if (ge->apiversion != Q2GAME_API_VERSION)
|
||||
{
|
||||
Con_Printf("game is version %i, not %i", ge->apiversion, Q2GAME_API_VERSION);
|
||||
Con_Printf(CON_ERROR "game is version %i, not %i\n", ge->apiversion, Q2GAME_API_VERSION);
|
||||
ge = NULL;
|
||||
SVQ2_UnloadGame ();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -746,29 +746,6 @@ void VARGS WorldQ2_LinkEdict(world_t *w, q2edict_t *ent)
|
|||
if (ent->solid == Q2SOLID_BBOX && !(ent->svflags & SVF_DEADMONSTER))
|
||||
{ // assume that x/y are equal and symetric
|
||||
ent->s.solid = COM_EncodeSize(ent->mins, ent->maxs);
|
||||
/*
|
||||
i = ent->maxs[0]/8;
|
||||
if (i<1)
|
||||
i = 1;
|
||||
if (i>31)
|
||||
i = 31;
|
||||
|
||||
// z is not symetric
|
||||
j = (-ent->mins[2])/8;
|
||||
if (j<1)
|
||||
j = 1;
|
||||
if (j>31)
|
||||
j = 31;
|
||||
|
||||
// and z maxs can be negative...
|
||||
k = (ent->maxs[2]+32)/8;
|
||||
if (k<1)
|
||||
k = 1;
|
||||
if (k>63)
|
||||
k = 63;
|
||||
|
||||
//fixme: 32bit?
|
||||
ent->s.solid = (k<<10) | (j<<5) | i;*/
|
||||
}
|
||||
else if (ent->solid == Q2SOLID_BSP)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue