qccgui: reworked compile prints to split the screen instead of being some other window that's hidden when fullscreened etc.

splitscreen: split spectator setting into a per-seat setting. scoreboards are now also per-seat.
added parm_string global for richer map change stuff.
dpp7: fixed and reinstated.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5110 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2017-05-28 15:42:32 +00:00
parent 0fad8fe37d
commit 025aeff8a4
50 changed files with 1150 additions and 813 deletions

View File

@ -520,7 +520,7 @@ static float vlen(vec3_t v)
// returns true if weapon model should be drawn in camera mode // returns true if weapon model should be drawn in camera mode
qboolean Cam_DrawViewModel(playerview_t *pv) qboolean Cam_DrawViewModel(playerview_t *pv)
{ {
if (cl.spectator) if (pv->spectator)
{ {
if (pv->cam_state == CAM_EYECAM && cl_chasecam.ival) if (pv->cam_state == CAM_EYECAM && cl_chasecam.ival)
return true; return true;
@ -536,7 +536,7 @@ qboolean Cam_DrawViewModel(playerview_t *pv)
int Cam_TrackNum(playerview_t *pv) int Cam_TrackNum(playerview_t *pv)
{ {
if (cl.spectator && pv->cam_state == CAM_EYECAM) if (pv->spectator && pv->cam_state == CAM_EYECAM)
return pv->cam_spec_track; return pv->cam_spec_track;
return -1; return -1;
} }
@ -822,7 +822,7 @@ void Cam_Track(playerview_t *pv, usercmd_t *cmd)
vec3_t vec; vec3_t vec;
float len; float len;
if (!cl.spectator || !cl.worldmodel) //can happen when the server changes level if (!pv->spectator || !cl.worldmodel) //can happen when the server changes level
return; return;
if (autotrackmode != TM_USER && pv->cam_state == CAM_FREECAM) if (autotrackmode != TM_USER && pv->cam_state == CAM_FREECAM)
@ -976,7 +976,7 @@ void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd)
if (cls.state != ca_active) if (cls.state != ca_active)
return; return;
if (!cl.spectator && (cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV)) // only in spectator mode if (!pv->spectator && (cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV)) // only in spectator mode
return; return;
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
@ -1197,7 +1197,7 @@ void Cam_TrackPlayer(int seat, char *cmdname, char *plrarg)
return; return;
} }
if (!cl.spectator) if (!pv->spectator)
{ {
Con_Printf("Not spectating.\n"); Con_Printf("Not spectating.\n");
return; return;

View File

@ -1159,7 +1159,7 @@ static void CLQW_RecordServerData(sizebuf_t *buf)
if (cls.fteprotocolextensions2 & PEXT2_MAXPLAYERS) if (cls.fteprotocolextensions2 & PEXT2_MAXPLAYERS)
{ {
MSG_WriteByte (buf, cl.allocated_client_slots); MSG_WriteByte (buf, cl.allocated_client_slots);
MSG_WriteByte (buf, cl.splitclients | (cl.spectator?128:0)); MSG_WriteByte (buf, cl.splitclients);
for (i = 0; i < cl.splitclients; i++) for (i = 0; i < cl.splitclients; i++)
MSG_WriteByte (buf, cl.playerview[i].playernum); MSG_WriteByte (buf, cl.playerview[i].playernum);
} }
@ -1167,7 +1167,7 @@ static void CLQW_RecordServerData(sizebuf_t *buf)
{ {
for (i = 0; i < cl.splitclients; i++) for (i = 0; i < cl.splitclients; i++)
{ {
if (cl.spectator) if (cl.playerview[i].spectator)
MSG_WriteByte (buf, cl.playerview[i].playernum | 128); MSG_WriteByte (buf, cl.playerview[i].playernum | 128);
else else
MSG_WriteByte (buf, cl.playerview[i].playernum); MSG_WriteByte (buf, cl.playerview[i].playernum);
@ -1544,7 +1544,7 @@ void CL_Record_f (void)
} }
else else
{ //automagically generate a name { //automagically generate a name
if (cl.spectator) if (cl.playerview[0].spectator)
{ // FIXME: if tracking a player, use his name { // FIXME: if tracking a player, use his name
fname = va ("spec_%s_%s", fname = va ("spec_%s_%s",
TP_PlayerName(), TP_PlayerName(),

View File

@ -1658,7 +1658,8 @@ void CLDP_ParseDarkPlaces5Entities(void) //the things I do.. :o(
} }
else else
{ {
// Con_Printf("Update %i\n", read); if (cl_shownet.ival > 3)
Con_Printf("Update %i\n", read);
DP5_ParseDelta(to, newpack); DP5_ParseDelta(to, newpack);
to->sequence = cls.netchan.incoming_sequence; to->sequence = cls.netchan.incoming_sequence;
to->inactiveflag = 0; to->inactiveflag = 0;
@ -3780,6 +3781,7 @@ void CL_LinkPacketEntities (void)
le = &cl.lerpents[timer->entnum]; le = &cl.lerpents[timer->entnum];
if (le->sequence != cl.lerpentssequence) if (le->sequence != cl.lerpentssequence)
continue; continue;
// VectorCopy(le->origin, timer->origin);
} }
R_AddItemTimer(timer->origin, cl.time*90 + timer->origin[0] + timer->origin[1] + timer->origin[2], timer->radius, (cl.time - timer->start) / timer->duration, timer->rgb); R_AddItemTimer(timer->origin, cl.time*90 + timer->origin[0] + timer->origin[1] + timer->origin[2], timer->radius, (cl.time - timer->start) / timer->duration, timer->rgb);
} }
@ -4716,7 +4718,7 @@ guess_pm_type:
for (i = 0; i < cl.splitclients; i++) for (i = 0; i < cl.splitclients; i++)
{ {
playerview_t *pv = &cl.playerview[i]; playerview_t *pv = &cl.playerview[i];
if ((cl.spectator?pv->cam_spec_track:pv->playernum) == num) if ((pv->spectator?pv->cam_spec_track:pv->playernum) == num)
{ {
pv->stats[STAT_WEAPONFRAME] = state->weaponframe; pv->stats[STAT_WEAPONFRAME] = state->weaponframe;
pv->statsf[STAT_WEAPONFRAME] = state->weaponframe; pv->statsf[STAT_WEAPONFRAME] = state->weaponframe;
@ -5290,7 +5292,7 @@ void CL_LinkViewModel(void)
ent.flags |= RF_WEAPONMODEL|RF_DEPTHHACK|RF_NOSHADOW; ent.flags |= RF_WEAPONMODEL|RF_DEPTHHACK|RF_NOSHADOW;
plnum = -1; plnum = -1;
if (cl.spectator) if (pv->spectator)
plnum = Cam_TrackNum(pv); plnum = Cam_TrackNum(pv);
if (plnum == -1) if (plnum == -1)
plnum = r_refdef.playerview->playernum; plnum = r_refdef.playerview->playernum;
@ -5520,13 +5522,6 @@ void CL_SetUpPlayerPrediction(qboolean dopred)
CL_PredictUsercmd (0, j+1, state, &exact, &state->command); CL_PredictUsercmd (0, j+1, state, &exact, &state->command);
VectorCopy (exact.origin, pplayer->origin); VectorCopy (exact.origin, pplayer->origin);
} }
if (cl.spectator)
{
// if (!Cam_DrawPlayer(0, j))
// VectorCopy(pplayer->origin, cl.simorg[0]);
}
} }
} }
} }

View File

@ -120,6 +120,7 @@ static void Display_Ignorelist(void)
int i; int i;
int x; int x;
qboolean foundone; qboolean foundone;
playerview_t *pv = &cl.playerview[0];
x = 0; x = 0;
foundone = false; foundone = false;
@ -172,7 +173,7 @@ static void Display_Ignorelist(void)
if (ignore_opponents.ival) if (ignore_opponents.ival)
Con_Printf("\x02" "Opponents are Ignored\n"); Con_Printf("\x02" "Opponents are Ignored\n");
if (ignore_spec.ival == 2 || (ignore_spec.ival == 1 && !cl.spectator)) if (ignore_spec.ival == 2 || (ignore_spec.ival == 1 && !pv->spectator))
Con_Printf ("\x02" "Spectators are Ignored\n"); Con_Printf ("\x02" "Spectators are Ignored\n");
if (ignore_qizmo_spec.ival) if (ignore_qizmo_spec.ival)
@ -573,7 +574,8 @@ void Ignore_Flood_Add(player_info_t *sender, const char *s)
qboolean Ignore_Message(const char *sendername, const char *s, int flags) qboolean Ignore_Message(const char *sendername, const char *s, int flags)
{ {
int slot, i; int slot, i;
playerview_t *pv = &cl.playerview[0];
if (!ignore_mode.ival && (flags & 2)) if (!ignore_mode.ival && (flags & 2))
return false; return false;
@ -581,7 +583,7 @@ qboolean Ignore_Message(const char *sendername, const char *s, int flags)
if (ignore_spec.ival == 2 && (flags == 4 || (flags == 8 && ignore_mode.ival))) if (ignore_spec.ival == 2 && (flags == 4 || (flags == 8 && ignore_mode.ival)))
return true; return true;
else if (ignore_spec.ival == 1 && (flags == 4) && !cl.spectator) else if (ignore_spec.ival == 1 && (flags == 4) && !pv->spectator)
return true; return true;
if (!sendername) if (!sendername)
@ -595,10 +597,10 @@ qboolean Ignore_Message(const char *sendername, const char *s, int flags)
if (ignore_opponents.ival && ( if (ignore_opponents.ival && (
(int) ignore_opponents.ival == 1 || (int) ignore_opponents.ival == 1 ||
(cls.state >= ca_connected && /*!cl.standby &&*/ !cls.demoplayback && !cl.spectator) // match? (cls.state >= ca_connected && /*!cl.standby &&*/ !cls.demoplayback && !pv->spectator) // match?
) && ) &&
flags == 1 && !cl.spectator && slot != cl.playerview[0].playernum && flags == 1 && !pv->spectator && slot != pv->playernum &&
(!cl.teamplay || strcmp(cl.players[slot].team, cl.players[cl.playerview[0].playernum].team)) (!cl.teamplay || strcmp(cl.players[slot].team, cl.players[pv->playernum].team))
) )
{ {
return true; return true;

View File

@ -273,7 +273,7 @@ void IN_JumpDown (void)
int pnum = CL_TargettedSplit(false); int pnum = CL_TargettedSplit(false);
playerview_t *pv = &cl.playerview[pnum];
condition = (cls.state == ca_active && cl_smartjump.ival && !prox_inmenu.ival); condition = (cls.state == ca_active && cl_smartjump.ival && !prox_inmenu.ival);
@ -283,14 +283,14 @@ void IN_JumpDown (void)
else else
#endif #endif
#ifdef QUAKESTATS #ifdef QUAKESTATS
if (condition && cl.playerview[pnum].stats[STAT_HEALTH] > 0 && !cls.demoplayback && !cl.spectator && if (condition && cl.playerview[pnum].stats[STAT_HEALTH] > 0 && !cls.demoplayback && !pv->spectator &&
(cls.protocol==CP_NETQUAKE || cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[cl.playerview[pnum].playernum].messagenum == cl.validsequence) (cls.protocol==CP_NETQUAKE || cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[pv->playernum].messagenum == cl.validsequence)
&& cl.playerview[pnum].waterlevel >= 2 && (!cl.teamfortress || !(in_forward.state[pnum] & 1)) && cl.playerview[pnum].waterlevel >= 2 && (!cl.teamfortress || !(in_forward.state[pnum] & 1))
) )
KeyDown(&in_up); KeyDown(&in_up);
else else
#endif #endif
if (condition && cl.spectator && cl.playerview[pnum].cam_state == CAM_FREECAM) if (condition && pv->spectator && pv->cam_state == CAM_FREECAM)
KeyDown(&in_up); KeyDown(&in_up);
else else
KeyDown(&in_jump); KeyDown(&in_jump);
@ -1404,6 +1404,7 @@ void CL_UpdateSeats(void)
targ = MAX_SPLITS; targ = MAX_SPLITS;
if (cl.splitclients < targ) if (cl.splitclients < targ)
{ {
char *ver;
char buffer[2048]; char buffer[2048];
char newinfo[2048]; char newinfo[2048];
Q_strncpyz(newinfo, cls.userinfo[cl.splitclients], sizeof(newinfo)); Q_strncpyz(newinfo, cls.userinfo[cl.splitclients], sizeof(newinfo));
@ -1423,6 +1424,14 @@ void CL_UpdateSeats(void)
if (!*Info_ValueForKey(newinfo, "skin")) //give players the same skin by default, because we can. q2 cares for teams. qw might as well (its not like anyone actually uses them thanks to enemy-skin forcing). if (!*Info_ValueForKey(newinfo, "skin")) //give players the same skin by default, because we can. q2 cares for teams. qw might as well (its not like anyone actually uses them thanks to enemy-skin forcing).
Info_SetValueForKey(newinfo, "skin", Info_ValueForKey(cls.userinfo[0], "skin"), sizeof(newinfo)); Info_SetValueForKey(newinfo, "skin", Info_ValueForKey(cls.userinfo[0], "skin"), sizeof(newinfo));
#ifdef SVNREVISION
if (strcmp(STRINGIFY(SVNREVISION), "-"))
ver = va("%s v%i.%02i %s", DISTRIBUTION, FTE_VER_MAJOR, FTE_VER_MINOR, STRINGIFY(SVNREVISION));
else
#endif
ver = va("%s v%i.%02i", DISTRIBUTION, FTE_VER_MAJOR, FTE_VER_MINOR);
Info_SetValueForKey(newinfo, "*ver", ver, sizeof(newinfo));
CL_SendClientCommand(true, "addseat %i %s", cl.splitclients, COM_QuotedString(newinfo, buffer, sizeof(buffer), false)); CL_SendClientCommand(true, "addseat %i %s", cl.splitclients, COM_QuotedString(newinfo, buffer, sizeof(buffer), false));
} }
else if (cl.splitclients > targ) else if (cl.splitclients > targ)
@ -1736,6 +1745,7 @@ void CL_SendCmd (double frametime, qboolean mainloop)
} }
for (plnum = 0; plnum < cl.splitclients; plnum++) for (plnum = 0; plnum < cl.splitclients; plnum++)
{ {
playerview_t *pv = &cl.playerview[plnum];
cmd = &cl.outframes[i].cmd[plnum]; cmd = &cl.outframes[i].cmd[plnum];
memset(cmd, 0, sizeof(*cmd)); memset(cmd, 0, sizeof(*cmd));
@ -1758,12 +1768,12 @@ void CL_SendCmd (double frametime, qboolean mainloop)
VectorClear(mousemovements[plnum]); VectorClear(mousemovements[plnum]);
// if we are spectator, try autocam // if we are spectator, try autocam
if (cl.spectator) if (pv->spectator)
Cam_Track(&cl.playerview[plnum], cmd); Cam_Track(pv, cmd);
CL_FinishMove(cmd, cmd->msec, plnum); CL_FinishMove(cmd, cmd->msec, plnum);
Cam_FinishMove(&cl.playerview[plnum], cmd); Cam_FinishMove(pv, cmd);
#ifdef CSQC_DAT #ifdef CSQC_DAT
CSQC_Input_Frame(plnum, cmd); CSQC_Input_Frame(plnum, cmd);
@ -1772,7 +1782,6 @@ void CL_SendCmd (double frametime, qboolean mainloop)
if (cls.state == ca_active) if (cls.state == ca_active)
{ {
player_state_t *from, *to; player_state_t *from, *to;
playerview_t *pv = &cl.playerview[plnum];
from = &cl.inframes[cl.ackedmovesequence & UPDATE_MASK].playerstate[pv->playernum]; from = &cl.inframes[cl.ackedmovesequence & UPDATE_MASK].playerstate[pv->playernum];
to = &cl.inframes[cl.movesequence & UPDATE_MASK].playerstate[pv->playernum]; to = &cl.inframes[cl.movesequence & UPDATE_MASK].playerstate[pv->playernum];
CL_PredictUsercmd(pv->playernum, pv->viewentity, from, to, &cl.outframes[cl.ackedmovesequence & UPDATE_MASK].cmd[plnum]); CL_PredictUsercmd(pv->playernum, pv->viewentity, from, to, &cl.outframes[cl.ackedmovesequence & UPDATE_MASK].cmd[plnum]);

View File

@ -1657,6 +1657,7 @@ This is also called on Host_Error, so it shouldn't cause any errors
void CL_Disconnect (void) void CL_Disconnect (void)
{ {
qbyte final[12]; qbyte final[12];
int i;
connectinfo.trying = false; connectinfo.trying = false;
@ -1741,7 +1742,8 @@ void CL_Disconnect (void)
COM_FlushTempoaryPacks(); COM_FlushTempoaryPacks();
r_worldentity.model = NULL; r_worldentity.model = NULL;
cl.spectator = 0; for (i = 0; i < cl.splitclients; i++)
cl.playerview[i].spectator = 0;
cl.sendprespawn = false; cl.sendprespawn = false;
cl.intermissionmode = IM_NONE; cl.intermissionmode = IM_NONE;
cl.oldgametime = 0; cl.oldgametime = 0;
@ -2033,9 +2035,18 @@ void CL_CheckServerInfo(void)
unsigned int allowed; unsigned int allowed;
#ifdef QUAKESTATS #ifdef QUAKESTATS
int oldstate; int oldstate;
#endif
#ifndef CLIENTONLY
extern cvar_t sv_cheats;
#endif #endif
int oldteamplay; int oldteamplay;
qboolean spectating = cl.spectator && cl.spectator != 2; //spectator 2 = spectator-with-scores, considered to be players. this means we don't want to allow spec cheats while they're inactive, because that would be weird. qboolean spectating = true;
int i;
//spectator 2 = spectator-with-scores, considered to be players. this means we don't want to allow spec cheats while they're inactive, because that would be weird.
for (i = 0; i < cl.splitclients; i++)
if (cl.playerview[i].spectator != 1)
spectating = false;
oldteamplay = cl.teamplay; oldteamplay = cl.teamplay;
cl.teamplay = atoi(Info_ValueForKey(cl.serverinfo, "teamplay")); cl.teamplay = atoi(Info_ValueForKey(cl.serverinfo, "teamplay"));
@ -2073,7 +2084,8 @@ void CL_CheckServerInfo(void)
#ifndef CLIENTONLY #ifndef CLIENTONLY
//allow cheats in single player regardless of sv_cheats. //allow cheats in single player regardless of sv_cheats.
if (sv.state == ss_active && sv.allocated_client_slots == 1) //(also directly read the sv_cheats cvar to avoid issues with nq protocols that don't support serverinfo.
if ((sv.state == ss_active && sv.allocated_client_slots == 1) || sv_cheats.ival)
cls.allow_cheats = true; cls.allow_cheats = true;
#endif #endif
@ -3074,6 +3086,7 @@ void CL_ConnectionlessPacket (void)
COM_Parse(s); COM_Parse(s);
if (!strcmp(com_token, "ccept")) if (!strcmp(com_token, "ccept"))
{ {
/*this is a DP server... but we don't know which version nor nq protocol*/
Con_Printf ("accept\n"); Con_Printf ("accept\n");
if (cls.state == ca_connected) if (cls.state == ca_connected)
return; //we're already connected. don't do it again! return; //we're already connected. don't do it again!
@ -3090,10 +3103,9 @@ void CL_ConnectionlessPacket (void)
CL_ParseEstablished(); CL_ParseEstablished();
Con_DPrintf ("CL_EstablishConnection: connected to %s\n", cls.servername); Con_DPrintf ("CL_EstablishConnection: connected to %s\n", cls.servername);
/*this is a DP server... but we don't know which version*/
cls.netchan.isnqprotocol = true; cls.netchan.isnqprotocol = true;
cls.protocol = CP_NETQUAKE; cls.protocol = CP_NETQUAKE;
cls.protocol_nq = CPNQ_ID; cls.protocol_nq = CPNQ_ID; //assume vanilla protocol until we know better.
cls.proquake_angles_hack = false; cls.proquake_angles_hack = false;
cls.challenge = connectinfo.challenge; cls.challenge = connectinfo.challenge;
connectinfo.trying = false; connectinfo.trying = false;
@ -3846,14 +3858,12 @@ void CL_ServerInfo_f(void)
} }
#endif #endif
/* #ifdef FTPCLIENT
#ifdef WEBCLIENT
void CL_FTP_f(void) void CL_FTP_f(void)
{ {
FTP_Client_Command(Cmd_Args(), NULL); FTP_Client_Command(Cmd_Args(), NULL);
} }
#endif #endif
*/
//fixme: make a cvar //fixme: make a cvar
void CL_Fog_f(void) void CL_Fog_f(void)
@ -3930,6 +3940,7 @@ void CL_Status_f(void)
switch(cls.protocol) switch(cls.protocol)
{ {
default:
case CP_UNKNOWN: case CP_UNKNOWN:
Con_Printf("Unknown protocol\n"); Con_Printf("Unknown protocol\n");
break; break;
@ -4230,9 +4241,9 @@ void CL_Init (void)
Cvar_Register (&qtvcl_forceversion1, cl_controlgroup); Cvar_Register (&qtvcl_forceversion1, cl_controlgroup);
Cvar_Register (&qtvcl_eztvextensions, cl_controlgroup); Cvar_Register (&qtvcl_eztvextensions, cl_controlgroup);
//#ifdef WEBCLIENT #ifdef FTPCLIENT
// Cmd_AddCommand ("ftp", CL_FTP_f); Cmd_AddCommand ("ftp", CL_FTP_f);
//#endif #endif
Cmd_AddCommandD ("changing", CL_Changing_f, "Part of network protocols. This command should not be used manually."); Cmd_AddCommandD ("changing", CL_Changing_f, "Part of network protocols. This command should not be used manually.");
Cmd_AddCommand ("disconnect", CL_Disconnect_f); Cmd_AddCommand ("disconnect", CL_Disconnect_f);
@ -5538,7 +5549,7 @@ double Host_Frame (double time)
extern cvar_t scr_chatmodecvar, r_stereo_method; extern cvar_t scr_chatmodecvar, r_stereo_method;
if (scr_chatmodecvar.ival && cl.intermissionmode == IM_NONE) if (scr_chatmodecvar.ival && cl.intermissionmode == IM_NONE)
scr_chatmode = (cl.spectator&&cl.splitclients<2&&cls.state == ca_active)?2:1; scr_chatmode = (cl.playerview[0].spectator&&cl.splitclients<2&&cls.state == ca_active)?2:1;
else else
scr_chatmode = 0; scr_chatmode = 0;

View File

@ -3086,18 +3086,19 @@ static void CLQW_ParseServerData (void)
{ {
cl.playerview[j].playernum = cl.allocated_client_slots + j; cl.playerview[j].playernum = cl.allocated_client_slots + j;
cl.playerview[j].viewentity = 0; //free floating. cl.playerview[j].viewentity = 0; //free floating.
cl.playerview[j].spectator = true;
for (i = 0; i < UPDATE_BACKUP; i++) for (i = 0; i < UPDATE_BACKUP; i++)
{ {
cl.inframes[i].playerstate[cl.playerview[j].playernum].pm_type = PM_SPECTATOR; cl.inframes[i].playerstate[cl.playerview[j].playernum].pm_type = PM_SPECTATOR;
cl.inframes[i].playerstate[cl.playerview[j].playernum].messagenum = 1; cl.inframes[i].playerstate[cl.playerview[j].playernum].messagenum = 1;
} }
} }
cl.spectator = true;
cl.splitclients = 1; cl.splitclients = 1;
} }
else if (cls.fteprotocolextensions2 & PEXT2_MAXPLAYERS) else if (cls.fteprotocolextensions2 & PEXT2_MAXPLAYERS)
{ {
qboolean spec = false;
cl.allocated_client_slots = MSG_ReadByte(); cl.allocated_client_slots = MSG_ReadByte();
if (cl.allocated_client_slots > MAX_CLIENTS) if (cl.allocated_client_slots > MAX_CLIENTS)
{ {
@ -3109,13 +3110,14 @@ static void CLQW_ParseServerData (void)
cl.splitclients = MSG_ReadByte(); cl.splitclients = MSG_ReadByte();
if (cl.splitclients & 128) if (cl.splitclients & 128)
{ {
cl.spectator = true; spec = true;
cl.splitclients &= ~128; cl.splitclients &= ~128;
} }
if (cl.splitclients > MAX_SPLITS) if (cl.splitclients > MAX_SPLITS)
Host_EndGame("Server sent us too many alternate clients\n"); Host_EndGame("Server sent us too many alternate clients\n");
for (pnum = 0; pnum < cl.splitclients; pnum++) for (pnum = 0; pnum < cl.splitclients; pnum++)
{ {
cl.playerview[pnum].spectator = true;
if (cls.z_ext & Z_EXT_VIEWHEIGHT) if (cls.z_ext & Z_EXT_VIEWHEIGHT)
cl.playerview[pnum].viewheight = 0; cl.playerview[pnum].viewheight = 0;
cl.playerview[pnum].playernum = MSG_ReadByte(); cl.playerview[pnum].playernum = MSG_ReadByte();
@ -3137,9 +3139,11 @@ static void CLQW_ParseServerData (void)
cl.playerview[clnum].playernum = pnum; cl.playerview[clnum].playernum = pnum;
if (cl.playerview[clnum].playernum & 128) if (cl.playerview[clnum].playernum & 128)
{ {
cl.spectator = true; cl.playerview[clnum].spectator = true;
cl.playerview[clnum].playernum &= ~128; cl.playerview[clnum].playernum &= ~128;
} }
else
cl.playerview[clnum].spectator = false;
if (cl.playerview[clnum].playernum >= cl.allocated_client_slots) if (cl.playerview[clnum].playernum >= cl.allocated_client_slots)
Host_EndGame("unsupported local player slot\n"); Host_EndGame("unsupported local player slot\n");
@ -3309,8 +3313,8 @@ static void CLQ2_ParseServerData (void)
// parse player entity number // parse player entity number
cl.playerview[0].playernum = MSG_ReadShort (); cl.playerview[0].playernum = MSG_ReadShort ();
cl.playerview[0].viewentity = cl.playerview[0].playernum+1; cl.playerview[0].viewentity = cl.playerview[0].playernum+1;
cl.playerview[0].spectator = false;
cl.splitclients = 1; cl.splitclients = 1;
cl.spectator = false;
cl.numq2visibleweapons = 1; //give it a default. cl.numq2visibleweapons = 1; //give it a default.
cl.q2visibleweapons[0] = "weapon.md2"; cl.q2visibleweapons[0] = "weapon.md2";
@ -4884,7 +4888,7 @@ void CL_NewTranslation (int slot)
bottom = player->rbottomcolor; bottom = player->rbottomcolor;
if (cl.splitclients < 2 && !(cl.fpd & FPD_NO_FORCE_COLOR)) //no colour/skin forcing in splitscreen. if (cl.splitclients < 2 && !(cl.fpd & FPD_NO_FORCE_COLOR)) //no colour/skin forcing in splitscreen.
{ {
if (cl.teamplay && cl.spectator) if (cl.teamplay && cl.playerview[0].spectator)
{ {
local = Cam_TrackNum(&cl.playerview[0]); local = Cam_TrackNum(&cl.playerview[0]);
if (local < 0) if (local < 0)
@ -4977,11 +4981,14 @@ static void CL_ProcessUserInfo (int slot, player_info_t *player)
player->colourised = TP_FindColours(player->name); player->colourised = TP_FindColours(player->name);
// If it's us // If it's us
if (slot == cl.playerview[0].playernum && player->name[0]) for (i = 0; i < cl.splitclients; i++)
if (slot == cl.playerview[i].playernum)
break;
if (i < cl.splitclients && player->name[0])
{ {
if (cl.spectator != player->spectator) if (cl.playerview[i].spectator != player->spectator)
{ {
cl.spectator = player->spectator; cl.playerview[i].spectator = player->spectator;
for (i = 0; i < cl.splitclients; i++) for (i = 0; i < cl.splitclients; i++)
{ {
Cam_Unlock(&cl.playerview[i]); Cam_Unlock(&cl.playerview[i]);
@ -4993,7 +5000,7 @@ static void CL_ProcessUserInfo (int slot, player_info_t *player)
Skin_FlushPlayers(); Skin_FlushPlayers();
} }
else if (cl.teamplay && cl.spectator && slot == Cam_TrackNum(&cl.playerview[0])) //skin forcing cares about the team of the guy we're tracking. else if (cl.teamplay && cl.playerview[0].spectator && slot == Cam_TrackNum(&cl.playerview[0])) //skin forcing cares about the team of the guy we're tracking.
Skin_FlushPlayers(); Skin_FlushPlayers();
else if (cls.state == ca_active) else if (cls.state == ca_active)
Skin_Find (player); Skin_Find (player);
@ -6104,7 +6111,8 @@ static void CL_ParseWeaponStats(void)
static void CL_ParseItemTimer(void) static void CL_ParseItemTimer(void)
{ {
float timeout = atof(Cmd_Argv(0)); //it [cur/]duration x y z radius 0xRRGGBB "timername" owningent
float timeout;// = atof(Cmd_Argv(0));
vec3_t org = { atof(Cmd_Argv(1)), vec3_t org = { atof(Cmd_Argv(1)),
atof(Cmd_Argv(2)), atof(Cmd_Argv(2)),
atof(Cmd_Argv(3))}; atof(Cmd_Argv(3))};
@ -6113,6 +6121,15 @@ static void CL_ParseItemTimer(void)
// char *timername = Cmd_Argv(6); // char *timername = Cmd_Argv(6);
unsigned int entnum = strtoul(Cmd_Argv(7), NULL, 0); unsigned int entnum = strtoul(Cmd_Argv(7), NULL, 0);
struct itemtimer_s *timer; struct itemtimer_s *timer;
float start = cl.time;
char *e;
timeout = strtod(Cmd_Argv(0), &e);
if (*e == '/')
{
start += timeout;
timeout = atof(e+1);
start -= timeout;
}
if (!timeout) if (!timeout)
timeout = FLT_MAX; timeout = FLT_MAX;
@ -6121,7 +6138,12 @@ static void CL_ParseItemTimer(void)
for (timer = cl.itemtimers; timer; timer = timer->next) for (timer = cl.itemtimers; timer; timer = timer->next)
{ {
if (VectorCompare(timer->origin, org) && timer->entnum == entnum && entnum) if (entnum)
{
if (timer->entnum == entnum)
break;
}
else if (VectorCompare(timer->origin, org))
break; break;
} }
if (!timer) if (!timer)
@ -6137,8 +6159,8 @@ static void CL_ParseItemTimer(void)
timer->radius = radius; timer->radius = radius;
timer->duration = timeout; timer->duration = timeout;
timer->entnum = entnum; timer->entnum = entnum;
timer->start = cl.time; timer->start = start;
timer->end = cl.time + timer->duration; timer->end = start + timer->duration;
timer->rgb[0] = ((rgb>>16)&0xff)/255.0; timer->rgb[0] = ((rgb>>16)&0xff)/255.0;
timer->rgb[1] = ((rgb>> 8)&0xff)/255.0; timer->rgb[1] = ((rgb>> 8)&0xff)/255.0;
timer->rgb[2] = ((rgb )&0xff)/255.0; timer->rgb[2] = ((rgb )&0xff)/255.0;
@ -6931,7 +6953,7 @@ void CLQW_ParseServerMessage (void)
if (cl.intermissionmode == IM_NONE) if (cl.intermissionmode == IM_NONE)
{ {
TP_ExecTrigger ("f_mapend", false); TP_ExecTrigger ("f_mapend", false);
if (cl.spectator) if (cl.playerview[destsplit].spectator)
TP_ExecTrigger ("f_specmapend", true); TP_ExecTrigger ("f_specmapend", true);
cl.completed_time = cl.gametime; cl.completed_time = cl.gametime;
} }

View File

@ -449,7 +449,7 @@ void CL_PredictUsercmd (int pnum, int entnum, player_state_t *from, player_state
void CL_CatagorizePosition (playerview_t *pv, float *org) void CL_CatagorizePosition (playerview_t *pv, float *org)
{ {
//fixme: in nq, we are told by the server and should skip this, which avoids needing to know the player's size. //fixme: in nq, we are told by the server and should skip this, which avoids needing to know the player's size.
if (cl.spectator) if (pv->spectator)
{ {
pv->onground = false; // in air pv->onground = false; // in air
return; return;
@ -912,7 +912,7 @@ void CL_PredictMovePNum (int seat)
pv->nolocalplayer = !!(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) || (cls.protocol != CP_QUAKEWORLD); pv->nolocalplayer = !!(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) || (cls.protocol != CP_QUAKEWORLD);
if (!cl.spectator && (pv->cam_state != CAM_FREECAM || pv->cam_spec_track != -1)) //just in case if (!pv->spectator && (pv->cam_state != CAM_FREECAM || pv->cam_spec_track != -1)) //just in case
{ {
if (pv->cam_state != CAM_FREECAM) if (pv->cam_state != CAM_FREECAM)
pv->viewentity = (cls.demoplayback)?0:(pv->playernum+1); pv->viewentity = (cls.demoplayback)?0:(pv->playernum+1);

View File

@ -712,9 +712,6 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
void SCR_CheckDrawCenterString (void) void SCR_CheckDrawCenterString (void)
{ {
#ifdef QUAKEHUD
extern qboolean sb_showscores;
#endif
int pnum; int pnum;
cprint_t *p; cprint_t *p;
@ -731,7 +728,7 @@ void SCR_CheckDrawCenterString (void)
continue; //should probably allow the console with a scissor region or something. continue; //should probably allow the console with a scissor region or something.
#ifdef QUAKEHUD #ifdef QUAKEHUD
if (sb_showscores) //this was annoying if (cl.playerview[pnum].sb_showscores) //this was annoying
continue; continue;
#endif #endif
@ -3066,7 +3063,7 @@ void SCR_DrawTwoDimensional(int uimenu, qboolean nohud)
} }
else if (cl.intermissionmode != IM_NONE) else if (cl.intermissionmode != IM_NONE)
{ {
Sbar_IntermissionOverlay (); Sbar_IntermissionOverlay (r_refdef.playerview);
} }
else else
{ {

View File

@ -599,6 +599,7 @@ struct playerview_s
{ {
int playernum; //cl.players index for this player. int playernum; //cl.players index for this player.
qboolean nolocalplayer; //inhibit use of qw-style players, predict based on entities. qboolean nolocalplayer; //inhibit use of qw-style players, predict based on entities.
qboolean spectator;
#ifdef PEXT_SETVIEW #ifdef PEXT_SETVIEW
int viewentity; //view is attached to this entity. int viewentity; //view is attached to this entity.
#endif #endif
@ -610,12 +611,16 @@ struct playerview_s
float item_gettime[32]; // cl.time of aquiring item, for blinking float item_gettime[32]; // cl.time of aquiring item, for blinking
float faceanimtime; // use anim frame if cl.time < this float faceanimtime; // use anim frame if cl.time < this
#ifdef QUAKEHUD
qboolean sb_showscores;
qboolean sb_showteamscores;
#ifdef HEXEN2 #ifdef HEXEN2
int sb_hexen2_cur_item;//hexen2 hud int sb_hexen2_cur_item;//hexen2 hud
float sb_hexen2_item_time; float sb_hexen2_item_time;
qboolean sb_hexen2_extra_info;//show the extra stuff qboolean sb_hexen2_extra_info;//show the extra stuff
qboolean sb_hexen2_infoplaque; qboolean sb_hexen2_infoplaque;
#endif #endif
#endif
// the client maintains its own idea of view angles, which are // the client maintains its own idea of view angles, which are
@ -752,7 +757,7 @@ typedef struct
// render a frame yet // render a frame yet
int movesequence; // client->server frames int movesequence; // client->server frames
int spectator; // int spectator;
int autotrack_hint; //the latest hint from the mod, might be negative for invalid. int autotrack_hint; //the latest hint from the mod, might be negative for invalid.
int autotrack_killer; //if someone kills the guy we're tracking, this is the guy we should switch to. int autotrack_killer; //if someone kills the guy we're tracking, this is the guy we should switch to.

View File

@ -768,7 +768,7 @@ void Key_DefaultLinkClicked(console_t *con, char *text, char *info)
if (*cl.players[player].ip) if (*cl.players[player].ip)
Con_Footerf(con, true, "\n%s", cl.players[player].ip); Con_Footerf(con, true, "\n%s", cl.players[player].ip);
if (cl.spectator || cls.demoplayback) if (cl.playerview[0].spectator || cls.demoplayback)
{ {
//we're spectating, or an mvd //we're spectating, or an mvd
Con_Footerf(con, true, " ^[Spectate\\player\\%i\\action\\spec^]", player); Con_Footerf(con, true, " ^[Spectate\\player\\%i\\action\\spec^]", player);
@ -803,7 +803,7 @@ void Key_DefaultLinkClicked(console_t *con, char *text, char *info)
//hey look! its you! //hey look! its you!
if (cl.spectator || cls.demoplayback) if (cl.playerview[i].spectator || cls.demoplayback)
{ {
//need join option here or something //need join option here or something
} }

View File

@ -246,7 +246,7 @@ static void CSQC_ChangeLocalPlayer(int seat)
{ {
if (csqc_playerview->viewentity) if (csqc_playerview->viewentity)
*csqcg.player_localentnum = csqc_playerview->viewentity; *csqcg.player_localentnum = csqc_playerview->viewentity;
else if (cl.spectator && Cam_TrackNum(csqc_playerview) >= 0) else if (csqc_playerview->spectator && Cam_TrackNum(csqc_playerview) >= 0)
*csqcg.player_localentnum = Cam_TrackNum(csqc_playerview) + 1; *csqcg.player_localentnum = Cam_TrackNum(csqc_playerview) + 1;
else if (csqc_playerview == &csqc_nullview) else if (csqc_playerview == &csqc_nullview)
*csqcg.player_localentnum = 0; *csqcg.player_localentnum = 0;
@ -2185,7 +2185,7 @@ static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars
#ifdef PLUGINS #ifdef PLUGINS
Plug_SBar (r_refdef.playerview); Plug_SBar (r_refdef.playerview);
#else #else
if (Sbar_ShouldDraw()) if (Sbar_ShouldDraw(r_refdef.playerview))
{ {
SCR_TileClear (sb_lines); SCR_TileClear (sb_lines);
Sbar_Draw (r_refdef.playerview); Sbar_Draw (r_refdef.playerview);
@ -2203,7 +2203,7 @@ static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars
} }
else if (cl.intermissionmode != IM_NONE) else if (cl.intermissionmode != IM_NONE)
{ {
Sbar_IntermissionOverlay (); Sbar_IntermissionOverlay (r_refdef.playerview);
} }
} }

View File

@ -39,7 +39,6 @@ model_t *currentmodel;
uploadfmt_t lightmap_fmt; //bgra32, rgba32, rgb24, lum8 uploadfmt_t lightmap_fmt; //bgra32, rgba32, rgb24, lum8
int lightmap_bytes; // 1, 3 or 4 int lightmap_bytes; // 1, 3 or 4
qboolean lightmap_bgra;
size_t maxblocksize; size_t maxblocksize;
vec3_t *blocknormals; vec3_t *blocknormals;
@ -903,8 +902,7 @@ static void Surf_BuildLightMap (msurface_t *surf, qbyte *dest, qbyte *deluxdest,
if (currentmodel->deluxdata) if (currentmodel->deluxdata)
Surf_BuildDeluxMap(currentmodel, surf, deluxdest, lmwidth, blocknormals); Surf_BuildDeluxMap(currentmodel, surf, deluxdest, lmwidth, blocknormals);
#ifdef PEXT_LIGHTSTYLECOL if (lightmap_fmt != TF_LUM8)
if (lightmap_bytes == 4 || lightmap_bytes == 3)
{ {
// set to full bright if no light data // set to full bright if no light data
if (ambient < 0) if (ambient < 0)
@ -1078,40 +1076,22 @@ static void Surf_BuildLightMap (msurface_t *surf, qbyte *dest, qbyte *deluxdest,
if (!r_stains.value || !surf->stained) if (!r_stains.value || !surf->stained)
stainsrc = NULL; stainsrc = NULL;
if (lightmap_bytes == 4) switch(lightmap_fmt)
{ {
if (lightmap_bgra) default:
{ Sys_Error("Bad lightmap_fmt\n");
Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, bgra4_os, stainsrc, lmwidth); case TF_BGRA32:
} Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, bgra4_os, stainsrc, lmwidth);
else break;
{ // case TF_RGBA32:
/*if (!r_stains.value || !surf->stained) // Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, rgba4, stainsrc, lmwidth);
Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, rgba4, NULL); // break;
else case TF_RGB24:
Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, rgba4, stainsrc); Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, rgb3_os, stainsrc, lmwidth);
*/ break;
}
}
else if (lightmap_bytes == 3)
{
if (lightmap_bgra)
{
/*
if (!r_stains.value || !surf->stained)
Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, bgr3, NULL);
else
Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, bgr3, stainsrc);
*/
}
else
{
Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, rgb3_os, stainsrc, lmwidth);
}
} }
} }
else else
#endif
{ {
// set to full bright if no light data // set to full bright if no light data
if (!surf->samples || !currentmodel->lightdata) if (!surf->samples || !currentmodel->lightdata)
@ -1206,8 +1186,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, qbyte
if (wmodel->deluxdata) if (wmodel->deluxdata)
Surf_BuildDeluxMap(wmodel, surf, deluxdest, lmwidth, blocknormals); Surf_BuildDeluxMap(wmodel, surf, deluxdest, lmwidth, blocknormals);
#ifdef PEXT_LIGHTSTYLECOL if (lightmap_fmt != TF_LUM8)
if (lightmap_bytes == 4 || lightmap_bytes == 3)
{ {
// set to full bright if no light data // set to full bright if no light data
if (ambient < 0) if (ambient < 0)
@ -1377,40 +1356,20 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, qbyte
if (!r_stains.value || !surf->stained) if (!r_stains.value || !surf->stained)
stainsrc = NULL; stainsrc = NULL;
if (lightmap_bytes == 4) switch(lightmap_fmt)
{ {
if (lightmap_bgra) default:
{ Sys_Error("Bad lightmap_fmt\n");
Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, bgra4_os, stainsrc, lmwidth); break;
} case TF_BGRA32:
else Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, bgra4_os, stainsrc, lmwidth);
{ break;
/*if (!r_stains.value || !surf->stained) case TF_RGB24:
Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, rgba4, NULL); Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, rgb3_os, stainsrc, lmwidth);
else break;
Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, rgba4, stainsrc);
*/
}
}
else if (lightmap_bytes == 3)
{
if (lightmap_bgra)
{
/*
if (!r_stains.value || !surf->stained)
Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, bgr3, NULL);
else
Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, bgr3, stainsrc);
*/
}
else
{
Surf_StoreLightmap(dest, blocklights, smax, tmax, shift, rgb3_os, stainsrc, lmwidth);
}
} }
} }
else else
#endif
{ {
// set to full bright if no light data // set to full bright if no light data
if (!surf->samples || !wmodel->lightdata) if (!surf->samples || !wmodel->lightdata)
@ -3305,58 +3264,44 @@ void Surf_Clear(model_t *mod)
//pick fastest mode for lightmap data //pick fastest mode for lightmap data
void Surf_LightmapMode(void) void Surf_LightmapMode(void)
{ {
lightmap_bgra = true;
switch(qrenderer) switch(qrenderer)
{ {
default: default:
case QR_SOFTWARE: // case QR_VULKAN:
// case QR_SOFTWARE:
// case QR_DIRECT3D8:
// case QR_DIRECT3D9:
// case QR_DIRECT3D11:
lightmap_fmt = TF_BGRA32; lightmap_fmt = TF_BGRA32;
lightmap_bytes = 4;
lightmap_bgra = true;
break; break;
#ifdef D3DQUAKE
case QR_DIRECT3D8:
case QR_DIRECT3D9:
case QR_DIRECT3D11:
/*always bgra, hope your card supports it*/
lightmap_fmt = TF_BGRA32;
lightmap_bytes = 4;
lightmap_bgra = true;
break;
#endif
#ifdef GLQUAKE #ifdef GLQUAKE
case QR_OPENGL: case QR_OPENGL:
/*favour bgra if the gpu supports it, otherwise use rgb only if it'll be used*/ /*favour bgra if the gpu supports it, otherwise use rgb only if it'll be used*/
lightmap_bgra = false;
if (gl_config.gles) if (gl_config.gles)
{ lightmap_fmt = TF_RGB24; //rgb24 is a guarenteed supported format, where bgr24 or rgbx32 are not.
//rgb is a supported format, where bgr or rgbx are not.
lightmap_fmt = TF_RGB24;
lightmap_bytes = 3;
lightmap_bgra = false;
}
else if (gl_config.glversion >= 1.2) else if (gl_config.glversion >= 1.2)
{ lightmap_fmt = TF_BGRA32; //the more common case
/*the more common case*/
lightmap_fmt = TF_BGRA32;
lightmap_bytes = 4;
lightmap_bgra = true;
}
else if (cl.worldmodel->fromgame == fg_quake3 || (cl.worldmodel->engineflags & MDLF_RGBLIGHTING) || cl.worldmodel->deluxdata || r_loadlits.value) else if (cl.worldmodel->fromgame == fg_quake3 || (cl.worldmodel->engineflags & MDLF_RGBLIGHTING) || cl.worldmodel->deluxdata || r_loadlits.value)
{ lightmap_fmt = TF_RGB24; //ooold gl driver, but we need rgb lighting
lightmap_fmt = TF_RGB24;
lightmap_bgra = false;
lightmap_bytes = 3;
}
else else
{ lightmap_fmt = TF_LUM8; //oldskool!
lightmap_fmt = TF_LUM8;
lightmap_bytes = 1;
}
break; break;
#endif #endif
} }
switch(lightmap_fmt)
{
default:
case TF_BGRA32:
lightmap_bytes = 4;
break;
case TF_RGB24:
lightmap_bytes = 3;
break;
case TF_LUM8:
lightmap_bytes = 1;
break;
}
} }
//needs to be followed by a BE_UploadAllLightmaps at some point //needs to be followed by a BE_UploadAllLightmaps at some point
@ -3374,6 +3319,8 @@ int Surf_NewLightmaps(int count, int width, int height, qboolean deluxe)
Con_Print("WARNING: Deluxemapping with odd number of lightmaps\n"); Con_Print("WARNING: Deluxemapping with odd number of lightmaps\n");
} }
Sys_LockMutex(com_resourcemutex);
i = numlightmaps + count; i = numlightmaps + count;
lightmap = BZ_Realloc(lightmap, sizeof(*lightmap)*(i)); lightmap = BZ_Realloc(lightmap, sizeof(*lightmap)*(i));
while(i > first) while(i > first)
@ -3416,6 +3363,8 @@ int Surf_NewLightmaps(int count, int width, int height, qboolean deluxe)
numlightmaps += count; numlightmaps += count;
Sys_UnlockMutex(com_resourcemutex);
return first; return first;
} }
int Surf_NewExternalLightmaps(int count, char *filepattern, qboolean deluxe) int Surf_NewExternalLightmaps(int count, char *filepattern, qboolean deluxe)
@ -3549,45 +3498,45 @@ void Surf_BuildModelLightmaps (model_t *m)
src = m->lightdata + i*m->lightmaps.width*m->lightmaps.height*3; src = m->lightdata + i*m->lightmaps.width*m->lightmaps.height*3;
if (m->lightdata) if (m->lightdata)
{ {
if (lightmap_bgra && lightmap_bytes == 4) switch(lightmap_fmt)
{ {
default:
Sys_Error("Bad lightmap_fmt\n");
break;
case TF_BGRA32:
for (j = min((m->lightdatasize-i*m->lightmaps.width*m->lightmaps.height*3)/3,m->lightmaps.width*m->lightmaps.height); j > 0; j--, dst += 4, src += 3) for (j = min((m->lightdatasize-i*m->lightmaps.width*m->lightmaps.height*3)/3,m->lightmaps.width*m->lightmaps.height); j > 0; j--, dst += 4, src += 3)
//for (j = 0; j < m->lightmaps.width*m->lightmaps.height; j++, dst += 4, src += 3)
{ {
dst[0] = src[2]; dst[0] = src[2];
dst[1] = src[1]; dst[1] = src[1];
dst[2] = src[0]; dst[2] = src[0];
dst[3] = 255; dst[3] = 255;
} }
} break;
else if (!lightmap_bgra && lightmap_bytes == 4) /*case TF_RGBA32:
{
for (j = min((m->lightdatasize-i*m->lightmaps.width*m->lightmaps.height*3)/3,m->lightmaps.width*m->lightmaps.height); j > 0; j--, dst += 4, src += 3) for (j = min((m->lightdatasize-i*m->lightmaps.width*m->lightmaps.height*3)/3,m->lightmaps.width*m->lightmaps.height); j > 0; j--, dst += 4, src += 3)
//for (j = 0; j < m->lightmaps.width*m->lightmaps.height; j++, dst += 4, src += 3)
{ {
dst[0] = src[0]; dst[0] = src[0];
dst[1] = src[1]; dst[1] = src[1];
dst[2] = src[2]; dst[2] = src[2];
dst[3] = 255; dst[3] = 255;
} }
} break;
else if (lightmap_bgra && lightmap_bytes == 3) case TF_BGR24:
{
for (j = 0; j < m->lightmaps.width*m->lightmaps.height; j++, dst += 3, src += 3) for (j = 0; j < m->lightmaps.width*m->lightmaps.height; j++, dst += 3, src += 3)
{ {
dst[0] = src[2]; dst[0] = src[2];
dst[1] = src[1]; dst[1] = src[1];
dst[2] = src[0]; dst[2] = src[0];
} }
} break;*/
else if (!lightmap_bgra && lightmap_bytes == 3) case TF_RGB24:
{
for (j = 0; j < m->lightmaps.width*m->lightmaps.height; j++, dst += 3, src += 3) for (j = 0; j < m->lightmaps.width*m->lightmaps.height; j++, dst += 3, src += 3)
{ {
dst[0] = src[0]; dst[0] = src[0];
dst[1] = src[1]; dst[1] = src[1];
dst[2] = src[2]; dst[2] = src[2];
} }
break;
} }
} }
} }

View File

@ -360,8 +360,8 @@ extern lightmapinfo_t **lightmap;
extern int numlightmaps; extern int numlightmaps;
//extern texid_t *lightmap_textures; //extern texid_t *lightmap_textures;
//extern texid_t *deluxmap_textures; //extern texid_t *deluxmap_textures;
extern int lightmap_bytes; // 1, 3, or 4 extern int lightmap_bytes; // 1, 3, or 4
extern qboolean lightmap_bgra; /*true=bgra, false=rgba*/ extern uploadfmt_t lightmap_fmt; //bgra32, rgba32, rgb24, lum8
void QDECL Surf_RebuildLightmap_Callback (struct cvar_s *var, char *oldvalue); void QDECL Surf_RebuildLightmap_Callback (struct cvar_s *var, char *oldvalue);

View File

@ -118,9 +118,6 @@ static int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_P
static apic_t *hsb_items[2]; static apic_t *hsb_items[2];
//end hipnotic //end hipnotic
qboolean sb_showscores;
qboolean sb_showteamscores;
static qboolean sbarfailed; static qboolean sbarfailed;
#ifdef HEXEN2 #ifdef HEXEN2
static qboolean sbar_hexen2; static qboolean sbar_hexen2;
@ -131,15 +128,15 @@ float sbar_rect_left;
int sb_lines; // scan lines to draw int sb_lines; // scan lines to draw
void Sbar_DeathmatchOverlay (int start); void Sbar_DeathmatchOverlay (playerview_t *pv, int start);
void Sbar_TeamOverlay (void); void Sbar_TeamOverlay (playerview_t *pv);
static void Sbar_MiniDeathmatchOverlay (playerview_t *pv); static void Sbar_MiniDeathmatchOverlay (playerview_t *pv);
void Sbar_ChatModeOverlay(playerview_t *pv); void Sbar_ChatModeOverlay(playerview_t *pv);
static int Sbar_PlayerNum(playerview_t *pv) static int Sbar_PlayerNum(playerview_t *pv)
{ {
int num; int num;
num = cl.spectator?Cam_TrackNum(pv):-1; num = pv->spectator?Cam_TrackNum(pv):-1;
if (num < 0) if (num < 0)
num = pv->playernum; num = pv->playernum;
return num; return num;
@ -716,7 +713,8 @@ Tab key down
*/ */
void Sbar_ShowTeamScores (void) void Sbar_ShowTeamScores (void)
{ {
if (sb_showteamscores) int seat = CL_TargettedSplit(false);
if (cl.playerview[seat].sb_showteamscores)
return; return;
#ifdef CSQC_DAT #ifdef CSQC_DAT
@ -724,7 +722,7 @@ void Sbar_ShowTeamScores (void)
return; return;
#endif #endif
sb_showteamscores = true; cl.playerview[seat].sb_showteamscores = true;
sb_updates = 0; sb_updates = 0;
} }
@ -737,7 +735,8 @@ Tab key up
*/ */
void Sbar_DontShowTeamScores (void) void Sbar_DontShowTeamScores (void)
{ {
sb_showteamscores = false; int seat = CL_TargettedSplit(false);
cl.playerview[seat].sb_showteamscores = false;
sb_updates = 0; sb_updates = 0;
#ifdef CSQC_DAT #ifdef CSQC_DAT
@ -755,13 +754,14 @@ Tab key down
*/ */
void Sbar_ShowScores (void) void Sbar_ShowScores (void)
{ {
int seat = CL_TargettedSplit(false);
if (scr_scoreboard_teamscores.ival) if (scr_scoreboard_teamscores.ival)
{ {
Sbar_ShowTeamScores(); Sbar_ShowTeamScores();
return; return;
} }
if (sb_showscores) if (cl.playerview[seat].sb_showscores)
return; return;
#ifdef CSQC_DAT #ifdef CSQC_DAT
@ -769,7 +769,7 @@ void Sbar_ShowScores (void)
return; return;
#endif #endif
sb_showscores = true; cl.playerview[seat].sb_showscores = true;
sb_updates = 0; sb_updates = 0;
} }
@ -893,13 +893,14 @@ Tab key up
*/ */
void Sbar_DontShowScores (void) void Sbar_DontShowScores (void)
{ {
int seat = CL_TargettedSplit(false);
if (scr_scoreboard_teamscores.ival) if (scr_scoreboard_teamscores.ival)
{ {
Sbar_DontShowTeamScores(); Sbar_DontShowTeamScores();
return; return;
} }
sb_showscores = false; cl.playerview[seat].sb_showscores = false;
sb_updates = 0; sb_updates = 0;
#ifdef CSQC_DAT #ifdef CSQC_DAT
@ -2166,7 +2167,7 @@ void Sbar_DrawNormal (playerview_t *pv)
, pv->stats[STAT_AMMO] <= 10); , pv->stats[STAT_AMMO] <= 10);
} }
qboolean Sbar_ShouldDraw (void) qboolean Sbar_ShouldDraw (playerview_t *pv)
{ {
#ifdef TEXTEDITOR #ifdef TEXTEDITOR
extern qboolean editoractive; extern qboolean editoractive;
@ -2182,7 +2183,7 @@ qboolean Sbar_ShouldDraw (void)
#endif #endif
#ifdef VM_UI #ifdef VM_UI
if (UI_DrawStatusBar((sb_showscores?1:0) + (sb_showteamscores?2:0))>0) if (UI_DrawStatusBar((pv->sb_showscores?1:0) + (pv->sb_showteamscores?2:0))>0)
return false; return false;
if (UI_MenuState()) if (UI_MenuState())
return false; return false;
@ -2195,10 +2196,9 @@ qboolean Sbar_ShouldDraw (void)
return true; return true;
} }
void Sbar_DrawScoreboard (void) void Sbar_DrawScoreboard (playerview_t *pv)
{ {
int pnum; qboolean isdead;
int deadcount=0;
if (cls.protocol == CP_QUAKE2) if (cls.protocol == CP_QUAKE2)
return; return;
@ -2214,31 +2214,27 @@ void Sbar_DrawScoreboard (void)
} }
#endif #endif
for (pnum = 0; pnum < cl.splitclients; pnum++) isdead = false;
if (pv->spectator && (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV))
{ {
if (cl.spectator && (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)) int t = pv->cam_spec_track;
{ if (t >= 0 && CAM_ISLOCKED(pv) && cl.players[t].statsf[STAT_HEALTH] <= 0)
int t = cl.playerview[pnum].cam_spec_track; isdead = true;
if (t < 0 || !CAM_ISLOCKED(&cl.playerview[pnum]))
continue;
if (cl.players[t].statsf[STAT_HEALTH] <= 0)
deadcount++;
}
else if (!cl.spectator && cl.playerview[pnum].statsf[STAT_HEALTH] <= 0)
deadcount++;
} }
else if (!pv->spectator && pv->statsf[STAT_HEALTH] <= 0)
isdead = true;
if (deadcount == cl.splitclients)// && !cl.spectator) if (isdead)// && !cl.spectator)
{ {
if (cl.teamplay > 0 && !sb_showscores) if (cl.teamplay > 0 && !pv->sb_showscores)
Sbar_TeamOverlay(); Sbar_TeamOverlay(pv);
else else
Sbar_DeathmatchOverlay (0); Sbar_DeathmatchOverlay (pv, 0);
} }
else if (sb_showscores) else if (pv->sb_showscores)
Sbar_DeathmatchOverlay (0); Sbar_DeathmatchOverlay (pv, 0);
else if (sb_showteamscores) else if (pv->sb_showteamscores)
Sbar_TeamOverlay(); Sbar_TeamOverlay(pv);
else else
return; return;
@ -2563,7 +2559,7 @@ static void Sbar_DrawTeamStatus(playerview_t *pv)
y = -32; y = -32;
track = Cam_TrackNum(pv); track = Cam_TrackNum(pv);
if (track == -1 || !cl.spectator) if (track == -1 || !pv->spectator)
track = pv->playernum; track = pv->playernum;
for (p = 0; p < cl.allocated_client_slots; p++) for (p = 0; p < cl.allocated_client_slots; p++)
@ -2730,7 +2726,7 @@ extern cvar_t show_speed_y;
t = Sys_DoubleTime(); t = Sys_DoubleTime();
if ((t - lastupstime) >= 1.0/20) if ((t - lastupstime) >= 1.0/20)
{ {
if (cl.spectator) if (pv->spectator)
track = Cam_TrackNum(pv); track = Cam_TrackNum(pv);
else else
track = -1; track = -1;
@ -2865,7 +2861,7 @@ void Sbar_Draw (playerview_t *pv)
// main area // main area
if (sb_lines > 0) if (sb_lines > 0)
{ {
if (cl.spectator) if (pv->spectator)
{ {
if (pv->cam_state == CAM_FREECAM || pv->cam_state == CAM_PENDING) if (pv->cam_state == CAM_FREECAM || pv->cam_state == CAM_PENDING)
{ {
@ -2879,7 +2875,7 @@ void Sbar_Draw (playerview_t *pv)
} }
else else
{ {
if (sb_showscores || sb_showteamscores || pv->stats[STAT_HEALTH] <= 0) if (pv->sb_showscores || pv->sb_showteamscores || pv->stats[STAT_HEALTH] <= 0)
Sbar_SoloScoreboard (); Sbar_SoloScoreboard ();
// else if (cls.gamemode != GAME_DEATHMATCH) // else if (cls.gamemode != GAME_DEATHMATCH)
// Sbar_CoopScoreboard (); // Sbar_CoopScoreboard ();
@ -2894,7 +2890,7 @@ void Sbar_Draw (playerview_t *pv)
} }
} }
} }
else if (sb_showscores || sb_showteamscores || (pv->stats[STAT_HEALTH] <= 0 && cl.splitclients == 1)) else if (pv->sb_showscores || pv->sb_showteamscores || (pv->stats[STAT_HEALTH] <= 0 && cl.splitclients == 1))
{ {
if (pv == cl.playerview) if (pv == cl.playerview)
{ {
@ -2915,7 +2911,7 @@ void Sbar_Draw (playerview_t *pv)
// top line // top line
if (sb_lines > 24) if (sb_lines > 24)
{ {
if (!cl.spectator || pv->cam_state == CAM_WALLCAM || pv->cam_state == CAM_EYECAM) if (!pv->spectator || pv->cam_state == CAM_WALLCAM || pv->cam_state == CAM_EYECAM)
Sbar_DrawInventory (pv); Sbar_DrawInventory (pv);
else if (cl_sbar.ival) else if (cl_sbar.ival)
Sbar_DrawPic (0, -24, 320, 24, sb_scorebar); //make sure we don't get HoM Sbar_DrawPic (0, -24, 320, 24, sb_scorebar); //make sure we don't get HoM
@ -3006,7 +3002,7 @@ team frags
added by Zoid added by Zoid
================== ==================
*/ */
void Sbar_TeamOverlay (void) void Sbar_TeamOverlay (playerview_t *pv)
{ {
mpic_t *pic; mpic_t *pic;
int i, k; int i, k;
@ -3015,8 +3011,8 @@ void Sbar_TeamOverlay (void)
team_t *tm; team_t *tm;
int plow, phigh, pavg; int plow, phigh, pavg;
int pw,ph; int pw,ph;
playerview_t *pv = r_refdef.playerview;
vrect_t gr = r_refdef.grect;
int rank_width = 320-32*2; int rank_width = 320-32*2;
int startx; int startx;
int trackplayer; int trackplayer;
@ -3027,11 +3023,11 @@ void Sbar_TeamOverlay (void)
// request new ping times every two second // request new ping times every two second
if (!cl.teamplay) if (!cl.teamplay)
{ {
Sbar_DeathmatchOverlay(0); Sbar_DeathmatchOverlay(pv, 0);
return; return;
} }
y = 0; y = gr.y;
if (scr_scoreboard_drawtitle.ival) if (scr_scoreboard_drawtitle.ival)
{ {
@ -3039,12 +3035,12 @@ void Sbar_TeamOverlay (void)
if (pic && R_GetShaderSizes(pic, &pw, &ph, false)>0) if (pic && R_GetShaderSizes(pic, &pw, &ph, false)>0)
{ {
k = (pw * 24) / ph; k = (pw * 24) / ph;
R2D_ScalePic ((vid.width-k)/2, 0, k, 24, pic); R2D_ScalePic (gr.x+(gr.width-k)/2, y, k, 24, pic);
} }
y += 24; y += 24;
} }
x = l = (vid.width - 320)/2 + 36; x = l = gr.x + (gr.width - 320)/2 + 36;
startx = x; startx = x;
@ -3099,7 +3095,7 @@ void Sbar_TeamOverlay (void)
// sort the teams // sort the teams
Sbar_SortTeams(pv); Sbar_SortTeams(pv);
if (cl.spectator) if (pv->spectator)
trackplayer = Cam_TrackNum(pv); trackplayer = Cam_TrackNum(pv);
else else
trackplayer = pv->playernum; trackplayer = pv->playernum;
@ -3184,7 +3180,7 @@ void Sbar_TeamOverlay (void)
} }
else else
y += 8; y += 8;
Sbar_DeathmatchOverlay(y); Sbar_DeathmatchOverlay(pv, y-gr.y);
} }
/* /*
@ -3287,7 +3283,7 @@ enum
}; };
#define ADDCOLUMN(id) showcolumns |= (1<<id) #define ADDCOLUMN(id) showcolumns |= (1<<id)
void Sbar_DeathmatchOverlay (int start) void Sbar_DeathmatchOverlay (playerview_t *pv, int start)
{ {
mpic_t *pic; mpic_t *pic;
int i, k; int i, k;
@ -3299,7 +3295,6 @@ void Sbar_DeathmatchOverlay (int start)
int skip = 10; int skip = 10;
int showcolumns; int showcolumns;
int startx, rank_width; int startx, rank_width;
playerview_t *pv = r_refdef.playerview;
vrect_t gr = r_refdef.grect; vrect_t gr = r_refdef.grect;
int namesize = (cl.teamplay ? 12*8 : 16*8); int namesize = (cl.teamplay ? 12*8 : 16*8);
@ -3753,8 +3748,8 @@ static void Sbar_MiniDeathmatchOverlay (playerview_t *pv)
Font_BeginString(font_default, x+24, y, &px, &py); Font_BeginString(font_default, x+24, y, &px, &py);
Font_DrawChar ( px, py, CON_WHITEMASK, num[2] | 0xe000); Font_DrawChar ( px, py, CON_WHITEMASK, num[2] | 0xe000);
if ((cl.spectator && k == pv->cam_spec_track && pv->cam_state != CAM_FREECAM) || if ((pv->spectator && k == pv->cam_spec_track && pv->cam_state != CAM_FREECAM) ||
(!cl.spectator && k == pv->playernum)) (!pv->spectator && k == pv->playernum))
{ {
Font_BeginString(font_default, x, y, &px, &py); Font_BeginString(font_default, x, y, &px, &py);
Font_DrawChar ( px, py, CON_WHITEMASK, 16 | 0xe000); Font_DrawChar ( px, py, CON_WHITEMASK, 16 | 0xe000);
@ -3812,12 +3807,11 @@ static void Sbar_MiniDeathmatchOverlay (playerview_t *pv)
} }
void Sbar_CoopIntermission (void) void Sbar_CoopIntermission (playerview_t *pv)
{ {
mpic_t *pic; mpic_t *pic;
int dig; int dig;
int num; int num;
int pnum = 0; //should be the same for all players.
sbar_rect.width = vid.width; sbar_rect.width = vid.width;
sbar_rect.height = vid.height; sbar_rect.height = vid.height;
@ -3842,13 +3836,13 @@ void Sbar_CoopIntermission (void)
R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 278,(sbar_rect.height - 200)/2 + 64, 16, 24, sb_nums[0][num%10]); R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 278,(sbar_rect.height - 200)/2 + 64, 16, 24, sb_nums[0][num%10]);
//it is assumed that secrits/monsters are going to be constant for any player... //it is assumed that secrits/monsters are going to be constant for any player...
Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 230 - 24*4, (sbar_rect.height - 200)/2 + 104, cl.playerview[pnum].stats[STAT_SECRETS], 4, 0, false); Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 230 - 24*4, (sbar_rect.height - 200)/2 + 104, pv->stats[STAT_SECRETS], 4, 0, false);
R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 230, (sbar_rect.height - 200)/2 + 104, 16, 24, sb_slash); R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 230, (sbar_rect.height - 200)/2 + 104, 16, 24, sb_slash);
Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 254, (sbar_rect.height - 200)/2 + 104, cl.playerview[pnum].stats[STAT_TOTALSECRETS], 4, 0, true); Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 254, (sbar_rect.height - 200)/2 + 104, pv->stats[STAT_TOTALSECRETS], 4, 0, true);
Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 230 - 24*4, (sbar_rect.height - 200)/2 + 144, cl.playerview[pnum].stats[STAT_MONSTERS], 4, 0, false); Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 230 - 24*4, (sbar_rect.height - 200)/2 + 144, pv->stats[STAT_MONSTERS], 4, 0, false);
R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 230,(sbar_rect.height - 200)/2 + 144, 16, 24, sb_slash); R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 230,(sbar_rect.height - 200)/2 + 144, 16, 24, sb_slash);
Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 254, (sbar_rect.height - 200)/2 + 144, cl.playerview[pnum].stats[STAT_TOTALMONSTERS], 4, 0, true); Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 254, (sbar_rect.height - 200)/2 + 144, pv->stats[STAT_TOTALMONSTERS], 4, 0, true);
} }
/* /*
================== ==================
@ -3856,7 +3850,7 @@ Sbar_IntermissionOverlay
================== ==================
*/ */
void Sbar_IntermissionOverlay (void) void Sbar_IntermissionOverlay (playerview_t *pv)
{ {
#ifdef VM_UI #ifdef VM_UI
if (UI_DrawIntermission()>0) if (UI_DrawIntermission()>0)
@ -3866,10 +3860,10 @@ void Sbar_IntermissionOverlay (void)
Sbar_Start(); Sbar_Start();
if (!cls.deathmatch) if (!cls.deathmatch)
Sbar_CoopIntermission(); Sbar_CoopIntermission(pv);
else if (cl.teamplay > 0 && !sb_showscores) else if (cl.teamplay > 0 && !pv->sb_showscores)
Sbar_TeamOverlay (); Sbar_TeamOverlay (pv);
else else
Sbar_DeathmatchOverlay (0); Sbar_DeathmatchOverlay (pv, 0);
} }
#endif #endif

View File

@ -33,12 +33,12 @@ qboolean Sbar_UpdateTeamStatus(struct player_info_s *player, char *status);
void Sbar_Changed (void); void Sbar_Changed (void);
// call whenever any of the client stats represented on the sbar changes // call whenever any of the client stats represented on the sbar changes
qboolean Sbar_ShouldDraw(void); qboolean Sbar_ShouldDraw(playerview_t *pv);
void Sbar_Draw (playerview_t *pv); //uses the current r_refdef.grect void Sbar_Draw (playerview_t *pv); //uses the current r_refdef.grect
void Sbar_DrawScoreboard (void); void Sbar_DrawScoreboard (playerview_t *pv);
// called every frame by screen // called every frame by screen
void Sbar_IntermissionOverlay (void); void Sbar_IntermissionOverlay (playerview_t *pv);
// called each frame after the level has been completed // called each frame after the level has been completed
void Sbar_FinaleOverlay (void); void Sbar_FinaleOverlay (void);

View File

@ -4,10 +4,9 @@
This is based on Jogi's OpenAL support. This is based on Jogi's OpenAL support.
Much of it is stripped, to try and get it clean/compliant. Much of it is stripped, to try and get it clean/compliant.
Missing features: Emscripten/WebAudio is buggy or limited.
FIXME: listener velocity calculations (currently ugly). This means we force distance models and use hacks to avoid bugs in browsers.
FIXME: does not track entity velocities, so no dopler (awkward, quake doesn't move playing sounds at all). We also have no doppler with WebAudio.
FIXME: a capture device would be useful (voice chat).
*/ */
#ifdef AVAIL_OPENAL #ifdef AVAIL_OPENAL

View File

@ -627,7 +627,7 @@ void Validation_Auto_Response(int playernum, char *s)
Validation_Version(); Validation_Version();
versionresponsetime = Sys_DoubleTime() + 5; versionresponsetime = Sys_DoubleTime() + 5;
} }
else if (cl.spectator) else if (cl.playerview[0].spectator)
return; return;
else if (!strncmp(s, "server", 6) && serverresponsetime < Sys_DoubleTime()) //respond to it. else if (!strncmp(s, "server", 6) && serverresponsetime < Sys_DoubleTime()) //respond to it.
{ {

View File

@ -160,7 +160,7 @@ float V_CalcBob (playerview_t *pv, qboolean queryold)
float hspeed, bob; float hspeed, bob;
vec3_t hvel; vec3_t hvel;
if (cl.spectator) if (pv->spectator)
return 0; return 0;
if (cl_bobcycle.value <= 0 || cl.intermissionmode != IM_NONE) if (cl_bobcycle.value <= 0 || cl.intermissionmode != IM_NONE)
@ -1477,9 +1477,9 @@ void V_CalcRefdef (playerview_t *pv)
} }
#ifdef QUAKESTATS #ifdef QUAKESTATS
if (pv->stats[STAT_HEALTH] < 0 && (!cl.spectator || pv->cam_state == CAM_EYECAM) && v_deathtilt.value) // PF_GIB will also set PF_DEAD if (pv->stats[STAT_HEALTH] < 0 && (!pv->spectator || pv->cam_state == CAM_EYECAM) && v_deathtilt.value) // PF_GIB will also set PF_DEAD
{ {
if (!cl.spectator || cl_chasecam.ival) if (!pv->spectator || cl_chasecam.ival)
r_refdef.viewangles[ROLL] = 80*v_deathtilt.value; // dead view angle r_refdef.viewangles[ROLL] = 80*v_deathtilt.value; // dead view angle
} }
else else
@ -1980,7 +1980,7 @@ void R_DrawNameTags(void)
} }
} }
if (((!cl.spectator && !cls.demoplayback) || !scr_autoid.ival) && (!cl.teamplay || !scr_autoid_team.ival)) if (((!r_refdef.playerview->spectator && !cls.demoplayback) || !scr_autoid.ival) && (!cl.teamplay || !scr_autoid_team.ival))
return; return;
if (cls.state != ca_active || !cl.validsequence || cl.intermissionmode != IM_NONE) if (cls.state != ca_active || !cl.validsequence || cl.intermissionmode != IM_NONE)
return; return;
@ -2029,13 +2029,13 @@ void R_DrawNameTags(void)
if (!cl.teamplay || !scr_autoid_team.ival) if (!cl.teamplay || !scr_autoid_team.ival)
isteam = false; isteam = false;
else if ((cl.teamfortress && !cl.spectator) || cls.protocol == CP_NETQUAKE) //teamfortress should go by their colours instead, because spies. primarily this is to allow enemy spies to appear through walls as well as your own team (note that the qc will also need tinfo stuff for tf, to avoid issues with just checking player names). else if ((cl.teamfortress && !r_refdef.playerview->spectator) || cls.protocol == CP_NETQUAKE) //teamfortress should go by their colours instead, because spies. primarily this is to allow enemy spies to appear through walls as well as your own team (note that the qc will also need tinfo stuff for tf, to avoid issues with just checking player names).
isteam = cl.players[i].rbottomcolor == ourcolour; isteam = cl.players[i].rbottomcolor == ourcolour;
else else
isteam = !strcmp(cl.players[i].team, ourteam); isteam = !strcmp(cl.players[i].team, ourteam);
if (!isteam) if (!isteam)
if ((!cl.spectator && !cls.demoplayback) || !scr_autoid.ival) if ((!r_refdef.playerview->spectator && !cls.demoplayback) || !scr_autoid.ival)
continue; //only show our team when playing, too cheaty otherwise. continue; //only show our team when playing, too cheaty otherwise.
SCR_DrawAutoID(nametagorg[i], &cl.players[i], isteam); SCR_DrawAutoID(nametagorg[i], &cl.players[i], isteam);

View File

@ -704,7 +704,8 @@ done:
static char *Skin_To_TFSkin (char *myskin) static char *Skin_To_TFSkin (char *myskin)
{ {
if (!cl.teamfortress || cl.spectator || Q_strncasecmp(myskin, "tf_", 3)) playerview_t *pv = &cl.playerview[SP];
if (!cl.teamfortress || pv->spectator || Q_strncasecmp(myskin, "tf_", 3))
{ {
Q_strncpyz(macro_buf, myskin, sizeof(macro_buf)); Q_strncpyz(macro_buf, myskin, sizeof(macro_buf));
} }
@ -732,9 +733,10 @@ static char *Macro_TF_Skin (void)
//Spike: added these: //Spike: added these:
static char *Macro_ConnectionType (void) static char *Macro_ConnectionType (void)
{ {
playerview_t *pv = &cl.playerview[SP];
if (!cls.state) if (!cls.state)
return "disconnected"; return "disconnected";
if (cl.spectator) if (pv->spectator)
return "spectator"; return "spectator";
return "connected"; return "connected";
} }
@ -878,6 +880,7 @@ static void CountNearbyPlayers(qboolean dead)
player_state_t *state; player_state_t *state;
player_info_t *info; player_info_t *info;
static int lastframecount = -1; static int lastframecount = -1;
playerview_t *pv = &cl.playerview[SP];
if (cls.framecount == lastframecount) if (cls.framecount == lastframecount)
return; return;
@ -885,7 +888,7 @@ static void CountNearbyPlayers(qboolean dead)
vars.numenemies = vars.numfriendlies = 0; vars.numenemies = vars.numfriendlies = 0;
if (!cl.spectator && !dead) if (!pv->spectator && !dead)
vars.numfriendlies++; vars.numfriendlies++;
if (!cl.oldparsecount || !cl.parsecount || cls.state < ca_active) if (!cl.oldparsecount || !cl.parsecount || cls.state < ca_active)
@ -894,7 +897,7 @@ static void CountNearbyPlayers(qboolean dead)
state = cl.inframes[cl.oldparsecount & UPDATE_MASK].playerstate; state = cl.inframes[cl.oldparsecount & UPDATE_MASK].playerstate;
info = cl.players; info = cl.players;
for (i = 0; i < cl.allocated_client_slots; i++, info++, state++) { for (i = 0; i < cl.allocated_client_slots; i++, info++, state++) {
if (i != cl.playerview[SP].playernum && state->messagenum == cl.oldparsecount && !info->spectator && !ISDEAD(state->frame)) { if (i != pv->playernum && state->messagenum == cl.oldparsecount && !info->spectator && !ISDEAD(state->frame)) {
if (cl.teamplay && !strcmp(info->team, TP_PlayerTeam())) if (cl.teamplay && !strcmp(info->team, TP_PlayerTeam()))
vars.numfriendlies++; vars.numfriendlies++;
else else
@ -2183,6 +2186,7 @@ int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr)
int flags; int flags;
player_info_t *player; player_info_t *player;
char *name; char *name;
playerview_t *pv = &cl.playerview[SP];
*offset = 0; *offset = 0;
*plr = NULL; *plr = NULL;
@ -2275,9 +2279,9 @@ int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr)
!strncmp(name, s+1, len)) !strncmp(name, s+1, len))
{ {
// no team messages in teamplay 0, except for our own // no team messages in teamplay 0, except for our own
if (cl.spectator) if (pv->spectator)
{ {
unsigned int track = Cam_TrackNum(&cl.playerview[SP]); unsigned int track = Cam_TrackNum(pv);
if (i == track || ( cl.teamplay && if (i == track || ( cl.teamplay &&
!strcmp(cl.players[track].team, player->team)) ) !strcmp(cl.players[track].team, player->team)) )
{ {
@ -2286,8 +2290,8 @@ int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr)
} }
else else
{ {
if (i == cl.playerview[SP].playernum || ( cl.teamplay && if (i == pv->playernum || ( cl.teamplay &&
!strcmp(cl.players[cl.playerview[SP].playernum].team, player->team)) ) !strcmp(cl.players[pv->playernum].team, player->team)) )
{ {
flags |= TPM_TEAM; flags |= TPM_TEAM;
} }
@ -2814,8 +2818,9 @@ static qboolean CheckTrigger (void)
int i, count; int i, count;
player_info_t *player; player_info_t *player;
char *myteam; char *myteam;
playerview_t *pv = &cl.playerview[SP];
if (cl.spectator) if (pv->spectator)
return false; return false;
if (tp_forceTriggers.ival) if (tp_forceTriggers.ival)
@ -2825,9 +2830,9 @@ static qboolean CheckTrigger (void)
return false; return false;
count = 0; count = 0;
myteam = cl.players[cl.playerview[SP].playernum].team; myteam = cl.players[pv->playernum].team;
for (i = 0, player= cl.players; i < cl.allocated_client_slots; i++, player++) { for (i = 0, player= cl.players; i < cl.allocated_client_slots; i++, player++) {
if (player->name[0] && !player->spectator && i != cl.playerview[SP].playernum && !strcmp(player->team, myteam)) if (player->name[0] && !player->spectator && i != pv->playernum && !strcmp(player->team, myteam))
count++; count++;
} }
@ -2890,13 +2895,14 @@ static void TP_ItemTaken (char *s, int flag, vec3_t org, int entnum, item_t *ite
void TP_ParsePlayerInfo(player_state_t *oldstate, player_state_t *state, player_info_t *info) void TP_ParsePlayerInfo(player_state_t *oldstate, player_state_t *state, player_info_t *info)
{ {
#ifndef QUAKETC #ifndef QUAKETC
playerview_t *pv = &cl.playerview[SP];
// if (TP_NeedRefreshSkins()) // if (TP_NeedRefreshSkins())
// { // {
// if ((state->effects & (EF_BLUE|EF_RED) ) != (oldstate->effects & (EF_BLUE|EF_RED))) // if ((state->effects & (EF_BLUE|EF_RED) ) != (oldstate->effects & (EF_BLUE|EF_RED)))
// TP_RefreshSkin(info - cl.players); // TP_RefreshSkin(info - cl.players);
// } // }
if (!cl.spectator && cl.teamplay && strcmp(info->team, TP_PlayerTeam())) if (!pv->spectator && cl.teamplay && strcmp(info->team, TP_PlayerTeam()))
{ {
qboolean eyes; qboolean eyes;
@ -2915,11 +2921,11 @@ void TP_ParsePlayerInfo(player_state_t *oldstate, player_state_t *state, player_
vars.enemy_powerups |= TP_RING; vars.enemy_powerups |= TP_RING;
} }
} }
if (!cl.spectator && !cl.teamfortress && info - cl.players == cl.playerview[SP].playernum) if (!pv->spectator && !cl.teamfortress && info - cl.players == pv->playernum)
{ {
if ((state->effects & (QWEF_FLAG1|QWEF_FLAG2)) && !(oldstate->effects & (QWEF_FLAG1|QWEF_FLAG2))) if ((state->effects & (QWEF_FLAG1|QWEF_FLAG2)) && !(oldstate->effects & (QWEF_FLAG1|QWEF_FLAG2)))
{ {
ExecTookTrigger_ (tp_name_flag.string, it_flag, cl.inframes[cl.validsequence & UPDATE_MASK].playerstate[cl.playerview[SP].playernum].origin); ExecTookTrigger_ (tp_name_flag.string, it_flag, cl.inframes[cl.validsequence & UPDATE_MASK].playerstate[pv->playernum].origin);
} }
else if (!(state->effects & (QWEF_FLAG1|QWEF_FLAG2)) && (oldstate->effects & (QWEF_FLAG1|QWEF_FLAG2))) else if (!(state->effects & (QWEF_FLAG1|QWEF_FLAG2)) && (oldstate->effects & (QWEF_FLAG1|QWEF_FLAG2)))
{ {
@ -2935,8 +2941,9 @@ void TP_CheckPickupSound (char *s, vec3_t org, int seat)
#ifndef QUAKETC #ifndef QUAKETC
int entnum; int entnum;
item_t *item; item_t *item;
playerview_t *pv = &cl.playerview[seat];
//if we're spectating, we don't want to do any actual triggers, so pretend it was someone else. //if we're spectating, we don't want to do any actual triggers, so pretend it was someone else.
if (cl.spectator) if (pv->spectator)
seat = -1; seat = -1;
//FIXME: on items/itembk2.wav kill relevant item timer. //FIXME: on items/itembk2.wav kill relevant item timer.
@ -2992,17 +2999,17 @@ more:
if (vars.stat_framecounts[STAT_ITEMS] == cls.framecount) if (vars.stat_framecounts[STAT_ITEMS] == cls.framecount)
{ {
if (vars.items & ~vars.olditems & IT_LIGHTNING) if (vars.items & ~vars.olditems & IT_LIGHTNING)
TP_ItemTaken (tp_name_lg.string, it_lg, cl.playerview[SP].simorg, entnum, item, seat); TP_ItemTaken (tp_name_lg.string, it_lg, pv->simorg, entnum, item, seat);
else if (vars.items & ~vars.olditems & IT_ROCKET_LAUNCHER) else if (vars.items & ~vars.olditems & IT_ROCKET_LAUNCHER)
TP_ItemTaken (tp_name_rl.string, it_rl, cl.playerview[SP].simorg, entnum, item, seat); TP_ItemTaken (tp_name_rl.string, it_rl, pv->simorg, entnum, item, seat);
else if (vars.items & ~vars.olditems & IT_GRENADE_LAUNCHER) else if (vars.items & ~vars.olditems & IT_GRENADE_LAUNCHER)
TP_ItemTaken (tp_name_gl.string, it_gl, cl.playerview[SP].simorg, entnum, item, seat); TP_ItemTaken (tp_name_gl.string, it_gl, pv->simorg, entnum, item, seat);
else if (vars.items & ~vars.olditems & IT_SUPER_NAILGUN) else if (vars.items & ~vars.olditems & IT_SUPER_NAILGUN)
TP_ItemTaken (tp_name_sng.string, it_sng, cl.playerview[SP].simorg, entnum, item, seat); TP_ItemTaken (tp_name_sng.string, it_sng, pv->simorg, entnum, item, seat);
else if (vars.items & ~vars.olditems & IT_NAILGUN) else if (vars.items & ~vars.olditems & IT_NAILGUN)
TP_ItemTaken (tp_name_ng.string, it_ng, cl.playerview[SP].simorg, entnum, item, seat); TP_ItemTaken (tp_name_ng.string, it_ng, pv->simorg, entnum, item, seat);
else if (vars.items & ~vars.olditems & IT_SUPER_SHOTGUN) else if (vars.items & ~vars.olditems & IT_SUPER_SHOTGUN)
TP_ItemTaken (tp_name_ssg.string, it_ssg, cl.playerview[SP].simorg, entnum, item, seat); TP_ItemTaken (tp_name_ssg.string, it_ssg, pv->simorg, entnum, item, seat);
} }
} }
return; return;
@ -3020,11 +3027,11 @@ more:
TP_ItemTaken (item->cvar->string, item->itemflag, org, entnum, item, seat); TP_ItemTaken (item->cvar->string, item->itemflag, org, entnum, item, seat);
else if (seat >= 0) else if (seat >= 0)
{ {
if (armor_updated && cl.playerview[SP].stats[STAT_ARMOR] == 100) if (armor_updated && pv->stats[STAT_ARMOR] == 100)
TP_ItemTaken (tp_name_ga.string, it_ga, org, entnum, NULL, seat); TP_ItemTaken (tp_name_ga.string, it_ga, org, entnum, NULL, seat);
else if (armor_updated && cl.playerview[SP].stats[STAT_ARMOR] == 150) else if (armor_updated && pv->stats[STAT_ARMOR] == 150)
TP_ItemTaken (tp_name_ya.string, it_ya, org, entnum, NULL, seat); TP_ItemTaken (tp_name_ya.string, it_ya, org, entnum, NULL, seat);
else if (armor_updated && cl.playerview[SP].stats[STAT_ARMOR] == 200) else if (armor_updated && pv->stats[STAT_ARMOR] == 200)
TP_ItemTaken (tp_name_ra.string, it_ra, org, entnum, NULL, seat); TP_ItemTaken (tp_name_ra.string, it_ra, org, entnum, NULL, seat);
} }
return; return;
@ -3216,6 +3223,7 @@ static void TP_FindPoint (void)
item_vis_t visitem; item_vis_t visitem;
extern cvar_t v_viewheight; extern cvar_t v_viewheight;
int oldskip = pmove.skipent; int oldskip = pmove.skipent;
playerview_t *pv = &cl.playerview[SP];
if (vars.pointtime == realtime) if (vars.pointtime == realtime)
return; return;
@ -3223,11 +3231,11 @@ static void TP_FindPoint (void)
if (!cl.validsequence) if (!cl.validsequence)
goto nothing; goto nothing;
pmove.skipent = cl.playerview[SP].viewentity; pmove.skipent = pv->viewentity;
ang[0] = cl.playerview[SP].viewangles[0]; ang[1] = cl.playerview[SP].viewangles[1]; ang[2] = 0; ang[0] = pv->viewangles[0]; ang[1] = pv->viewangles[1]; ang[2] = 0;
AngleVectors (ang, visitem.forward, visitem.right, visitem.up); AngleVectors (ang, visitem.forward, visitem.right, visitem.up);
VectorCopy (cl.playerview[SP].simorg, visitem.vieworg); VectorCopy (pv->simorg, visitem.vieworg);
visitem.vieworg[2] += 22 + (v_viewheight.value ? bound (-7, v_viewheight.value, 4) : 0); visitem.vieworg[2] += 22 + (v_viewheight.value ? bound (-7, v_viewheight.value, 4) : 0);
pointflags_dmm = pointflags; pointflags_dmm = pointflags;
@ -3274,7 +3282,7 @@ static void TP_FindPoint (void)
info = cl.players; info = cl.players;
for (j = 0; j < cl.allocated_client_slots; j++, info++, state++) for (j = 0; j < cl.allocated_client_slots; j++, info++, state++)
{ {
if (state->messagenum != cl.parsecount || j == cl.playerview[SP].playernum || info->spectator) if (state->messagenum != cl.parsecount || j == pv->playernum || info->spectator)
continue; continue;
if ( if (
@ -3325,7 +3333,7 @@ static void TP_FindPoint (void)
if (eyes) if (eyes)
name = tp_name_eyes.string; //duck on 2night2 name = tp_name_eyes.string; //duck on 2night2
else if (cl.spectator) else if (pv->spectator)
name = bestinfo->name; name = bestinfo->name;
else if (teammate) else if (teammate)
name = tp_name_teammate.string[0] ? tp_name_teammate.string : "teammate"; name = tp_name_teammate.string[0] ? tp_name_teammate.string : "teammate";
@ -3341,7 +3349,7 @@ static void TP_FindPoint (void)
if (eyes) if (eyes)
name = tp_name_eyes.string; name = tp_name_eyes.string;
else if (cl.spectator || (teammate && !tp_name_teammate.string[0])) else if (pv->spectator || (teammate && !tp_name_teammate.string[0]))
name = bestinfo->name; name = bestinfo->name;
else else
name = teammate ? tp_name_teammate.string : tp_name_enemy.string; name = teammate ? tp_name_teammate.string : tp_name_enemy.string;
@ -3390,6 +3398,7 @@ void TP_UpdateAutoStatus(void)
char newstatusbuf[sizeof(vars.autoteamstatus)]; char newstatusbuf[sizeof(vars.autoteamstatus)];
char *newstatus; char *newstatus;
int level; int level;
playerview_t *pv = &cl.playerview[SP];
if (vars.autoteamstatus_time > realtime || !*tp_autostatus.string) if (vars.autoteamstatus_time > realtime || !*tp_autostatus.string)
return; return;
@ -3415,7 +3424,7 @@ void TP_UpdateAutoStatus(void)
if (tp_autostatus.latched_string) if (tp_autostatus.latched_string)
return; return;
if (cl.spectator) //don't spam as spectators, that's just silly if (pv->spectator) //don't spam as spectators, that's just silly
return; return;
if (!cl.teamplay) //don't spam in deathmatch, that's just pointless if (!cl.teamplay) //don't spam in deathmatch, that's just pointless
return; return;
@ -3427,6 +3436,7 @@ void TP_UpdateAutoStatus(void)
void TP_StatChanged (int stat, int value) void TP_StatChanged (int stat, int value)
{ {
#ifdef QUAKESTATS #ifdef QUAKESTATS
playerview_t *pv = &cl.playerview[SP];
int i; int i;
if (stat == STAT_HEALTH) if (stat == STAT_HEALTH)
{ {
@ -3437,14 +3447,14 @@ void TP_StatChanged (int stat, int value)
// we just respawned // we just respawned
vars.respawntrigger_time = realtime; vars.respawntrigger_time = realtime;
if (!cl.spectator && CountTeammates()) if (!pv->spectator && CountTeammates())
TP_ExecTrigger ("f_respawn", false); TP_ExecTrigger ("f_respawn", false);
} }
} }
else if (vars.health > 0) else if (vars.health > 0)
{ // We have just died { // We have just died
vars.droppedweapon = cl.playerview[SP].stats[STAT_ACTIVEWEAPON]; vars.droppedweapon = pv->stats[STAT_ACTIVEWEAPON];
vars.deathtrigger_time = realtime; vars.deathtrigger_time = realtime;
strcpy (vars.lastdeathloc, Macro_Location()); strcpy (vars.lastdeathloc, Macro_Location());
@ -3453,9 +3463,9 @@ void TP_StatChanged (int stat, int value)
vars.last_numenemies = vars.numenemies; vars.last_numenemies = vars.numenemies;
vars.last_numfriendlies = vars.numfriendlies; vars.last_numfriendlies = vars.numfriendlies;
if (!cl.spectator && CountTeammates()) if (!pv->spectator && CountTeammates())
{ {
if (cl.teamfortress && (cl.playerview[SP].stats[STAT_ITEMS] & (IT_KEY1|IT_KEY2)) if (cl.teamfortress && (pv->stats[STAT_ITEMS] & (IT_KEY1|IT_KEY2))
&& Cmd_AliasExist("f_flagdeath", RESTRICT_LOCAL)) && Cmd_AliasExist("f_flagdeath", RESTRICT_LOCAL))
TP_ExecTrigger ("f_flagdeath", false); TP_ExecTrigger ("f_flagdeath", false);
else else
@ -3469,14 +3479,14 @@ void TP_StatChanged (int stat, int value)
i = value &~ vars.items; i = value &~ vars.items;
if (i & (IT_KEY1|IT_KEY2)) { if (i & (IT_KEY1|IT_KEY2)) {
if (cl.teamfortress && !cl.spectator) if (cl.teamfortress && !pv->spectator)
{ {
ExecTookTrigger_ (tp_name_flag.string, it_flag, ExecTookTrigger_ (tp_name_flag.string, it_flag,
cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[cl.playerview[SP].playernum].origin); cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[pv->playernum].origin);
} }
} }
if (!cl.spectator && cl.teamfortress && ~value & vars.items & (IT_KEY1|IT_KEY2)) if (!pv->spectator && cl.teamfortress && ~value & vars.items & (IT_KEY1|IT_KEY2))
{ {
vars.lastdrop_time = realtime; vars.lastdrop_time = realtime;
strcpy (vars.lastdroploc, Macro_Location()); strcpy (vars.lastdroploc, Macro_Location());
@ -3487,9 +3497,9 @@ void TP_StatChanged (int stat, int value)
} }
else if (stat == STAT_ACTIVEWEAPON) else if (stat == STAT_ACTIVEWEAPON)
{ {
if (cl.playerview[SP].stats[STAT_ACTIVEWEAPON] != vars.activeweapon) if (pv->stats[STAT_ACTIVEWEAPON] != vars.activeweapon)
TP_ExecTrigger ("f_weaponchange", false); TP_ExecTrigger ("f_weaponchange", false);
vars.activeweapon = cl.playerview[SP].stats[STAT_ACTIVEWEAPON]; vars.activeweapon = pv->stats[STAT_ACTIVEWEAPON];
} }
#endif #endif
vars.stat_framecounts[stat] = cls.framecount; vars.stat_framecounts[stat] = cls.framecount;
@ -3709,6 +3719,7 @@ void TP_Init (void)
qboolean TP_SuppressMessage(char *buf) { qboolean TP_SuppressMessage(char *buf) {
char *s; char *s;
playerview_t *pv = &cl.playerview[SP];
for (s = buf; *s && *s != 0x7f; s++) for (s = buf; *s && *s != 0x7f; s++)
; ;
@ -3717,7 +3728,7 @@ qboolean TP_SuppressMessage(char *buf) {
*s++ = '\n'; *s++ = '\n';
*s++ = 0; *s++ = 0;
return (!cls.demoplayback && !cl.spectator && *s - 'A' == cl.playerview[SP].playernum); return (!cls.demoplayback && !pv->spectator && *s - 'A' == pv->playernum);
} }
return false; return false;
} }
@ -3728,6 +3739,7 @@ void CL_Say (qboolean team, char *extra)
{ {
extern cvar_t cl_fakename; extern cvar_t cl_fakename;
char text[2048], sendtext[2048], *s; char text[2048], sendtext[2048], *s;
playerview_t *pv = &cl.playerview[SP];
if (Cmd_Argc() < 2) if (Cmd_Argc() < 2)
{ {
@ -3748,7 +3760,7 @@ void CL_Say (qboolean team, char *extra)
Q_strncpyz (text, TP_ParseFunChars (s), sizeof(text)); Q_strncpyz (text, TP_ParseFunChars (s), sizeof(text));
sendtext[0] = 0; sendtext[0] = 0;
if (team && !cl.spectator && cl_fakename.string[0] && if (team && !pv->spectator && cl_fakename.string[0] &&
!strchr(s, '\x0d') /* explicit $\ in message overrides cl_fakename */) !strchr(s, '\x0d') /* explicit $\ in message overrides cl_fakename */)
{ {
char buf[1024]; char buf[1024];
@ -3803,7 +3815,7 @@ void CL_Say (qboolean team, char *extra)
if (team) if (team)
plrflags |= 2; plrflags |= 2;
CL_PrintChat(&cl.players[cl.playerview[SP].playernum], text, plrflags); CL_PrintChat(&cl.players[pv->playernum], text, plrflags);
} }
//strip out the extra markup //strip out the extra markup
@ -3831,7 +3843,7 @@ void CL_Say (qboolean team, char *extra)
*d = '\0'; *d = '\0';
//mark the message so that we ignore it when we get the echo. //mark the message so that we ignore it when we get the echo.
strlcat (sendtext, va("\x7f!%c", 'A'+cl.playerview[SP].playernum), sizeof(sendtext)); strlcat (sendtext, va("\x7f!%c", 'A'+pv->playernum), sizeof(sendtext));
} }
#ifdef Q3CLIENT #ifdef Q3CLIENT

View File

@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// release version // release version
#define FTE_VER_MAJOR 1 #define FTE_VER_MAJOR 1
#define FTE_VER_MINOR 5 #define FTE_VER_MINOR 6
#if defined(__APPLE__) && defined(__MACH__) #if defined(__APPLE__) && defined(__MACH__)
#define MACOSX #define MACOSX
@ -281,8 +281,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// #define HLCLIENT 7 //we can run HL gamecode (not protocol compatible, set to 6 or 7) // #define HLCLIENT 7 //we can run HL gamecode (not protocol compatible, set to 6 or 7)
// #define HLSERVER 140 //we can run HL gamecode (not protocol compatible, set to 138 or 140) // #define HLSERVER 140 //we can run HL gamecode (not protocol compatible, set to 138 or 140)
#define NQPROT //server and client are capable of using quake1/netquake protocols. (qw is still prefered. uses the command 'nqconnect') #define NQPROT //server and client are capable of using quake1/netquake protocols. (qw is still prefered. uses the command 'nqconnect')
#define WEBSERVER //http/ftp servers // #define WEBSERVER //http server
#define WEBCLIENT //http/ftp clients. #define FTPSERVER //ftp server
#define WEBCLIENT //http clients.
#define RUNTIMELIGHTING //calculate lit/lux files the first time the map is loaded and doesn't have a loadable lit. #define RUNTIMELIGHTING //calculate lit/lux files the first time the map is loaded and doesn't have a loadable lit.
// #define QTERM //qterm... adds a console command that allows running programs from within quake - bit like xterm. // #define QTERM //qterm... adds a console command that allows running programs from within quake - bit like xterm.
#define CL_MASTER //query master servers and stuff for a dynamic server listing. #define CL_MASTER //query master servers and stuff for a dynamic server listing.

View File

@ -1100,7 +1100,7 @@ static vfsfile_t *QDECL FSZIP_OpenVFS(searchpathfuncs_t *handle, flocation_t *lo
if (flags & ZFL_DEFLATED) if (flags & ZFL_DEFLATED)
{ {
#ifdef ZIPCRYPT #ifdef ZIPCRYPT
//FIXME: Cvar_Get is not threadsafe. //FIXME: Cvar_Get is not threadsafe, and nor is accessing the cvar...
char *password = (flags & ZFL_WEAKENCRYPT)?Cvar_Get("fs_zip_password", "thisispublic", 0, "Filesystem")->string:NULL; char *password = (flags & ZFL_WEAKENCRYPT)?Cvar_Get("fs_zip_password", "thisispublic", 0, "Filesystem")->string:NULL;
#else #else
char *password = NULL; char *password = NULL;

View File

@ -95,9 +95,9 @@ typedef int (VARGS gnutls_certificate_verify_function)(gnutls_session_t session)
#else #else
#include <gnutls/gnutls.h> #include <gnutls/gnutls.h>
#if GNUTLS_VERSION_MAJOR >= 3 && defined(HAVE_DTLS) #if GNUTLS_VERSION_MAJOR >= 3 && defined(HAVE_DTLS)
#include <gnutls/dtls.h> #include <gnutls/dtls.h>
#else #else
#undef HAVE_DTLS #undef HAVE_DTLS
#endif #endif
#define gnutls_connection_end_t unsigned int #define gnutls_connection_end_t unsigned int

View File

@ -1866,10 +1866,11 @@ int Plug_ConnectionlessClientPacket(char *buffer, int size)
void Plug_SBar(playerview_t *pv) void Plug_SBar(playerview_t *pv)
{ {
#ifdef QUAKEHUD #ifdef QUAKEHUD
extern qboolean sb_showscores, sb_showteamscores; #define sb_showscores pv->sb_showscores
#define sb_showteamscores pv->sb_showteamscores
#else #else
#define sb_showscores 0 #define sb_showscores 0
#define sb_showteamscores 0 #define sb_showteamscores 0
#endif #endif
plugin_t *oc=currentplug; plugin_t *oc=currentplug;
@ -1877,7 +1878,7 @@ void Plug_SBar(playerview_t *pv)
int cleared = false; int cleared = false;
int hudmode; int hudmode;
if (!Sbar_ShouldDraw()) if (!Sbar_ShouldDraw(pv))
{ {
SCR_TileClear (0); SCR_TileClear (0);
return; return;
@ -1935,9 +1936,9 @@ void Plug_SBar(playerview_t *pv)
} }
} }
if (!(ret & 2) && pv == cl.playerview) if (!(ret & 2))
{ {
Sbar_DrawScoreboard(); Sbar_DrawScoreboard(pv);
} }

View File

@ -279,10 +279,15 @@ void D3D11_UploadLightmap(lightmapinfo_t *lm)
mips.mip[0].width = lm->width; mips.mip[0].width = lm->width;
mips.mip[0].height = lm->height; mips.mip[0].height = lm->height;
mips.mip[0].datasize = lm->width*lm->height*4; mips.mip[0].datasize = lm->width*lm->height*4;
if (lightmap_bgra) switch (lightmap_fmt)
{
case TF_BGRA32:
mips.encoding = PTI_BGRX8; mips.encoding = PTI_BGRX8;
else break;
mips.encoding = PTI_RGBX8; case TF_RGBA32:
mips.encoding = PTI_RGBX8;
break;
}
mips.mipcount = 1; mips.mipcount = 1;
D3D11_LoadTextureMips(tex, &mips); D3D11_LoadTextureMips(tex, &mips);
tex->width = lm->width; tex->width = lm->width;

View File

@ -886,7 +886,7 @@ qboolean D3D8_VID_ApplyGammaRamps (unsigned int gammarampsize, unsigned short *
IDirect3DDevice8_SetGammaRamp(pD3DDev8, D3DSGR_NO_CALIBRATION, (D3DGAMMARAMP *)ramps); IDirect3DDevice8_SetGammaRamp(pD3DDev8, D3DSGR_NO_CALIBRATION, (D3DGAMMARAMP *)ramps);
return true; return true;
} }
static char *(D3D8_VID_GetRGBInfo) (int *truevidwidth, int *truevidheight, enum uploadfmt *fmt) static char *(D3D8_VID_GetRGBInfo) (int *bytestride, int *truevidwidth, int *truevidheight, enum uploadfmt *fmt)
{ {
//FIXME: no screenshots //FIXME: no screenshots
return NULL; return NULL;
@ -921,6 +921,7 @@ static char *(D3D8_VID_GetRGBInfo) (int *truevidwidth, int *truevidheight, enu
*fmt = TF_RGB24; *fmt = TF_RGB24;
// read surface rect and convert 32 bgra to 24 rgb and flip // read surface rect and convert 32 bgra to 24 rgb and flip
//FIXME: shouldn't need to convert+flip any more. just return it as upside-down bgra or whatever
c = desc.Width*desc.Height*3; c = desc.Width*desc.Height*3;
p = (qbyte *)rect.pBits; p = (qbyte *)rect.pBits;
@ -935,6 +936,7 @@ static char *(D3D8_VID_GetRGBInfo) (int *truevidwidth, int *truevidheight, enu
p += rect.Pitch; p += rect.Pitch;
} }
*bytestride = desc.Width*3;
*truevidwidth = desc.Width; *truevidwidth = desc.Width;
*truevidheight = desc.Height; *truevidheight = desc.Height;
} }

View File

@ -67,6 +67,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iqm", "..\..\iqm\iqm.vcproj
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmake", "gmake.vcproj", "{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmake", "gmake.vcproj", "{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "terrorgen", "..\..\plugins\terrorgen\terrorgen.vcproj", "{1E65A0D3-3371-4602-A69C-53BA389FFBD9}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
D3DDebug|Win32 = D3DDebug|Win32 D3DDebug|Win32 = D3DDebug|Win32
@ -1094,6 +1096,48 @@ Global
{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.VkRelease|Win32.ActiveCfg = Release|Win32 {0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.VkRelease|Win32.ActiveCfg = Release|Win32
{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.VkRelease|Win32.Build.0 = Release|Win32 {0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.VkRelease|Win32.Build.0 = Release|Win32
{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.VkRelease|x64.ActiveCfg = Release|Win32 {0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.VkRelease|x64.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.D3DDebug|Win32.Build.0 = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.D3DDebug|x64.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.D3DRelease|Win32.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.D3DRelease|Win32.Build.0 = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.D3DRelease|x64.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Debug Dedicated Server|Win32.Build.0 = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Debug Dedicated Server|x64.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Debug|Win32.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Debug|Win32.Build.0 = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Debug|x64.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.GLDebug|Win32.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.GLDebug|Win32.Build.0 = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.GLDebug|x64.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.GLRelease|Win32.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.GLRelease|Win32.Build.0 = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.GLRelease|x64.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.MDebug|Win32.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.MDebug|Win32.Build.0 = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.MDebug|x64.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.MinGLDebug|Win32.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.MinGLDebug|Win32.Build.0 = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.MinGLDebug|x64.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.MinGLRelease|Win32.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.MinGLRelease|Win32.Build.0 = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.MinGLRelease|x64.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.MRelease|Win32.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.MRelease|Win32.Build.0 = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.MRelease|x64.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Release Dedicated Server|Win32.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Release Dedicated Server|Win32.Build.0 = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Release Dedicated Server|x64.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Release|Win32.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Release|Win32.Build.0 = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Release|x64.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.VkDebug|Win32.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.VkDebug|Win32.Build.0 = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.VkDebug|x64.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.VkRelease|Win32.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.VkRelease|Win32.Build.0 = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.VkRelease|x64.ActiveCfg = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -1118,6 +1162,7 @@ Global
{F756A3D2-025A-43D4-9829-4074753B774B} = {8CED01C6-2C61-4EC5-90B6-574D9756D773} {F756A3D2-025A-43D4-9829-4074753B774B} = {8CED01C6-2C61-4EC5-90B6-574D9756D773}
{909E9AE0-0617-469C-954E-1ED09367F90E} = {8CED01C6-2C61-4EC5-90B6-574D9756D773} {909E9AE0-0617-469C-954E-1ED09367F90E} = {8CED01C6-2C61-4EC5-90B6-574D9756D773}
{E6CDA919-628B-45BF-A5DB-FB55179D6443} = {8CED01C6-2C61-4EC5-90B6-574D9756D773} {E6CDA919-628B-45BF-A5DB-FB55179D6443} = {8CED01C6-2C61-4EC5-90B6-574D9756D773}
{1E65A0D3-3371-4602-A69C-53BA389FFBD9} = {8CED01C6-2C61-4EC5-90B6-574D9756D773}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
AMDCaProjectFile = C:\Games\Quake\wip\engine\dotnet2005\CodeAnalyst\ftequake.caw AMDCaProjectFile = C:\Games\Quake\wip\engine\dotnet2005\CodeAnalyst\ftequake.caw

View File

@ -4985,20 +4985,15 @@ static void BE_UpdateLightmaps(void)
int lmidx; int lmidx;
int glformat, gltype; int glformat, gltype;
int internalformat = GL_RGBA; int internalformat = GL_RGBA;
switch (lightmap_bytes) switch (lightmap_fmt)
{ {
case 4: case TF_INVALID: return;
glformat = lightmap_bgra?GL_BGRA_EXT:GL_RGBA; default: Sys_Error("Bad lightmap_fmt\n"); return;
gltype = GL_UNSIGNED_INT_8_8_8_8_REV; case TF_BGRA32: glformat = GL_BGRA_EXT; gltype = GL_UNSIGNED_INT_8_8_8_8_REV; break;
break; // case TF_RGBA32: glformat = GL_RGBA; gltype = GL_UNSIGNED_INT_8_8_8_8_REV; break;
case 3: // case TF_BGR24: glformat = GL_BGR_EXT; gltype = GL_UNSIGNED_BYTE; break;
glformat = lightmap_bgra?GL_BGR_EXT:GL_RGB; case TF_RGB24: glformat = GL_RGB; gltype = GL_UNSIGNED_BYTE; break;
gltype = GL_UNSIGNED_BYTE; case TF_LUM8: glformat = GL_LUMINANCE;gltype = GL_UNSIGNED_BYTE; break;
break;
default:
glformat = GL_LUMINANCE;
gltype = GL_UNSIGNED_BYTE;
break;
} }
if (gl_config.gles) if (gl_config.gles)
internalformat = glformat; internalformat = glformat;
@ -5025,16 +5020,12 @@ static void BE_UpdateLightmaps(void)
GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture); GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexImage2D(GL_TEXTURE_2D, 0, internalformat, qglTexImage2D(GL_TEXTURE_2D, 0, internalformat, lm->width, lm->height, 0, glformat, gltype, lm->lightmaps);
lm->width, lm->height, 0, glformat, gltype,
lm->lightmaps);
} }
else else
{ {
GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture); GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture);
qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, t, qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, t, lm->width, b-t, glformat, gltype, lm->lightmaps+t*lm->width*lightmap_bytes);
lm->width, b-t, glformat, gltype,
lm->lightmaps+t *lm->width*lightmap_bytes);
} }
lm->modified = false; lm->modified = false;
lm->rectchange.l = lm->width; lm->rectchange.l = lm->width;

View File

@ -158,11 +158,14 @@ static qboolean QDECL Terr_InitLightmap(hmsection_t *s, qboolean initialise)
if (s->lightmap < 0) if (s->lightmap < 0)
{ {
struct lmsect_s *lms; struct lmsect_s *lms;
if (!hm->unusedlmsects) Sys_LockMutex(com_resourcemutex);
while (!hm->unusedlmsects)
{ {
int lm; int lm;
int i; int i;
Sys_UnlockMutex(com_resourcemutex);
lm = Surf_NewLightmaps(1, SECTTEXSIZE*LMCHUNKS, SECTTEXSIZE*LMCHUNKS, false); lm = Surf_NewLightmaps(1, SECTTEXSIZE*LMCHUNKS, SECTTEXSIZE*LMCHUNKS, false);
Sys_LockMutex(com_resourcemutex);
for (i = 0; i < LMCHUNKS*LMCHUNKS; i++) for (i = 0; i < LMCHUNKS*LMCHUNKS; i++)
{ {
lms = BZ_Malloc(sizeof(*lms)); lms = BZ_Malloc(sizeof(*lms));
@ -184,6 +187,7 @@ static qboolean QDECL Terr_InitLightmap(hmsection_t *s, qboolean initialise)
hm->numunusedlmsects--; hm->numunusedlmsects--;
hm->numusedlmsects++; hm->numusedlmsects++;
Sys_UnlockMutex(com_resourcemutex);
Z_Free(lms); Z_Free(lms);
initialise = true; initialise = true;
@ -2070,6 +2074,9 @@ void Terr_PurgeTerrainModel(model_t *mod, qboolean lightmapsonly, qboolean light
int cx, cy; int cx, cy;
int sx, sy; int sx, sy;
COM_WorkerFullSync(); //should probably be inside the caller or something. make sure there's no loaders still loading lightmaps when lightmaps are going to be nuked.
validatelinks(&hm->recycle); validatelinks(&hm->recycle);
// Con_Printf("PrePurge: %i lm chunks used, %i unused\n", hm->numusedlmsects, hm->numunusedlmsects); // Con_Printf("PrePurge: %i lm chunks used, %i unused\n", hm->numusedlmsects, hm->numunusedlmsects);
@ -2177,6 +2184,7 @@ void Terr_FreeModel(model_t *mod)
hm->entities = n; hm->entities = n;
} }
Sys_DestroyMutex(hm->entitylock); Sys_DestroyMutex(hm->entitylock);
Z_Free(hm->seed);
Z_Free(hm); Z_Free(hm);
mod->terrain = NULL; mod->terrain = NULL;
} }
@ -3015,6 +3023,8 @@ void Terr_DrawTerrainModel (batch_t **batches, entity_t *e)
else else
culldist = 999999999999999.f; culldist = 999999999999999.f;
if (culldist < hm->maxdrawdist)
culldist = hm->maxdrawdist;
if (culldist > r_refdef.maxdist && r_refdef.maxdist>0) if (culldist > r_refdef.maxdist && r_refdef.maxdist>0)
culldist = r_refdef.maxdist; culldist = r_refdef.maxdist;
@ -4828,9 +4838,11 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
G_FLOAT(OFS_RETURN) = 0; G_FLOAT(OFS_RETURN) = 0;
if (!mod || !mod->terrain) if (!mod)
return;
if (!mod->terrain)
{ {
if (mod && mod->loadstate == MLS_LOADING) if (mod->loadstate == MLS_LOADING)
COM_WorkerPartialSync(mod, &mod->loadstate, MLS_LOADING); COM_WorkerPartialSync(mod, &mod->loadstate, MLS_LOADING);
} }
if (mod->loadstate != MLS_LOADED) if (mod->loadstate != MLS_LOADED)
@ -5258,6 +5270,25 @@ void Terr_ParseEntityLump(model_t *mod, heightmap_t *heightmap)
heightmap->culldistance = atof(value); heightmap->culldistance = atof(value);
heightmap->culldistance *= heightmap->culldistance; heightmap->culldistance *= heightmap->culldistance;
} }
else if (!strcmp("drawdist", key))
heightmap->maxdrawdist = atof(value);
else if (!strcmp("seed", key))
{
Z_Free(heightmap->seed);
heightmap->seed = Z_StrDup(value);
}
else if (!strcmp("exterior", key))
{
heightmap->legacyterrain = false;
if (!strcmp(value, "empty") || !strcmp(value, ""))
heightmap->exteriorcontents = FTECONTENTS_EMPTY;
else if (!strcmp(value, "sky"))
heightmap->exteriorcontents = FTECONTENTS_SKY;
else if (!strcmp(value, "lava"))
heightmap->exteriorcontents = FTECONTENTS_LAVA;
else //if (!strcmp(value, "solid"))
heightmap->exteriorcontents = FTECONTENTS_SOLID;
}
else if (!strcmp("skybox", key)) else if (!strcmp("skybox", key))
Q_strncpyz(heightmap->skyname, value, sizeof(heightmap->skyname)); Q_strncpyz(heightmap->skyname, value, sizeof(heightmap->skyname));
else if (!strcmp("tiles", key)) else if (!strcmp("tiles", key))
@ -5569,69 +5600,65 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e)
in = br->faces[j].lightdata; in = br->faces[j].lightdata;
out = lm->lightmaps + (br->faces[j].lmbase[1] * lm->width + br->faces[j].lmbase[0]) * lightmap_bytes; out = lm->lightmaps + (br->faces[j].lmbase[1] * lm->width + br->faces[j].lmbase[0]) * lightmap_bytes;
if (lightmap_bytes == 4) switch(lightmap_fmt)
{ {
if (lightmap_bgra) default:
Sys_Error("Bad lightmap_fmt\n");
break;
case TF_BGRA32:
for (t = 0; t < br->faces[j].lmextents[1]; t++)
{ {
for (t = 0; t < br->faces[j].lmextents[1]; t++) for (s = 0; s < br->faces[j].lmextents[0]; s++)
{ {
for (s = 0; s < br->faces[j].lmextents[0]; s++) *out++ = in[2];
{ *out++ = in[1];
*out++ = in[2]; *out++ = in[0];
*out++ = in[1]; *out++ = 0xff;
*out++ = in[0]; in+=3;
*out++ = 0xff;
in+=3;
}
out += (lm->width - br->faces[j].lmextents[0]) * 4;
} }
out += (lm->width - br->faces[j].lmextents[0]) * 4;
} }
else break;
/*case TF_RGBA32:
for (t = 0; t < br->faces[j].lmextents[1]; t++)
{ {
for (t = 0; t < br->faces[j].lmextents[1]; t++) for (s = 0; s < br->faces[j].lmextents[0]; s++)
{ {
for (s = 0; s < br->faces[j].lmextents[0]; s++) *out++ = in[0];
{ *out++ = in[1];
*out++ = in[0]; *out++ = in[2];
*out++ = in[1]; *out++ = 0xff;
*out++ = in[2]; in+=3;
*out++ = 0xff;
in+=3;
}
out += (lm->width - br->faces[j].lmextents[0]) * 4;
} }
out += (lm->width - br->faces[j].lmextents[0]) * 4;
} }
} break;*/
else if (lightmap_bytes == 3) /*case TF_BGR24:
{ for (t = 0; t < br->faces[j].lmextents[1]; t++)
if (lightmap_bgra)
{ {
for (t = 0; t < br->faces[j].lmextents[1]; t++) for (s = 0; s < br->faces[j].lmextents[0]; s++)
{ {
for (s = 0; s < br->faces[j].lmextents[0]; s++) *out++ = in[2];
{ *out++ = in[1];
*out++ = in[2]; *out++ = in[0];
*out++ = in[1]; in+=3;
*out++ = in[0];
in+=3;
}
out += (lm->width - br->faces[j].lmextents[0]) * 3;
} }
out += (lm->width - br->faces[j].lmextents[0]) * 3;
} }
else break;*/
case TF_RGB24:
for (t = 0; t < br->faces[j].lmextents[1]; t++)
{ {
for (t = 0; t < br->faces[j].lmextents[1]; t++) for (s = 0; s < br->faces[j].lmextents[0]; s++)
{ {
for (s = 0; s < br->faces[j].lmextents[0]; s++) *out++ = in[0];
{ *out++ = in[1];
*out++ = in[0]; *out++ = in[2];
*out++ = in[1]; in+=3;
*out++ = in[2];
in+=3;
}
out += (lm->width - br->faces[j].lmextents[0]) * 3;
} }
out += (lm->width - br->faces[j].lmextents[0]) * 3;
} }
break;
} }
} }
} }
@ -6884,7 +6911,7 @@ void Terr_WriteMapFile(vfsfile_t *file, model_t *mod)
heightmap_t *hm; heightmap_t *hm;
hm = mod->terrain; hm = mod->terrain;
if (hm && hm->exteriorcontents != FTECONTENTS_EMPTY) if (hm && hm->legacyterrain)
VFS_WRITE(file, "terrain\n", 8); VFS_WRITE(file, "terrain\n", 8);
start = entities; start = entities;
@ -7355,7 +7382,7 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
qboolean QDECL Terr_LoadTerrainModel (model_t *mod, void *buffer, size_t bufsize) qboolean QDECL Terr_LoadTerrainModel (model_t *mod, void *buffer, size_t bufsize)
{ {
int exterior = FTECONTENTS_SOLID; int legacyterrain;
heightmap_t *hm; heightmap_t *hm;
char token[MAX_QPATH]; char token[MAX_QPATH];
@ -7364,9 +7391,12 @@ qboolean QDECL Terr_LoadTerrainModel (model_t *mod, void *buffer, size_t bufsize
src = COM_ParseOut(buffer, token, sizeof(token)); src = COM_ParseOut(buffer, token, sizeof(token));
if (!strcmp(token, "terrain")) if (!strcmp(token, "terrain"))
{
legacyterrain = true;
buffer = src; buffer = src;
}
else if (!strcmp(token, "{")) else if (!strcmp(token, "{"))
exterior = FTECONTENTS_EMPTY; legacyterrain = false;
else else
{ {
Con_Printf(CON_ERROR "%s wasn't terrain map\n", mod->name); //shouldn't happen Con_Printf(CON_ERROR "%s wasn't terrain map\n", mod->name); //shouldn't happen
@ -7390,7 +7420,7 @@ qboolean QDECL Terr_LoadTerrainModel (model_t *mod, void *buffer, size_t bufsize
hm->entitylock = Sys_CreateMutex(); hm->entitylock = Sys_CreateMutex();
hm->sectionsize = sectsize; hm->sectionsize = sectsize;
if (exterior) if (legacyterrain)
{ {
hm->firstsegx = -1; hm->firstsegx = -1;
hm->firstsegy = -1; hm->firstsegy = -1;
@ -7404,7 +7434,9 @@ qboolean QDECL Terr_LoadTerrainModel (model_t *mod, void *buffer, size_t bufsize
hm->maxsegx = 0; hm->maxsegx = 0;
hm->maxsegy = 0; hm->maxsegy = 0;
} }
hm->exteriorcontents = exterior; //sky outside the map hm->legacyterrain = legacyterrain;
if (legacyterrain)
hm->exteriorcontents = FTECONTENTS_SOLID; //sky outside the map
Terr_ParseEntityLump(mod, hm); Terr_ParseEntityLump(mod, hm);
@ -7528,44 +7560,56 @@ void Mod_Terrain_Create_f(void)
char *watername; char *watername;
char *groundheight; char *groundheight;
char *waterheight; char *waterheight;
char *seed;
vfsfile_t *file; vfsfile_t *file;
model_t mod; model_t mod;
memset(&mod, 0, sizeof(mod)); memset(&mod, 0, sizeof(mod));
if (Cmd_Argc() < 2) if (Cmd_Argc() < 2)
{ {
Con_Printf("%s: NAME \"DESCRIPTION\" SKYNAME DEFAULTGROUNDTEX DEFAULTHEIGHT DEFAULTWATER DEFAULTWATERHEIGHT\nGenerates a fresh maps/foo.hmp file. You may wish to edit it with notepad later to customise it. You will need csaddon.dat in order to edit the actual terrain.\n", Cmd_Argv(0)); Con_Printf("%s: NAME \"DESCRIPTION\" SKYNAME DEFAULTGROUNDTEX DEFAULTHEIGHT DEFAULTWATER DEFAULTWATERHEIGHT seed\nGenerates a fresh maps/foo.hmp file. You may wish to edit it with notepad later to customise it. You will need csaddon.dat in order to edit the actual terrain.\n", Cmd_Argv(0));
return; return;
} }
mname = va("maps/%s.hmp", Cmd_Argv(1)); mname = va("maps/%s.hmp", Cmd_Argv(1));
mapdesc = Cmd_Argv(2); if (!*mapdesc) mapdesc = Cmd_Argv(1); mapdesc = Cmd_Argv(2); if (!*mapdesc) mapdesc = Cmd_Argv(1);
skyname = Cmd_Argv(3); if (!*skyname) skyname = "sky1"; skyname = Cmd_Argv(3);
groundname = Cmd_Argv(4); if (!*groundname) groundname = "default"; groundname = Cmd_Argv(4);
groundheight = Cmd_Argv(5); if (!*groundheight) groundheight = "0"; groundheight = Cmd_Argv(5);
watername = Cmd_Argv(6); if (!*watername) watername = ""; watername = Cmd_Argv(6);
waterheight = Cmd_Argv(7); if (!*waterheight) waterheight = "1024"; waterheight = Cmd_Argv(7);
seed = Cmd_Argv(7);
Mod_SetEntitiesString(&mod, va( Mod_SetEntitiesString(&mod, va(
"{\n" "{\n"
"classname \"worldspawn\"\n" "classname \"worldspawn\"\n"
"message \"%s\"\n" "message \"%s\"\n"
"_sky sky1\n" "_sky \"%s\"\n"
"_fog 0.02\n" "_fog 0.02\n"
"_segmentsize 1024\n" "_maxdrawdist 0 /*overrides fog distance (if greater)*/\n"
"_segmentsize 1024 /*how big each section is. this affects texturing and resolutions*/\n"
"_minxsegment -2048\n" "_minxsegment -2048\n"
"_minysegment -2048\n" "_minysegment -2048\n"
"_maxxsegment 2048\n" "_maxxsegment 2048\n"
"_maxysegment 2048\n" "_maxysegment 2048\n"
"//_defaultgroundtexture \"city4_2\"\n" "_seed \"%s\" /*for auto-gen plugins*/\n"
"//_defaultwatertexture \"*water2\"\n" "_exterior solid\n"
"//_defaultgroundheight -1024\n" "_defaultgroundtexture \"%s\"\n"
"//_defaultwaterheight 0\n" //hurrah, sea level. "_defaultgroundheight \"%s\"\n"
"_defaultwatertexture \"%s\"\n"
"_defaultwaterheight \"%s\"\n" //hurrah, sea level.
// "_tiles 64 64 8 8\n" // "_tiles 64 64 8 8\n"
"}\n" "}\n"
"{\n" "{\n"
"classname info_player_start\n" "classname info_player_start\n"
"origin \"0 0 1024\"\n" "origin \"0 0 1024\" /*EDITME*/\n"
"}\n" "}\n"
, Cmd_Argv(2)), true); "/*ADD EXTRA ENTITIES!*/\n"
, mapdesc
,*skyname?skyname:"terrsky1", seed
,*groundname?groundname:"ground1_1"
,*groundheight?groundheight:"-1024"
,*watername?watername:"*water2"
,*waterheight?waterheight:"0"
), true);
mod.type = mod_heightmap; mod.type = mod_heightmap;
mod.terrain = hm = Z_Malloc(sizeof(*hm)); mod.terrain = hm = Z_Malloc(sizeof(*hm));
@ -7724,7 +7768,11 @@ void Mod_Terrain_Reload_f(void)
terrainfuncs_t *QDECL Terr_GetTerrainFuncs(void) terrainfuncs_t *QDECL Terr_GetTerrainFuncs(void)
{ {
#ifdef SERVERONLY
return NULL; //dedicated server builds have all the visual stuff stripped, which makes APIs too inconsistent. Generate then save. Or fix up the API...
#else
return &terrainfuncs; return &terrainfuncs;
#endif
} }
void Terr_Init(void) void Terr_Init(void)

View File

@ -1422,7 +1422,8 @@ model_t *Mod_LoadModel (model_t *mod, enum mlverbosity_e verbose)
// Mod_LoadModelWorker(mod, MLV_WARN, 0); // Mod_LoadModelWorker(mod, MLV_WARN, 0);
// else // else
if (verbose == MLV_ERROR || verbose == MLV_WARNSYNC) if (verbose == MLV_ERROR || verbose == MLV_WARNSYNC)
COM_AddWork(WG_MAIN, Mod_LoadModelWorker, mod, NULL, verbose, 0); Mod_LoadModelWorker(mod, NULL, verbose, 0);
// COM_AddWork(WG_MAIN, Mod_LoadModelWorker, mod, NULL, verbose, 0);
else else
COM_AddWork(WG_LOADER, Mod_LoadModelWorker, mod, NULL, verbose, 0); COM_AddWork(WG_LOADER, Mod_LoadModelWorker, mod, NULL, verbose, 0);
} }

View File

@ -546,23 +546,14 @@ void GLBE_UploadAllLightmaps(void)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
} }
switch (lightmap_bytes) switch(lightmap_fmt) //bgra32, rgba32, rgb24, lum8
{ {
case 4: default: Sys_Error("Bad lightmap_fmt\n"); break;
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, case TF_BGRA32: qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lm->width, lm->height, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV,lightmap[i]->lightmaps); break;
lm->width, lm->height, 0, (lightmap_bgra?GL_BGRA_EXT:GL_RGBA), GL_UNSIGNED_INT_8_8_8_8_REV, // case TF_RGBA32: qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lm->width, lm->height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV,lightmap[i]->lightmaps); break;
lightmap[i]->lightmaps); // case TF_BGR24: qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, lm->width, lm->height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, lightmap[i]->lightmaps); break;
break; case TF_RGB24: qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, lm->width, lm->height, 0, GL_RGB, GL_UNSIGNED_BYTE, lightmap[i]->lightmaps); break;
case 3: case TF_LUM8: qglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, lm->width, lm->height, 0, GL_LUMINANCE,GL_UNSIGNED_BYTE, lightmap[i]->lightmaps); break;
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
lm->width, lm->height, 0, (lightmap_bgra?GL_BGR_EXT:GL_RGB), GL_UNSIGNED_BYTE,
lightmap[i]->lightmaps);
break;
case 1:
qglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,
lm->width, lm->height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
lightmap[i]->lightmaps);
break;
} }
//for completeness. //for completeness.
lm->lightmap_texture->width = lm->width; lm->lightmap_texture->width = lm->width;

View File

@ -287,23 +287,28 @@ typedef struct
typedef struct heightmap_s typedef struct heightmap_s
{ {
char path[MAX_QPATH]; char path[MAX_QPATH];
char skyname[MAX_QPATH]; char skyname[MAX_QPATH]; //name of the skybox
char groundshadername[MAX_QPATH]; char groundshadername[MAX_QPATH]; //this is the shader we're using to draw the terrain itself. you could use other shaders here, for eg debugging or stylised weirdness.
char defaultwatershader[MAX_QPATH]; //typically the name of the ocean or whatever. unsigned int culldistance; //entities will be culled if they're this far away (squared distance
unsigned int culldistance; float maxdrawdist; //maximum view distance. extends view if larger than fog implies.
qboolean forcedefault;
float defaultwaterheight; unsigned char *seed; //used by whatever terrain generator.
float defaultgroundheight; qboolean forcedefault; //sections that cannot be loaded/generated will receive default values for stuff.
char defaultgroundtexture[MAX_QPATH]; char defaultgroundtexture[MAX_QPATH];//texture used for defaulted sections
int firstsegx, firstsegy; char defaultwatershader[MAX_QPATH]; //shader used for defaulted sections that have heights beneath defaultwaterheight.
int maxsegx, maxsegy; //tex/cull sections float defaultwaterheight; //water height. if you want your islands to be surrounded by water.
float defaultgroundheight; //defaulted sections will have a z plane this high
int firstsegx, firstsegy; //min bounds of the terrain, in sections
int maxsegx, maxsegy; //max bounds of the terrain, in sections
float sectionsize; //each section is this big, in world coords float sectionsize; //each section is this big, in world coords
hmcluster_t *cluster[MAXCLUSTERS*MAXCLUSTERS]; hmcluster_t *cluster[MAXCLUSTERS*MAXCLUSTERS];
shader_t *skyshader; shader_t *skyshader;
shader_t *shader; shader_t *shader;
mesh_t skymesh; mesh_t skymesh;
mesh_t *askymesh; mesh_t *askymesh;
unsigned int exteriorcontents; qboolean legacyterrain; //forced exterior=SOLID
unsigned int exteriorcontents; //contents type outside of the terrain sections area (.map should be empty, while terrain will usually block).
unsigned int loadingsections; //number of sections currently being loaded. avoid loading extras while non-zero. unsigned int loadingsections; //number of sections currently being loaded. avoid loading extras while non-zero.
size_t traceseq; size_t traceseq;
size_t drawnframe; size_t drawnframe;

View File

@ -1,6 +1,6 @@
#include "quakedef.h" #include "quakedef.h"
#if 0//def WEBCLIENT #ifdef FTPCLIENT
#include "iweb.h" #include "iweb.h"

View File

@ -8,7 +8,7 @@
#endif #endif
#endif #endif
#ifdef WEBSERVER #ifdef FTPSERVER
#include "iweb.h" #include "iweb.h"

View File

@ -1,7 +1,9 @@
#ifndef IWEB_H__ #ifndef IWEB_H__
#define IWEB_H__ #define IWEB_H__
#ifdef WEBSERVER qboolean SV_AllowDownload (const char *name);
#if defined(WEBSERVER) || defined(FTPSERVER)
#ifdef WEBSVONLY #ifdef WEBSVONLY
//When running standalone //When running standalone
@ -34,8 +36,6 @@ struct sockaddr;
struct sockaddr_qstorage; struct sockaddr_qstorage;
int NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s); int NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s);
qboolean SV_AllowDownload (const char *name);
typedef qboolean iwboolean; typedef qboolean iwboolean;

View File

@ -1,6 +1,6 @@
#include "quakedef.h" #include "quakedef.h"
#ifdef WEBSERVER #if defined(WEBSERVER) || defined(FTPSERVER)
#include "iweb.h" #include "iweb.h"
#include "netinc.h" #include "netinc.h"
@ -503,15 +503,18 @@ IWEBFILE *IWebFOpenRead(char *name) //fread(name, "rb");
#else #else
#if defined(WEBSERVER) || defined(FTPSERVER)
static cvar_t sv_readlevel = CVAR("sv_readlevel", "0"); //default to allow anyone
static cvar_t sv_writelevel = CVARD("sv_writelevel", "35", "Specifies the required trust level at which user accounts may write to the user-specific subdir of /uploads/USERNAME/*. If blank, then no uploads are permitted"); //allowed to write to uploads/uname
static cvar_t sv_fulllevel = CVARD("sv_fulllevel", "51", "User accounts with an access level greater than this may write anywhere, including the gamedir. Note that setting this low is increadibly risky. An empty value will be understood to never give this permission."); //allowed to write anywhere, replace any file...
#ifdef WEBSERVER #ifdef WEBSERVER
cvar_t ftpserver = CVAR("sv_ftp", "0"); static cvar_t httpserver = CVAR("sv_http", "0");
cvar_t ftpserver_port = CVAR("sv_ftp_port", "21"); static cvar_t httpserver_port = CVAR("sv_http_port", "80");
cvar_t httpserver = CVAR("sv_http", "0"); #endif
cvar_t httpserver_port = CVAR("sv_http_port", "80"); #ifdef FTPSERVER
cvar_t sv_readlevel = CVAR("sv_readlevel", "0"); //default to allow anyone static cvar_t ftpserver = CVAR("sv_ftp", "0");
cvar_t sv_writelevel = CVAR("sv_writelevel", "35"); //allowed to write to uploads/uname static cvar_t ftpserver_port = CVAR("sv_ftp_port", "21");
cvar_t sv_fulllevel = CVAR("sv_fulllevel", "51"); //allowed to write anywhere, replace any file... static cvar_t sv_ftp_port_range = CVARD("sv_ftp_port_range", "0", "Specifies the port range for the server to create listening sockets for 'active' ftp connections, to work around NAT/firewall issues.\nMost FTP clients should use passive connections, but there's still some holdouts like windows.");
cvar_t sv_ftp_port_range = CVARD("sv_ftp_port_range", "0", "Specifies the port range for the server to create listening sockets for 'active' ftp connections, to work around NAT/firewall issues.\nMost FTP clients should use passive connections, but there's still some holdouts like windows.");
int IWebGetSafeListeningPort(void) int IWebGetSafeListeningPort(void)
{ {
@ -533,6 +536,7 @@ int IWebGetSafeListeningPort(void)
return base + (sequence++ % (range+1-base)); return base + (sequence++ % (range+1-base));
} }
#endif #endif
#endif
//this file contains functions called from each side. //this file contains functions called from each side.
@ -680,9 +684,9 @@ int IWebAuthorize(const char *name, const char *password)
Rank_GetPlayerInfo(id, &info); Rank_GetPlayerInfo(id, &info);
if (info.s.trustlevel >= sv_fulllevel.value) if (*sv_fulllevel.string && info.s.trustlevel >= sv_fulllevel.value)
return IWEBACC_READ | IWEBACC_WRITE | IWEBACC_FULL; //allowed to read and write anywhere to the quake filesystem return IWEBACC_READ | IWEBACC_WRITE | IWEBACC_FULL; //allowed to read and write anywhere to the quake filesystem
if (info.s.trustlevel >= sv_writelevel.value) if (*sv_writelevel.string && info.s.trustlevel >= sv_writelevel.value)
return IWEBACC_READ | IWEBACC_WRITE; //allowed to read anywhere write to specific places return IWEBACC_READ | IWEBACC_WRITE; //allowed to read anywhere write to specific places
if (info.s.trustlevel >= sv_readlevel.value) if (info.s.trustlevel >= sv_readlevel.value)
return IWEBACC_READ; //read only anywhere return IWEBACC_READ; //read only anywhere

View File

@ -1,11 +1,11 @@
#include "quakedef.h" #include "quakedef.h"
#ifdef WEBSERVER #if defined(WEBSERVER) || defined(FTPSERVER)
#include "iweb.h" #include "iweb.h"
#ifdef CLIENTONLY #if defined(CLIENTONLY) || !defined(WEBSERVER)
vfsfile_t *IWebGenerateFile(char *name) vfsfile_t *IWebGenerateFile(const char *name, const char *content, int contentlength)
{ {
return NULL; return NULL;
} }

View File

@ -703,13 +703,11 @@ HMODULE scintilla;
pbool resetprogssrc; //progs.src was changed, reload project info. pbool resetprogssrc; //progs.src was changed, reload project info.
HWND mainwindow; HWND mainwindow;
HWND gamewindow; HWND gamewindow;
HWND mdibox; HWND mdibox;
HWND watches; HWND watches;
HWND optionsmenu; HWND optionsmenu;
HWND outputwindow;
HWND outputbox; HWND outputbox;
HWND projecttree; HWND projecttree;
HWND search_name; HWND search_name;
@ -717,6 +715,240 @@ HWND search_gotodef;
HWND search_grep; HWND search_grep;
HACCEL accelerators; HACCEL accelerators;
//our splitter...
#define SPLITTER_SIZE 4
static struct splits_s
{
HWND wnd;
HWND splitter;
int minsize;
int cury;
int cursize;
float frac;
} *splits;
static size_t numsplits;
static RECT splitterrect;
static struct splits_s *SplitterGet(HWND id)
{
size_t s;
for (s = 0; s < numsplits; s++)
{
if (splits[s].wnd == id)
return &splits[s];
}
return NULL;
}
static int SplitterShrinkPrior(size_t s, int px)
{
int found = 0;
int avail;
for (; px && s > 0; s--)
{
avail = splits[s].cursize - splits[s].minsize;
if (avail > px)
avail = px;
splits[s].cursize -= avail;
found += avail;
px -= avail;
}
if (px)
{
avail = splits[0].cursize - splits[0].minsize;
if (avail > px)
avail = px;
splits[0].cursize -= avail;
found += avail;
px -= avail;
}
return found;
}
static SplitterShrinkNext(size_t s, int px)
{
int found = 0;
int avail;
for (; px && s < numsplits; s++)
{
avail = splits[s].cursize - splits[s].minsize;
if (avail > px)
avail = px;
splits[s].cursize -= avail;
found += avail;
px -= avail;
}
return found;
}
static void SplitterUpdate(void);
static LRESULT CALLBACK SplitterWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
size_t s;
PAINTSTRUCT ps;
RECT rect;
int y;
int cascade;
switch(message)
{
case WM_LBUTTONDOWN:
SetCapture(hWnd);
return TRUE;
case WM_MOUSEMOVE:
if (wParam & MK_LBUTTON)
if (GetCapture() == hWnd)
goto doresize;
return true;
case WM_LBUTTONUP:
ReleaseCapture();
doresize:
y = GET_Y_LPARAM(lParam);
GetClientRect(hWnd, &rect);
y = y - rect.top - SPLITTER_SIZE/2;
for (s = 1; s < numsplits; s++)
{
if (splits[s].splitter == hWnd)
{
cascade = 0;
if (y < 0)
splits[s].cursize += SplitterShrinkPrior(s-1, -y);
else
splits[s-1].cursize += SplitterShrinkNext(s, y);
SplitterUpdate();
break;
}
}
return TRUE;
case WM_PAINT:
BeginPaint(hWnd,(LPPAINTSTRUCT)&ps);
EndPaint(hWnd,(LPPAINTSTRUCT)&ps);
return TRUE;
default:
return DefWindowProc(hWnd,message,wParam,lParam);
}
}
static void SplitterUpdate(void)
{
int y = 0;
size_t s;
if (!numsplits)
return;
//figure out the total height
for (s = numsplits; s-- > 0; )
{
y += splits[s].cursize;
}
y = splitterrect.bottom-splitterrect.top;
//now figure out their positions relative to that
for (s = numsplits; s-- > 1; )
{
y -= splits[s].cursize;
splits[s].cury = y;
y -= SPLITTER_SIZE;
}
splits[0].cursize = y;
splits[0].cury = 0;
if (splits[0].cursize < splits[0].minsize)
splits[0].cursize += SplitterShrinkNext(1, splits[0].minsize-splits[0].cursize);
for (s = 0; s < numsplits; s++)
{
if (s)
{
if (!splits[s].splitter)
{
WNDCLASSA wclass;
wclass.style = 0;
wclass.lpfnWndProc = SplitterWndProc;
wclass.cbClsExtra = 0;
wclass.cbWndExtra = 0;
wclass.hInstance = ghInstance;
wclass.hIcon = NULL;
wclass.hCursor = LoadCursor(0, IDC_SIZENS);
wclass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wclass.lpszMenuName = NULL;
wclass.lpszClassName = "splitter";
RegisterClassA(&wclass);
splits[s].splitter = CreateWindowExA(0, wclass.lpszClassName, "", WS_CHILD|WS_VISIBLE, splitterrect.left, splitterrect.top+splits[s].cury-SPLITTER_SIZE, splitterrect.right-splitterrect.left, SPLITTER_SIZE, mainwindow, NULL, ghInstance, NULL);
}
else
SetWindowPos(splits[s].splitter, HWND_TOP, splitterrect.left, splitterrect.top+splits[s].cury-SPLITTER_SIZE, splitterrect.right-splitterrect.left, SPLITTER_SIZE, SWP_NOZORDER);
}
else
{
if (splits[s].splitter)
{
DestroyWindow(splits[s].splitter);
splits[s].splitter = NULL;
}
}
SetWindowPos(splits[s].wnd, HWND_TOP, splitterrect.left, splitterrect.top+splits[s].cury, splitterrect.right-splitterrect.left, splits[s].cursize, SWP_NOZORDER);
}
}
static void SplitterFocus(HWND w, int minsize)
{
struct splits_s *s = SplitterGet(w);
if (s)
{
if (s->cursize < minsize)
{
s->cursize += SplitterShrinkPrior(s-splits-1, (minsize-s->cursize)/2);
if (s->cursize < minsize)
s->cursize += SplitterShrinkNext(s-splits+1, minsize-s->cursize);
if (s->cursize < minsize)
s->cursize += SplitterShrinkPrior(s-splits-1, minsize-s->cursize);
SplitterUpdate();
}
}
SetFocus(w);
}
static void SplitterAdd(HWND w, int minsize)
{
struct splits_s *n = malloc(sizeof(*n)*(numsplits+1));
memcpy(n, splits, sizeof(*n)*numsplits);
free(splits);
splits = n;
n += numsplits;
n->wnd = w;
n->splitter = NULL;
n->minsize = minsize;
n->cursize = minsize;
n->cury = 0;
numsplits++;
SplitterUpdate();
ShowWindow(w, SW_SHOW);
}
static void SplitterRemove(HWND w)
{
struct splits_s *s = SplitterGet(w);
size_t idx;
if (!s)
return;
if (s->splitter)
DestroyWindow(s->splitter);
idx = s-splits;
numsplits--;
memmove(splits+idx, splits+idx+1, sizeof(*s)*(numsplits-idx));
ShowWindow(w, SW_HIDE);
SplitterUpdate();
}
FILE *logfile; FILE *logfile;
void GrepAllFiles(char *string); void GrepAllFiles(char *string);
@ -855,21 +1087,21 @@ LRESULT CALLBACK MySubclassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
{ {
*colon1 = '\0'; *colon1 = '\0';
*colon2 = '\0'; *colon2 = '\0';
EditFile(line, atoi(colon1+1)-1, false); EditFile(line, atoi(colon1+1)-1, 2);
} }
else if (!strncmp(line, "Source file: ", 13)) else if (!strncmp(line, "Source file: ", 13))
EditFile(line+13, -1, false); EditFile(line+13, -1, 2);
else if (!strncmp(line, "Including: ", 11)) else if (!strncmp(line, "Including: ", 11))
EditFile(line+11, -1, false); EditFile(line+11, -1, 2);
} }
else if (!strncmp(line, "including ", 10)) else if (!strncmp(line, "including ", 10))
EditFile(line+10, -1, false); EditFile(line+10, -1, 2);
else if (!strncmp(line, "compiling ", 10)) else if (!strncmp(line, "compiling ", 10))
EditFile(line+10, -1, false); EditFile(line+10, -1, 2);
else if (!strncmp(line, "prototyping ", 12)) else if (!strncmp(line, "prototyping ", 12))
EditFile(line+12, -1, false); EditFile(line+12, -1, 2);
else if (!strncmp(line, "Couldn't open file ", 19)) else if (!strncmp(line, "Couldn't open file ", 19))
EditFile(line+19, -1, false); EditFile(line+19, -1, 2);
Edit_SetSel(hWnd, selrange.cpMin, selrange.cpMin); //deselect it. Edit_SetSel(hWnd, selrange.cpMin, selrange.cpMin); //deselect it.
} }
} }
@ -1385,11 +1617,7 @@ void GenericMenu(WPARAM wParam)
case IDM_OUTPUT_WINDOW: case IDM_OUTPUT_WINDOW:
if (outputwindow && outputbox) SplitterFocus(outputbox, 128);
{
SetFocus(outputwindow);
SetFocus(outputbox);
}
break; break;
case IDM_SHOWLINENUMBERS: case IDM_SHOWLINENUMBERS:
{ {
@ -2267,6 +2495,8 @@ static LRESULT CALLBACK EditorWndProc(HWND hWnd,UINT message,
GetClientRect(hWnd, &rect); GetClientRect(hWnd, &rect);
SetWindowPos(editor->editpane, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, 0); SetWindowPos(editor->editpane, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, 0);
goto gdefault; goto gdefault;
case WM_ERASEBKGND:
return TRUE;
case WM_PAINT: case WM_PAINT:
BeginPaint(hWnd,(LPPAINTSTRUCT)&ps); BeginPaint(hWnd,(LPPAINTSTRUCT)&ps);
@ -2547,6 +2777,10 @@ static void EditorReload(editor_t *editor)
} }
//line is 0-based. use -1 for no reselection //line is 0-based. use -1 for no reselection
//setcontrol is the reason we're opening it.
//0: just load and go to the line.
//1: show the line as the executing one
//2: draw extra focus to it
void EditFile(const char *name, int line, pbool setcontrol) void EditFile(const char *name, int line, pbool setcontrol)
{ {
char title[1024]; char title[1024];
@ -2574,7 +2808,10 @@ void EditFile(const char *name, int line, pbool setcontrol)
{ {
if (line >= 0) if (line >= 0)
{ {
Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line), Edit_LineIndex(neweditor->editpane, line+1)-1); if (setcontrol)
Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line+1)-1, Edit_LineIndex(neweditor->editpane, line+1)-1);
else
Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line), Edit_LineIndex(neweditor->editpane, line+1)-1);
Edit_ScrollCaret(neweditor->editpane); Edit_ScrollCaret(neweditor->editpane);
if (setcontrol && neweditor->scintilla) if (setcontrol && neweditor->scintilla)
@ -2635,15 +2872,15 @@ void EditFile(const char *name, int line, pbool setcontrol)
wndclass.style = 0; wndclass.style = 0;
wndclass.lpfnWndProc = EditorWndProc; wndclass.lpfnWndProc = EditorWndProc;
wndclass.cbClsExtra = 0; wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0; wndclass.cbWndExtra = 0;
wndclass.hInstance = ghInstance; wndclass.hInstance = ghInstance;
wndclass.hIcon = LoadIcon(ghInstance, IDI_ICON_FTEQCC); wndclass.hIcon = LoadIcon(ghInstance, IDI_ICON_FTEQCC);
wndclass.hCursor = LoadCursor (NULL,IDC_ARROW); wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
wndclass.hbrBackground = (void *)COLOR_WINDOW; wndclass.hbrBackground = (void *)COLOR_WINDOW;
wndclass.lpszMenuName = 0; wndclass.lpszMenuName = 0;
wndclass.lpszClassName = EDIT_WINDOW_CLASS_NAME; wndclass.lpszClassName = EDIT_WINDOW_CLASS_NAME;
RegisterClass(&wndclass); RegisterClass(&wndclass);
neweditor->window = NULL; neweditor->window = NULL;
@ -2658,7 +2895,7 @@ void EditFile(const char *name, int line, pbool setcontrol)
mcs.hOwner = ghInstance; mcs.hOwner = ghInstance;
mcs.x = mcs.cx = CW_USEDEFAULT; mcs.x = mcs.cx = CW_USEDEFAULT;
mcs.y = mcs.cy = CW_USEDEFAULT; mcs.y = mcs.cy = CW_USEDEFAULT;
mcs.style = WS_OVERLAPPEDWINDOW; mcs.style = WS_OVERLAPPEDWINDOW|WS_MAXIMIZE;
mcs.lParam = 0; mcs.lParam = 0;
neweditor->window = (HWND) SendMessage (mdibox, WM_MDICREATE, 0, neweditor->window = (HWND) SendMessage (mdibox, WM_MDICREATE, 0,
@ -2685,7 +2922,12 @@ void EditFile(const char *name, int line, pbool setcontrol)
EditorReload(neweditor); EditorReload(neweditor);
if (line >= 0) if (line >= 0)
Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line), Edit_LineIndex(neweditor->editpane, line+1)); {
if (setcontrol)
Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line+1)-1, Edit_LineIndex(neweditor->editpane, line+1)-1);
else
Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line), Edit_LineIndex(neweditor->editpane, line+1)-1);
}
else else
Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, 0), Edit_LineIndex(neweditor->editpane, 0)); Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, 0), Edit_LineIndex(neweditor->editpane, 0));
@ -3417,8 +3659,8 @@ static LRESULT CALLBACK EngineWndProc(HWND hWnd,UINT message,
} }
if (hWnd == gamewindow) if (hWnd == gamewindow)
{ {
SplitterRemove(watches);
gamewindow = NULL; gamewindow = NULL;
PostMessage(mainwindow, WM_SIZE, 0, 0);
} }
break; break;
case WM_USER: case WM_USER:
@ -3724,6 +3966,8 @@ void RunEngine(void)
gamewindow = (HWND) SendMessage (mdibox, WM_MDICREATE, 0, (LONG_PTR) (LPMDICREATESTRUCT) &mcs); gamewindow = (HWND) SendMessage (mdibox, WM_MDICREATE, 0, (LONG_PTR) (LPMDICREATESTRUCT) &mcs);
} }
SplitterAdd(watches, 0);
SplitterFocus(watches, 64);
} }
else else
{ {
@ -5398,12 +5642,14 @@ static LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
watches = CreateWindow(WC_LISTVIEW, (LPCTSTR) NULL, watches = CreateWindow(WC_LISTVIEW, (LPCTSTR) NULL,
WS_CHILD | WS_VSCROLL | WS_HSCROLL | LVS_REPORT | LVS_EDITLABELS, WS_CHILD | WS_VSCROLL | WS_HSCROLL | LVS_REPORT | LVS_EDITLABELS,
0, 0, 320, 200, hWnd, (HMENU) 0xCAD, ghInstance, NULL); 0, 0, 320, 200, hWnd, (HMENU) 0xCAD, ghInstance, NULL);
ShowWindow(watches, SW_SHOW);
SplitterAdd(mdibox, 32);
if (watches) if (watches)
{ {
LVCOLUMN col; LVCOLUMN col;
LVITEM newi; LVITEM newi;
// ListView_SetUnicodeFormat(watches, TRUE); // ListView_SetUnicodeFormat(watches, TRUE);
ListView_SetExtendedListViewStyle(watches, LVS_EX_GRIDLINES); ListView_SetExtendedListViewStyle(watches, LVS_EX_GRIDLINES);
memset(&col, 0, sizeof(col)); memset(&col, 0, sizeof(col));
@ -5481,40 +5727,37 @@ static LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
GetClientRect(mainwindow, &rect); GetClientRect(mainwindow, &rect);
if (projecttree) if (projecttree)
{ {
int mdiheight, watchheight; SetWindowPos(projecttree, NULL, 0, 0, 192, rect.bottom-rect.top - 48, SWP_NOZORDER);
SetWindowPos(projecttree, NULL, 0, 0, 192, rect.bottom-rect.top - 34 - 48, 0);
SetWindowPos(search_name, NULL, 0, rect.bottom-rect.top - 33 - 48, 192, 24, 0); SetWindowPos(search_name, NULL, 0, rect.bottom-rect.top - 48, 192, 24, SWP_NOZORDER);
SetWindowPos(search_gotodef, NULL, 0, rect.bottom-rect.top - 33 - 24, 192/2, 24, 0); SetWindowPos(search_gotodef, NULL, 0, rect.bottom-rect.top - 24, 192/2, 24, SWP_NOZORDER);
SetWindowPos(search_grep, NULL, 192/2, rect.bottom-rect.top - 33 - 24, 192/2, 24, 0); SetWindowPos(search_grep, NULL, 192/2, rect.bottom-rect.top - 24, 192/2, 24, SWP_NOZORDER);
if (gamewindow) splitterrect.left = 192;
watchheight = (ListView_GetItemCount(watches) + 2) * 16;
else
watchheight = 0;
mdiheight = (rect.bottom-rect.top) - 32;
if (watchheight > mdiheight/2)
watchheight = mdiheight/2;
mdiheight -= watchheight;
SetWindowPos(watches, NULL, 192, mdiheight, rect.right-rect.left-192, watchheight, 0);
SetWindowPos(mdibox?mdibox:outputbox, NULL, 192, 0, rect.right-rect.left-192, mdiheight, 0);
} }
else else
SetWindowPos(mdibox?mdibox:outputbox, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top - 32, 0); {
width = (rect.right-rect.left); splitterrect.left = 0;
width/=NUMBUTTONS; }
splitterrect.right = rect.right-rect.left;
splitterrect.bottom = rect.bottom-rect.top-32;
SplitterUpdate();
width = (rect.right-rect.left)-splitterrect.left;
for (i = 0; i < NUMBUTTONS; i++) for (i = 0; i < NUMBUTTONS; i++)
{ {
SetWindowPos(buttons[i].hwnd, NULL, width*i, rect.bottom-rect.top - 32, width, 32, 0); int l = splitterrect.left+(width*i)/(NUMBUTTONS);
int r = splitterrect.left+(width*(i+1))/(NUMBUTTONS);
SetWindowPos(buttons[i].hwnd, NULL, l, rect.bottom-rect.top - 32, r-l, 32, SWP_NOZORDER);
} }
break; break;
// goto gdefault; // goto gdefault;
case WM_ERASEBKGND:
return TRUE; //background is clear... or doesn't need clearing (if its fully obscured)
case WM_PAINT: case WM_PAINT:
BeginPaint(hWnd,(LPPAINTSTRUCT)&ps); BeginPaint(hWnd,(LPPAINTSTRUCT)&ps);
EndPaint(hWnd,(LPPAINTSTRUCT)&ps); EndPaint(hWnd,(LPPAINTSTRUCT)&ps);
return TRUE; return TRUE;
break;
case WM_COMMAND: case WM_COMMAND:
i = LOWORD(wParam); i = LOWORD(wParam);
if (i == 0x4403) if (i == 0x4403)
@ -5722,27 +5965,6 @@ static void DoTranslateMessage(MSG *msg)
} }
} }
static LRESULT CALLBACK OutputWindowProc(HWND hWnd,UINT message,
WPARAM wParam,LPARAM lParam)
{
RECT rect;
switch (message)
{
case WM_DESTROY:
outputwindow = NULL;
outputbox = NULL;
break;
case WM_CREATE:
outputbox = CreateAnEditControl(hWnd, NULL);
case WM_SIZE:
GetClientRect(hWnd, &rect);
SetWindowPos(outputbox, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, 0);
default:
return DefMDIChildProc(hWnd,message,wParam,lParam);
}
return 0;
}
void GUIPrint(HWND wnd, char *msg) void GUIPrint(HWND wnd, char *msg)
{ {
// MSG wmsg; // MSG wmsg;
@ -6031,8 +6253,7 @@ int GUIprintf(const char *msg, ...)
outlen = 0; outlen = 0;
/*make sure its active so we can actually scroll. stupid windows*/ /*make sure its active so we can actually scroll. stupid windows*/
SetFocus(outputwindow); SplitterFocus(outputbox, 0);
SetFocus(outputbox);
/*colour background to default*/ /*colour background to default*/
TreeView_SetBkColor(projecttree, -1); TreeView_SetBkColor(projecttree, -1);
@ -6274,45 +6495,14 @@ void RunCompiler(char *args, pbool quick)
void CreateOutputWindow(pbool doannoates) void CreateOutputWindow(pbool doannoates)
{ {
WNDCLASS wndclass;
MDICREATESTRUCT mcs;
gui_doannotates = doannoates; gui_doannotates = doannoates;
if (!mdibox) //should already be created if (!outputbox)
return;
if (!outputwindow)
{ {
wndclass.style = 0; outputbox = CreateAnEditControl(mainwindow, NULL);
wndclass.lpfnWndProc = OutputWindowProc; SplitterAdd(outputbox, 64);
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = ghInstance;
wndclass.hIcon = LoadIcon(ghInstance, IDI_ICON_FTEQCC);
wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
wndclass.hbrBackground = (void *)COLOR_WINDOW;
wndclass.lpszMenuName = 0;
wndclass.lpszClassName = MAIN_WINDOW_CLASS_NAME;
RegisterClass(&wndclass);
mcs.szClass = MAIN_WINDOW_CLASS_NAME;
mcs.szTitle = "Compiler output";
mcs.hOwner = ghInstance;
mcs.x = mcs.cx = CW_USEDEFAULT;
mcs.y = mcs.cy = CW_USEDEFAULT;
mcs.style = WS_OVERLAPPEDWINDOW;
mcs.lParam = 0;
outputwindow = (HWND) SendMessage (mdibox, WM_MDICREATE, 0, (LONG_PTR) (LPMDICREATESTRUCT) &mcs);
ShowWindow(outputwindow, SW_SHOW);
} }
SplitterFocus(outputbox, 128);
//bring it to the front.
SendMessage(mdibox, WM_MDIACTIVATE, (WPARAM)outputwindow, 0);
} }

View File

@ -820,6 +820,7 @@ void PR_LoadGlabalStruct(qboolean muted)
globalfloat (false, input_buttons); globalfloat (false, input_buttons);
globalint (false, serverid); globalint (false, serverid);
globalvec (false, global_gravitydir); globalvec (false, global_gravitydir);
globalstring (false, parm_string);
memset(&evalc_idealpitch, 0, sizeof(evalc_idealpitch)); memset(&evalc_idealpitch, 0, sizeof(evalc_idealpitch));
memset(&evalc_pitch_speed, 0, sizeof(evalc_pitch_speed)); memset(&evalc_pitch_speed, 0, sizeof(evalc_pitch_speed));
@ -2664,15 +2665,25 @@ void PF_setmodel_Internal (pubprogfuncs_t *prinst, edict_t *e, const char *m)
if (sv.state != ss_loading) if (sv.state != ss_loading)
{ {
int j;
Con_DPrintf("Delayed model precache: %s\n", m); Con_DPrintf("Delayed model precache: %s\n", m);
MSG_WriteByte(&sv.reliable_datagram, svcfte_precache);
MSG_WriteShort(&sv.reliable_datagram, i); for (j = 0; j < sv.allocated_client_slots; j++)
MSG_WriteString(&sv.reliable_datagram, m); {
#ifdef NQPROT if (svs.clients[j].state < cs_connected)
MSG_WriteByte(&sv.nqreliable_datagram, svcdp_precache); continue;
MSG_WriteShort(&sv.nqreliable_datagram, i); if (ISDPCLIENT(&svs.clients[j]) || (svs.clients[j].fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS))
MSG_WriteString(&sv.nqreliable_datagram, m); {
#endif ClientReliableWrite_Begin (&svs.clients[j], ISNQCLIENT(&svs.clients[j])?svcdp_precache:svcfte_precache, strlen(m)+4);
ClientReliableWrite_Short (&svs.clients[j], i);
ClientReliableWrite_String (&svs.clients[j], m);
}
else
{
//client doesn't support this... reset the connection so they're forced to reload everything.
//SV_StuffcmdToClient(&svs.clients[j], "cmd new\n");
}
}
} }
} }
else else
@ -3677,6 +3688,25 @@ void PF_stuffcmd_Internal(int entnum, const char *str, unsigned int flags)
{ {
client_t *cl; client_t *cl;
int slen; int slen;
unsigned int i;
if (flags & STUFFCMD_BROADCAST)
{
for (i = 0, cl = svs.clients; i < sv.allocated_client_slots; i++, cl++)
{
if (cl->state != cs_spawned || cl->controller == cl)
continue;
SV_StuffcmdToClient(cl, str);
}
if (!(flags & STUFFCMD_IGNOREINDEMO))
if (sv.mvdrecording)
{
sizebuf_t *msg = MVDWrite_Begin (dem_all, 0, 2 + strlen(str));
MSG_WriteByte (msg, svc_stufftext);
MSG_WriteString (msg, str);
}
return;
}
if (entnum < 1 || entnum > sv.allocated_client_slots) if (entnum < 1 || entnum > sv.allocated_client_slots)
return; return;
@ -5529,9 +5559,7 @@ void QCBUILTIN PF_setspawnparms (pubprogfuncs_t *prinst, struct globalvars_s *pr
// copy spawn parms out of the client_t // copy spawn parms out of the client_t
client = svs.clients + (i-1); client = svs.clients + (i-1);
for (i=0 ; i< NUM_SPAWN_PARMS ; i++) SV_SpawnParmsToQC(client);
if (pr_global_ptrs->spawnparamglobals[i])
*pr_global_ptrs->spawnparamglobals[i] = client->spawn_parms[i];
} }
/* /*
@ -5744,7 +5772,7 @@ char *PF_infokey_Internal (int entnum, const char *key)
value = ""; //could be a writebyted bot... value = ""; //could be a writebyted bot...
break; break;
case SCP_QUAKEWORLD: case SCP_QUAKEWORLD:
if (!svs.clients[entnum-1].fteprotocolextensions && !svs.clients[entnum-1].fteprotocolextensions) if (!svs.clients[entnum-1].fteprotocolextensions && !svs.clients[entnum-1].fteprotocolextensions2)
value = "quakeworld"; value = "quakeworld";
else else
value = "quakeworld+"; value = "quakeworld+";
@ -8550,29 +8578,44 @@ static void QCBUILTIN PF_te_teleport(pubprogfuncs_t *prinst, struct globalvars_s
//void(vector org, float color, float length) te_explosion2 = #427; //void(vector org, float color, float length) te_explosion2 = #427;
static void QCBUILTIN PF_te_explosion2(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_te_explosion2(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
qboolean old = false;
float *org = G_VECTOR(OFS_PARM0); float *org = G_VECTOR(OFS_PARM0);
int start = G_FLOAT(OFS_PARM1); int start = G_FLOAT(OFS_PARM1);
int length = G_FLOAT(OFS_PARM2); int length = G_FLOAT(OFS_PARM2);
start = bound(0, start, 255); start = bound(0, start, 255);
length = bound(0, length, 255-start); length = bound(0, length, 255-start);
MSG_WriteByte (&sv.multicast, svc_temp_entity); for(;;)
MSG_WriteByte (&sv.multicast, TEQW_EXPLOSION2); {
MSG_WriteCoord (&sv.multicast, org[0]); MSG_WriteByte (&sv.multicast, svc_temp_entity);
MSG_WriteCoord (&sv.multicast, org[1]); MSG_WriteByte (&sv.multicast, old?TE_EXPLOSION:TEQW_EXPLOSION2);
MSG_WriteCoord (&sv.multicast, org[2]); MSG_WriteCoord (&sv.multicast, org[0]);
MSG_WriteByte (&sv.multicast, start); MSG_WriteCoord (&sv.multicast, org[1]);
MSG_WriteByte (&sv.multicast, length); MSG_WriteCoord (&sv.multicast, org[2]);
#ifdef NQPROT if (!old)
MSG_WriteByte (&sv.nqmulticast, svc_temp_entity); {
MSG_WriteByte (&sv.nqmulticast, TENQ_EXPLOSION2); MSG_WriteByte (&sv.multicast, start);
MSG_WriteCoord (&sv.nqmulticast, org[0]); MSG_WriteByte (&sv.multicast, length);
MSG_WriteCoord (&sv.nqmulticast, org[1]); }
MSG_WriteCoord (&sv.nqmulticast, org[2]); #ifdef NQPROT
MSG_WriteByte (&sv.nqmulticast, start); MSG_WriteByte (&sv.nqmulticast, svc_temp_entity);
MSG_WriteByte (&sv.nqmulticast, length); MSG_WriteByte (&sv.nqmulticast, TENQ_EXPLOSION2);
#endif MSG_WriteCoord (&sv.nqmulticast, org[0]);
SV_MulticastProtExt(org, MULTICAST_PHS, pr_global_struct->dimension_send, 0, 0); MSG_WriteCoord (&sv.nqmulticast, org[1]);
MSG_WriteCoord (&sv.nqmulticast, org[2]);
MSG_WriteByte (&sv.nqmulticast, start);
MSG_WriteByte (&sv.nqmulticast, length);
#endif
if (old)
{
SV_MulticastProtExt(org, MULTICAST_PHS, pr_global_struct->dimension_send, 0, PEXT_TE_BULLET);
break;
}
else
SV_MulticastProtExt(org, MULTICAST_PHS, pr_global_struct->dimension_send, PEXT_TE_BULLET, 0);
old = true;
}
} }
//DP_TE_FLAMEJET //DP_TE_FLAMEJET

View File

@ -2097,6 +2097,7 @@ qboolean PR_LoadQ1QVM(void)
pr_global_ptrs->spawnparamglobals[i] = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)(&global->parm1 + i)); pr_global_ptrs->spawnparamglobals[i] = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)(&global->parm1 + i));
for (; i < NUM_SPAWN_PARMS; i++) for (; i < NUM_SPAWN_PARMS; i++)
pr_global_ptrs->spawnparamglobals[i] = NULL; pr_global_ptrs->spawnparamglobals[i] = NULL;
pr_global_ptrs->parm_string = NULL;
#define emufield(n,t) if (field[i].type == t && !strcmp(#n, fname)) {fofs.n = (field[i].ofs - WASTED_EDICT_T_SIZE)/sizeof(float); continue;} #define emufield(n,t) if (field[i].type == t && !strcmp(#n, fname)) {fofs.n = (field[i].ofs - WASTED_EDICT_T_SIZE)/sizeof(float); continue;}
if (VM_NonNative(q1qvm)) if (VM_NonNative(q1qvm))

View File

@ -100,6 +100,7 @@ typedef struct nqglobalvars_s
float *input_buttons; float *input_buttons;
vec3_t *global_gravitydir; vec3_t *global_gravitydir;
float *spawnparamglobals[NUM_SPAWN_PARMS]; float *spawnparamglobals[NUM_SPAWN_PARMS];
string_t *parm_string;
int *serverid; int *serverid;
} globalptrs_t; } globalptrs_t;

View File

@ -803,11 +803,7 @@ qboolean SV_LoadLevelCache(const char *savename, const char *level, const char *
e2 = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "stats_restored", ev_float, NULL); e2 = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "stats_restored", ev_float, NULL);
if (e2) if (e2)
e2->_float = 1; e2->_float = 1;
for (j=0 ; j< NUM_SPAWN_PARMS ; j++) SV_SpawnParmsToQC(host_client);
{
if (pr_global_ptrs->spawnparamglobals[j])
*pr_global_ptrs->spawnparamglobals[j] = host_client->spawn_parms[j];
}
pr_global_struct->time = sv.world.physicstime; pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent);
ent->area.next = ent->area.prev = NULL; ent->area.next = ent->area.prev = NULL;

View File

@ -333,13 +333,18 @@ typedef struct
float move_msecs; // float move_msecs; //
int packetsizein; //amount of data received for this frame int packetsizein; //amount of data received for this frame
int packetsizeout; //amount of data that was sent in the frame int packetsizeout; //amount of data that was sent in the frame
packet_entities_t entities; //package containing entity states that were sent in this frame, for deltaing
packet_entities_t qwentities; //package containing entity states that were sent in this frame, for deltaing
struct resendinfo_s struct resendinfo_s
{ {
unsigned int entnum; unsigned int entnum;
unsigned int bits; //delta unsigned int bits; //delta (fte or dpp5+)
unsigned int flags; //csqc unsigned int flags; //csqc
} *resend; } *resend;
unsigned int numresend;
unsigned int maxresend;
unsigned short resendstats[32];//the number of each entity that was sent in this frame unsigned short resendstats[32];//the number of each entity that was sent in this frame
unsigned int numresendstats; //the bits of each entity that were sent in this frame unsigned int numresendstats; //the bits of each entity that were sent in this frame
@ -396,7 +401,7 @@ typedef struct //merge?
enum enum
{ {
PRESPAWN_INVALID=0, PRESPAWN_INVALID=0,
PRESPAWN_PROTOCOLSWITCH, //nq drops unreliables until reliables are acked PRESPAWN_PROTOCOLSWITCH, //nq drops unreliables until reliables are acked. this gives us a chance to drop any clc_move packets with formats from the previous map
PRESPAWN_SERVERINFO, PRESPAWN_SERVERINFO,
PRESPAWN_SOUNDLIST, //nq skips these PRESPAWN_SOUNDLIST, //nq skips these
PRESPAWN_VWEPMODELLIST, //qw ugly extension. PRESPAWN_VWEPMODELLIST, //qw ugly extension.
@ -504,7 +509,8 @@ typedef struct client_s
// spawn parms are carried from level to level // spawn parms are carried from level to level
float spawn_parms[NUM_SPAWN_PARMS]; float spawn_parms[NUM_SPAWN_PARMS];
char *spawninfo; char *spawn_parmstring; //qc-specified data.
char *spawninfo; //entity-formatted data (for hexen2's ClientReEnter)
float spawninfotime; float spawninfotime;
float nextservertimeupdate; //next time to send STAT_TIME float nextservertimeupdate; //next time to send STAT_TIME
float lastoutgoingphysicstime;//sv.world.physicstime of the last outgoing message. float lastoutgoingphysicstime;//sv.world.physicstime of the last outgoing message.
@ -1119,6 +1125,8 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg);
void SVQW_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, unsigned int protext); void SVQW_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, unsigned int protext);
client_t *SV_AddSplit(client_t *controller, char *info, int id); client_t *SV_AddSplit(client_t *controller, char *info, int id);
void SV_SpawnParmsToQC(client_t *client);
void SV_SpawnParmsToClient(client_t *client);
void SV_GetNewSpawnParms(client_t *cl); void SV_GetNewSpawnParms(client_t *cl);
void SV_SaveSpawnparms (void); void SV_SaveSpawnparms (void);
void SV_SaveSpawnparmsClient(client_t *client, float *transferparms); //if transferparms, calls SetTransferParms instead, and does not modify the player. void SV_SaveSpawnparmsClient(client_t *client, float *transferparms); //if transferparms, calls SetTransferParms instead, and does not modify the player.

View File

@ -759,7 +759,8 @@ void SV_Map_f (void)
Z_Free(host_client->spawninfo); Z_Free(host_client->spawninfo);
host_client->spawninfo = NULL; host_client->spawninfo = NULL;
memset(host_client->spawn_parms, 0, sizeof(host_client->spawn_parms)); memset(host_client->spawn_parms, 0, sizeof(host_client->spawn_parms));
SV_GetNewSpawnParms(host_client); if (host_client->state > cs_zombie)
SV_GetNewSpawnParms(host_client);
} }
if (preserveplayers && svprogfuncs && host_client->state == cs_spawned && host_client->spawninfo) if (preserveplayers && svprogfuncs && host_client->state == cs_spawned && host_client->spawninfo)
@ -2855,16 +2856,14 @@ void SV_MemInfo_f(void)
sz += lp->length; sz += lp->length;
fr = 0; fr = 0;
fr += sizeof(client_frame_t)*UPDATE_BACKUP;
if (cl->pendingdeltabits) if (cl->pendingdeltabits)
{ {
int maxents = cl->frameunion.frames[0].entities.max_entities; /*this is the max number of ents updated per frame. we can't track more, so...*/ fr += sizeof(cl)*UPDATE_BACKUP+
fr = sizeof(cl)*UPDATE_BACKUP+ sizeof(*cl->pendingdeltabits)*cl->max_net_ents;
sizeof(*cl->pendingdeltabits)*cl->max_net_ents+
sizeof(unsigned int)*maxents*UPDATE_BACKUP+
sizeof(unsigned int)*maxents*UPDATE_BACKUP;
} }
else fr += sizeof(*cl->frameunion.frames[0].resend)*cl->frameunion.frames[0].maxresend*UPDATE_BACKUP;
fr = (sizeof(client_frame_t)+sizeof(entity_state_t)*cl->frameunion.frames[0].entities.max_entities)*UPDATE_BACKUP; fr += sizeof(entity_state_t)*cl->frameunion.frames[0].qwentities.max_entities*UPDATE_BACKUP;
fr += sizeof(*cl->sentents.entities) * cl->sentents.max_entities; fr += sizeof(*cl->sentents.entities) * cl->sentents.max_entities;
csfr = sizeof(*cl->pendingcsqcbits) * cl->max_net_ents; csfr = sizeof(*cl->pendingcsqcbits) * cl->max_net_ents;
@ -2873,7 +2872,8 @@ void SV_MemInfo_f(void)
} }
} }
//FIXME: report vm memory if (sv.world.progs)
Con_Printf("ssqc: %u (used) / %u (reserved)\n", sv.world.progs->stringtablesize, sv.world.progs->stringtablemaxsize);
} }
void SV_Download_f (void) void SV_Download_f (void)

View File

@ -125,18 +125,18 @@ unsigned int SV_Q2BSP_FatPVS (model_t *mod, vec3_t org, qbyte *resultbuf, unsig
#endif #endif
void SVFTE_ExpandFrames(client_t *client, int require) void SV_ExpandNackFrames(client_t *client, int require)
{ {
client_frame_t *newframes; client_frame_t *newframes;
char *ptr; char *ptr;
int i; int i;
int maxents = require * 2; /*this is the max number of ents updated per frame. we can't track more, so...*/ int maxlog = require * 2; /*this is the max number of ents updated per frame. we can't track more, so...*/
if (maxents > client->max_net_ents) if (maxlog > client->max_net_ents)
maxents = client->max_net_ents; maxlog = client->max_net_ents;
ptr = Z_Malloc( sizeof(client_frame_t)*UPDATE_BACKUP+ ptr = Z_Malloc( sizeof(client_frame_t)*UPDATE_BACKUP+
sizeof(*client->pendingdeltabits)*client->max_net_ents+ sizeof(*client->pendingdeltabits)*client->max_net_ents+
sizeof(*client->pendingcsqcbits)*client->max_net_ents+ sizeof(*client->pendingcsqcbits)*client->max_net_ents+
sizeof(newframes[i].resend)*maxents*UPDATE_BACKUP); sizeof(newframes[i].resend)*maxlog*UPDATE_BACKUP);
newframes = (void*)ptr; newframes = (void*)ptr;
memcpy(newframes, client->frameunion.frames, sizeof(client_frame_t)*UPDATE_BACKUP); memcpy(newframes, client->frameunion.frames, sizeof(client_frame_t)*UPDATE_BACKUP);
ptr += sizeof(client_frame_t)*UPDATE_BACKUP; ptr += sizeof(client_frame_t)*UPDATE_BACKUP;
@ -148,9 +148,11 @@ void SVFTE_ExpandFrames(client_t *client, int require)
ptr += sizeof(*client->pendingcsqcbits)*client->max_net_ents; ptr += sizeof(*client->pendingcsqcbits)*client->max_net_ents;
for (i = 0; i < UPDATE_BACKUP; i++) for (i = 0; i < UPDATE_BACKUP; i++)
{ {
newframes[i].entities.max_entities = maxents; newframes[i].maxresend = maxlog;
newframes[i].qwentities.max_entities = 0;
newframes[i].resend = (void*)ptr; newframes[i].resend = (void*)ptr;
memcpy(newframes[i].resend, client->frameunion.frames[i].resend, sizeof(newframes[i].resend)*client->frameunion.frames[i].entities.num_entities); newframes[i].numresend = client->frameunion.frames[i].numresend;
memcpy(newframes[i].resend, client->frameunion.frames[i].resend, sizeof(newframes[i].resend)*newframes[i].numresend);
newframes[i].senttime = realtime; newframes[i].senttime = realtime;
} }
Z_Free(client->frameunion.frames); Z_Free(client->frameunion.frames);
@ -348,10 +350,11 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
qboolean writtenheader = false; qboolean writtenheader = false;
int viewerent; int viewerent;
int entnum; int entnum;
int lognum = client->frameunion.frames[currentsequence & UPDATE_MASK].entities.num_entities; client_frame_t *frame = &client->frameunion.frames[currentsequence & UPDATE_MASK];
int lognum = frame->numresend;
struct resendinfo_s *resend = client->frameunion.frames[currentsequence & UPDATE_MASK].resend; struct resendinfo_s *resend = frame->resend;
int maxlog = client->frameunion.frames[currentsequence & UPDATE_MASK].entities.max_entities; int maxlog = frame->maxresend;
//we don't check that we got some already - because this is delta compressed! //we don't check that we got some already - because this is delta compressed!
@ -391,7 +394,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
if (lognum > maxlog) if (lognum > maxlog)
{ {
SVFTE_ExpandFrames(client, lognum+1); SV_ExpandNackFrames(client, lognum+1);
break; break;
} }
resend[lognum].entnum = entnum; resend[lognum].entnum = entnum;
@ -444,7 +447,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
if (lognum > maxlog) if (lognum > maxlog)
{ {
SVFTE_ExpandFrames(client, lognum+1); SV_ExpandNackFrames(client, lognum+1);
break; break;
} }
resend[lognum].entnum = entnum; resend[lognum].entnum = entnum;
@ -478,7 +481,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
if (lognum > maxlog) if (lognum > maxlog)
{ {
SVFTE_ExpandFrames(client, lognum+1); SV_ExpandNackFrames(client, lognum+1);
break; break;
} }
resend[lognum].entnum = entnum; resend[lognum].entnum = entnum;
@ -514,7 +517,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
if (lognum > maxlog) if (lognum > maxlog)
{ {
SVFTE_ExpandFrames(client, lognum+1); SV_ExpandNackFrames(client, lognum+1);
break; break;
} }
resend[lognum].entnum = entnum; resend[lognum].entnum = entnum;
@ -540,7 +543,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
csqcnuments = 0; csqcnuments = 0;
client->frameunion.frames[currentsequence & UPDATE_MASK].entities.num_entities = lognum; frame->numresend = lognum;
//prevent the qc from trying to use it at inopertune times. //prevent the qc from trying to use it at inopertune times.
csqcmsgbuffer.maxsize = 0; csqcmsgbuffer.maxsize = 0;
@ -551,6 +554,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
void SV_CSQC_DroppedPacket(client_t *client, int sequence) void SV_CSQC_DroppedPacket(client_t *client, int sequence)
{ {
int i; int i;
client_frame_t *frame;
if (!ISQWCLIENT(client) && !ISNQCLIENT(client)) if (!ISQWCLIENT(client) && !ISNQCLIENT(client))
return; return;
@ -559,39 +563,35 @@ void SV_CSQC_DroppedPacket(client_t *client, int sequence)
Con_Printf("Server bug: No frames!\n"); Con_Printf("Server bug: No frames!\n");
return; return;
} }
frame = &client->frameunion.frames[sequence & UPDATE_MASK];
//skip it if we never generated that frame, to avoid pulling in stale data //skip it if we never generated that frame, to avoid pulling in stale data
if (client->frameunion.frames[sequence & UPDATE_MASK].sequence != sequence) if (frame->sequence != sequence)
{ {
// Con_Printf("SV: Stale %i\n", sequence); // Con_Printf("SV: Stale %i\n", sequence);
return; return;
} }
//lost entities need flagging for a resend //lost entities need flagging for a resend
if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) if (frame->numresend)
{ {
struct resendinfo_s *resend = client->frameunion.frames[sequence & UPDATE_MASK].resend; struct resendinfo_s *resend = frame->resend;
// Con_Printf("SV: Resend %i\n", sequence); // Con_Printf("SV: Resend %i\n", sequence);
i = client->frameunion.frames[sequence & UPDATE_MASK].entities.num_entities; i = frame->numresend;
while (i > 0) while (i > 0)
{ {
i--; i--;
// if (f[i] & UF_RESET)
// Con_Printf("Resend %i @ %i\n", i, sequence);
// if (f[i] & UF_REMOVE)
// Con_Printf("Remove %i @ %i\n", i, sequence);
client->pendingdeltabits[resend[i].entnum] |= resend[i].bits; client->pendingdeltabits[resend[i].entnum] |= resend[i].bits;
client->pendingcsqcbits[resend[i].entnum] |= resend[i].flags; client->pendingcsqcbits[resend[i].entnum] |= resend[i].flags;
} }
client->frameunion.frames[sequence & UPDATE_MASK].entities.num_entities = 0; frame->numresend = 0; //don't resend the same info twice!
} }
//lost stats do too //lost stats do too
if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) if (frame->numresendstats)
{ {
client_t *sp; client_t *sp;
unsigned short *n = client->frameunion.frames[sequence & UPDATE_MASK].resendstats; unsigned short *n = frame->resendstats;
i = client->frameunion.frames[sequence & UPDATE_MASK].numresendstats; i = frame->numresendstats;
while(i-->0) while(i-->0)
{ {
unsigned short s = n[i]; unsigned short s = n[i];
@ -608,7 +608,7 @@ void SV_CSQC_DroppedPacket(client_t *client, int sequence)
else else
client->pendingstats[s>>5u] |= 1u << (s & 0x1fu); client->pendingstats[s>>5u] |= 1u << (s & 0x1fu);
} }
client->frameunion.frames[sequence & UPDATE_MASK].numresendstats = 0; frame->numresendstats = 0;
} }
} }
@ -1532,7 +1532,7 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
/*cache frame info*/ /*cache frame info*/
resend = client->frameunion.frames[sequence & UPDATE_MASK].resend; resend = client->frameunion.frames[sequence & UPDATE_MASK].resend;
outno = 0; outno = 0;
outmax = client->frameunion.frames[sequence & UPDATE_MASK].entities.max_entities; outmax = client->frameunion.frames[sequence & UPDATE_MASK].maxresend;
/*start writing the packet*/ /*start writing the packet*/
MSG_WriteByte (msg, svcfte_updateentities); MSG_WriteByte (msg, svcfte_updateentities);
@ -1564,7 +1564,7 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
} }
if (outno >= outmax) if (outno >= outmax)
{ //expand the frames. may need some copying... { //expand the frames. may need some copying...
SVFTE_ExpandFrames(client, outno+1); SV_ExpandNackFrames(client, outno+1);
break; break;
} }
@ -1615,7 +1615,7 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
else else
client->nextdeltaindex = j; //we overflowed or something, start going round-robin client->nextdeltaindex = j; //we overflowed or something, start going round-robin
client->frameunion.frames[sequence & UPDATE_MASK].entities.num_entities = outno; client->frameunion.frames[sequence & UPDATE_MASK].numresend = outno;
client->frameunion.frames[sequence & UPDATE_MASK].sequence = sequence; client->frameunion.frames[sequence & UPDATE_MASK].sequence = sequence;
return overflow; return overflow;
} }
@ -1642,7 +1642,7 @@ void SVQW_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t
if (client->delta_sequence != -1) if (client->delta_sequence != -1)
{ {
fromframe = &client->frameunion.frames[client->delta_sequence & UPDATE_MASK]; fromframe = &client->frameunion.frames[client->delta_sequence & UPDATE_MASK];
from = &fromframe->entities; from = &fromframe->qwentities;
oldmax = from->num_entities; oldmax = from->num_entities;
MSG_WriteByte (msg, svc_deltapacketentities); MSG_WriteByte (msg, svc_deltapacketentities);
@ -1916,122 +1916,148 @@ void SVDP_EmitEntityDelta(unsigned int bits, entity_state_t *to, sizebuf_t *msg,
MSG_WriteShort(msg, to->u.q1.traileffectnum); MSG_WriteShort(msg, to->u.q1.traileffectnum);
} }
void SVDP_EmitEntitiesUpdate (client_t *client, packet_entities_t *to, sizebuf_t *msg) void SVDP_EmitEntitiesUpdate (client_t *client, client_frame_t *frame, packet_entities_t *to, sizebuf_t *msg)
{ {
packet_entities_t *from; packet_entities_t *cur;
int oldindex, newindex; int newindex;
int oldnum, newnum; int curnum, newnum;
int oldmax;
int j; int j;
int sequence = client->netchan.incoming_sequence;
// this is the frame that we are going to delta update from // this is the frame that we are going to delta update from
cur = &client->sentents;
if (!client->netchan.incoming_sequence) if (!client->netchan.incoming_sequence)
{ { //first packet deltas from nothing.
oldmax = 0; //so make sure we start with nothing
from = NULL; cur->num_entities = 0;
}
else
{
from = &client->sentents;
oldmax = from->num_entities;
} }
if (to->num_entities) if (to->num_entities)
{ {
j = to->entities[to->num_entities-1].number+1; j = to->entities[to->num_entities-1].number+1;
if (j > from->max_entities) if (j > cur->max_entities)
{ {
from->entities = BZ_Realloc(from->entities, sizeof(*from->entities) * j); cur->entities = BZ_Realloc(cur->entities, sizeof(*cur->entities) * j);
memset(&from->entities[from->max_entities], 0, sizeof(from->entities[0]) * (j - from->max_entities)); memset(&cur->entities[cur->max_entities], 0, sizeof(cur->entities[0]) * (j - cur->max_entities));
from->max_entities = j; cur->max_entities = j;
} }
while(j > client->sentents.num_entities) while(j > cur->num_entities)
{ {
from->entities[from->num_entities].number = 0; cur->entities[cur->num_entities].number = 0;
from->num_entities++; cur->num_entities++;
} }
} }
//diff the from+to states, flagging any changed state (which is combined with any state from previous packet loss //diff the from+to states, flagging any changed state (which is combined with any state from previous packet loss
newindex = 0; newindex = 0;
oldindex = 0; curnum = 0;
while (newindex < to->num_entities || oldindex < oldmax) while (newindex < to->num_entities || curnum < cur->num_entities)
{ {
newnum = newindex >= to->num_entities ? 0x7fff : to->entities[newindex].number; newnum = newindex >= to->num_entities ? 0x8000 : to->entities[newindex].number;
oldnum = oldindex >= oldmax ? 0x7fff : from->entities[oldindex].number;
if (newnum < oldnum) if (newnum == curnum)
{ // this is a new entity, send it from the baseline... as far as dp understands it... {
client->pendingdeltabits[newnum] |= E5_FULLUPDATE | SVDP_CalcDelta(&nullentitystate, NULL, &to->entities[oldindex], to->bonedata); if (cur->entities[curnum].number)
newindex++; { //regular update
} client->pendingdeltabits[newnum] |= SVDP_CalcDelta(&cur->entities[curnum], NULL/*cur->bonedata*/, &to->entities[newindex], to->bonedata);
else if (newnum > oldnum) if (client->pendingdeltabits[newnum] & E5_SERVERREMOVE)
{ // the old entity isn't present in the new message { //if it got flagged for removal, but its actually a valid entity, then assume that its an outdated remove and just flag it for a full update in case stuff got lost.
client->pendingdeltabits[oldnum] = E5_SERVERREMOVE; client->pendingdeltabits[newnum] &= ~E5_SERVERREMOVE;
oldindex++; client->pendingdeltabits[newnum] |= E5_FULLUPDATE;
} }
else
{ // delta update from old position
client->pendingdeltabits[newnum] |= SVDP_CalcDelta(&from->entities[oldindex], NULL/*from->bonedata*/, &to->entities[oldindex], to->bonedata);
if (client->pendingdeltabits[newnum] & E5_SERVERREMOVE)
{ //if it got flagged for removal, but its actually a valid entity, then assume that its an outdated remove and just flag it for a full update in case stuff got lost.
client->pendingdeltabits[newnum] &= ~E5_SERVERREMOVE;
client->pendingdeltabits[newnum] |= E5_FULLUPDATE;
} }
oldindex++; else
{ //this ent is new
//dpp5+ does not use baselines. it just resets from default state.
client->pendingdeltabits[newnum] = E5_FULLUPDATE | SVDP_CalcDelta(&nullentitystate, NULL, &to->entities[newindex], to->bonedata);
}
cur->entities[curnum] = to->entities[newindex];
newindex++; newindex++;
} }
else if (cur->entities[curnum].number)
{ //this entity was apparently removed since last time.
cur->entities[curnum].number = 0;
client->pendingdeltabits[curnum] = E5_SERVERREMOVE;
}
curnum++;
} }
to = cur;
//loop through all ents and send them as required //loop through all ents and send them as required
// Con_Printf ("frame %i\n", client->netchan.incoming_sequence); // Con_Printf ("frame %i\n", client->netchan.incoming_sequence);
MSG_WriteByte(msg, svcdp_entities);
MSG_WriteLong(msg, client->netchan.incoming_sequence); //sequence for the client to ack (any bits sent in unacked frames will be re-queued)
if (client->protocol == SCP_DARKPLACES7)
MSG_WriteLong(msg, client->last_sequence); //movement sequence that we are acking.
client->netchan.incoming_sequence++;
//add in the bitmasks of dropped packets.
/* newindex = 0;
oldindex = 0;
//Con_Printf ("---%i to %i ----\n", client->delta_sequence & UPDATE_MASK
// , client->netchan.outgoing_sequence & UPDATE_MASK);
while (newindex < to->num_entities || oldindex < oldmax)
{ {
newnum = newindex >= to->num_entities ? 0x7fff : to->entities[newindex].number; unsigned int bits;
oldnum = oldindex >= oldmax ? 0x7fff : from->entities[oldindex].number; int outno, outmax = frame->maxresend;
qboolean overflow = false;
struct resendinfo_s *resend = frame->resend;
if (newnum == oldnum) MSG_WriteByte(msg, svcdp_entities);
{ // delta update from old position MSG_WriteLong(msg, sequence); //sequence for the client to ack (any bits sent in unacked frames will be re-queued)
//Con_Printf ("delta %i\n", newnum); if (client->protocol == SCP_DARKPLACES7)
SVDP_EmitEntityDelta (&from->entities[oldindex], &to->entities[newindex], msg, false, to->bonedata); MSG_WriteLong(msg, client->last_sequence); //movement sequence that we are acking.
oldindex++;
newindex++;
continue;
}
if (newnum < oldnum) client->netchan.incoming_sequence++;
{ // this is a new entity, send it from the baseline... as far as dp understands it...
//Con_Printf ("baseline %i\n", newnum);
SVDP_EmitEntityDelta (&nullentitystate, &to->entities[newindex], msg, true, to->bonedata);
newindex++;
continue;
}
if (newnum > oldnum) //add in the bitmasks of dropped packets.
{ // the old entity isn't present in the new message for(outno = 0, j = 1; j < to->num_entities; j++)
// Con_Printf("sRemove %i\n", oldnum); {
MSG_WriteShort(msg, oldnum | 0x8000); bits = client->pendingdeltabits[j];
oldindex++; if (!bits)
continue; continue;
if (msg->cursize + 50 > msg->maxsize)
{
overflow = true;
break; /*give up if it gets full. FIXME: bone data is HUGE.*/
}
if (outno >= outmax)
{ //expand the frames. may need some copying...
SV_ExpandNackFrames(client, outno+1);
break;
}
if (bits & E5_SERVERREMOVE)
{ //if reset is set, then reset was set eroneously.
MSG_WriteShort(msg, j | 0x8000);
resend[outno].bits = E5_SERVERREMOVE;
// Con_Printf("REMOVE %i @ %i\n", j, sequence);
}
else if (to->entities[j].number) /*only send a new copy of the ent if they actually have one already*/
{
//if we didn't reach the end in the last packet, start at that point to avoid spam
//player slots are exempt from this, so they are in every packet (strictly speaking only the local player 'needs' this, but its nice to have it for high-priority targets too)
if (j < client->nextdeltaindex && j > svs.allocated_client_slots)
continue;
if (bits & E5_FULLUPDATE)
{
/*flag the entity for the next packet, so we always get two resets when it appears, to reduce the effects of packetloss on seeing rockets etc*/
bits = E5_FULLUPDATE | SVDP_CalcDelta(&nullentitystate, NULL, &to->entities[j], to->bonedata);
resend[outno].bits = E5_FULLUPDATE;
// Con_Printf("RESET %i @ %i\n", j, sequence);
}
else
resend[outno].bits = bits;
SVDP_EmitEntityDelta (bits, &to->entities[j], msg, to->bonedata);
}
client->pendingdeltabits[j] = 0;
resend[outno].flags = 0;
resend[outno++].entnum = j;
} }
MSG_WriteShort(msg, 0x8000); //dp5+ uses 'remove world' as a terminator.
frame->numresend = outno;
frame->sequence = sequence;
if (j == to->num_entities) //looks like we sent them all
client->nextdeltaindex = 0; //start afresh with the next packet.
else
client->nextdeltaindex = j; //we overflowed or something, start going round-robin
} }
*/
MSG_WriteShort(msg, 0x8000);
} }
#endif #endif
@ -3965,7 +3991,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
} }
host_client = client; host_client = client;
if ((client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) || !frame->entities.entities) if ((client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) || !frame->qwentities.entities || ISNQCLIENT(client))
{ {
pack = &svs.entstatebuffer; pack = &svs.entstatebuffer;
if (pack->max_entities < client->max_net_ents) if (pack->max_entities < client->max_net_ents)
@ -3976,7 +4002,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
} }
} }
else else
pack = &frame->entities; pack = &frame->qwentities;
SV_Snapshot_Clear(pack); SV_Snapshot_Clear(pack);
if (!pack->entities) if (!pack->entities)
@ -4024,7 +4050,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
} }
} }
else if (client->protocol == SCP_DARKPLACES6 || client->protocol == SCP_DARKPLACES7) else if (client->protocol == SCP_DARKPLACES6 || client->protocol == SCP_DARKPLACES7)
SVDP_EmitEntitiesUpdate(client, pack, msg); SVDP_EmitEntitiesUpdate(client, frame, pack, msg);
else else
{ {
for (e = 0; e < pack->num_entities; e++) for (e = 0; e < pack->num_entities; e++)

View File

@ -271,14 +271,40 @@ void SVQ1_CreateBaseline (void)
} }
} }
void SV_SpawnParmsToQC(client_t *client)
{
int i;
// copy spawn parms out of the client_t
for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
{
if (pr_global_ptrs->spawnparamglobals[i])
*pr_global_ptrs->spawnparamglobals[i] = client->spawn_parms[i];
}
if (pr_global_ptrs->parm_string)
*pr_global_ptrs->parm_string = client->spawn_parmstring?PR_TempString(sv.world.progs, client->spawn_parmstring):0;
}
void SV_SpawnParmsToClient(client_t *client)
{
int i;
for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
{
if (pr_global_ptrs->spawnparamglobals[i])
client->spawn_parms[i] = *pr_global_ptrs->spawnparamglobals[i];
else
client->spawn_parms[i] = 0;
}
Z_Free(client->spawn_parmstring);
if (pr_global_ptrs->parm_string)
client->spawn_parmstring = Z_StrDup(PR_GetString(sv.world.progs, *pr_global_ptrs->parm_string));
else
client->spawn_parmstring = NULL;
}
void SV_SaveSpawnparmsClient(client_t *client, float *transferparms) void SV_SaveSpawnparmsClient(client_t *client, float *transferparms)
{ {
int j; int j;
for (j=0 ; j<NUM_SPAWN_PARMS ; j++) SV_SpawnParmsToQC(client);
{
if (pr_global_ptrs->spawnparamglobals[j])
*pr_global_ptrs->spawnparamglobals[j] = client->spawn_parms[j];
}
#ifdef VM_Q1 #ifdef VM_Q1
if (svs.gametype == GT_Q1QVM) if (svs.gametype == GT_Q1QVM)
@ -314,11 +340,7 @@ void SV_SaveSpawnparmsClient(client_t *client, float *transferparms)
} }
else else
{ {
for (j=0 ; j<NUM_SPAWN_PARMS ; j++) SV_SpawnParmsToClient(client);
{
if (pr_global_ptrs->spawnparamglobals[j])
client->spawn_parms[j] = *pr_global_ptrs->spawnparamglobals[j];
}
} }
// call the progs to get default spawn parms for the new client // call the progs to get default spawn parms for the new client
@ -394,8 +416,6 @@ void SV_SaveSpawnparms (void)
void SV_GetNewSpawnParms(client_t *cl) void SV_GetNewSpawnParms(client_t *cl)
{ {
int i;
if (svprogfuncs) //q2 dlls don't use parms in this manner. It's all internal to the dll. if (svprogfuncs) //q2 dlls don't use parms in this manner. It's all internal to the dll.
{ {
// call the progs to get default spawn parms for the new client // call the progs to get default spawn parms for the new client
@ -408,13 +428,8 @@ void SV_GetNewSpawnParms(client_t *cl)
if (pr_global_ptrs->SetNewParms) if (pr_global_ptrs->SetNewParms)
PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms); PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms);
} }
for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
{ SV_SpawnParmsToClient(cl);
if (pr_global_ptrs->spawnparamglobals[i])
cl->spawn_parms[i] = *pr_global_ptrs->spawnparamglobals[i];
else
cl->spawn_parms[i] = 0;
}
} }
} }
@ -1645,14 +1660,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
{ {
sv_player = host_client->edict; sv_player = host_client->edict;
SV_ExtractFromUserinfo(host_client, true); SV_ExtractFromUserinfo(host_client, true);
SV_SpawnParmsToQC(host_client);
// copy spawn parms out of the client_t
for (j=0 ; j< NUM_SPAWN_PARMS ; j++)
{
if (pr_global_ptrs->spawnparamglobals[j])
*pr_global_ptrs->spawnparamglobals[j] = host_client->spawn_parms[j];
}
SV_SetUpClientEdict(host_client, sv_player); SV_SetUpClientEdict(host_client, sv_player);
#ifndef NOLEGACY #ifndef NOLEGACY
sv_player->xv->clientcolors = atoi(Info_ValueForKey(host_client->userinfo, "topcolor"))*16 + atoi(Info_ValueForKey(host_client->userinfo, "bottomcolor")); sv_player->xv->clientcolors = atoi(Info_ValueForKey(host_client->userinfo, "topcolor"))*16 + atoi(Info_ValueForKey(host_client->userinfo, "bottomcolor"));

View File

@ -1968,7 +1968,7 @@ void SV_ClientProtocolExtensionsChanged(client_t *client)
ptr += sizeof(*client->pendingcsqcbits)*client->max_net_ents; ptr += sizeof(*client->pendingcsqcbits)*client->max_net_ents;
for (i = 0; i < UPDATE_BACKUP; i++) for (i = 0; i < UPDATE_BACKUP; i++)
{ {
client->frameunion.frames[i].entities.max_entities = maxents; client->frameunion.frames[i].maxresend = maxents;
client->frameunion.frames[i].resend = (void*)ptr; client->frameunion.frames[i].resend = (void*)ptr;
ptr += sizeof(*client->frameunion.frames[i].resend)*maxents; ptr += sizeof(*client->frameunion.frames[i].resend)*maxents;
client->frameunion.frames[i].senttime = realtime; client->frameunion.frames[i].senttime = realtime;
@ -1982,8 +1982,8 @@ void SV_ClientProtocolExtensionsChanged(client_t *client)
client->frameunion.frames = Z_Malloc((sizeof(client_frame_t))*UPDATE_BACKUP); client->frameunion.frames = Z_Malloc((sizeof(client_frame_t))*UPDATE_BACKUP);
for (i = 0; i < UPDATE_BACKUP; i++) for (i = 0; i < UPDATE_BACKUP; i++)
{ {
client->frameunion.frames[i].entities.max_entities = 0; client->frameunion.frames[i].qwentities.max_entities = 0;
client->frameunion.frames[i].entities.entities = NULL; client->frameunion.frames[i].qwentities.entities = NULL;
client->frameunion.frames[i].senttime = realtime; client->frameunion.frames[i].senttime = realtime;
} }
} }
@ -1992,8 +1992,8 @@ void SV_ClientProtocolExtensionsChanged(client_t *client)
client->frameunion.frames = Z_Malloc((sizeof(client_frame_t)+sizeof(entity_state_t)*maxpacketentities)*UPDATE_BACKUP); client->frameunion.frames = Z_Malloc((sizeof(client_frame_t)+sizeof(entity_state_t)*maxpacketentities)*UPDATE_BACKUP);
for (i = 0; i < UPDATE_BACKUP; i++) for (i = 0; i < UPDATE_BACKUP; i++)
{ {
client->frameunion.frames[i].entities.max_entities = maxpacketentities; client->frameunion.frames[i].qwentities.max_entities = maxpacketentities;
client->frameunion.frames[i].entities.entities = (entity_state_t*)(client->frameunion.frames+UPDATE_BACKUP) + i*client->frameunion.frames[i].entities.max_entities; client->frameunion.frames[i].qwentities.entities = (entity_state_t*)(client->frameunion.frames+UPDATE_BACKUP) + i*client->frameunion.frames[i].qwentities.max_entities;
client->frameunion.frames[i].senttime = realtime; client->frameunion.frames[i].senttime = realtime;
} }
} }

View File

@ -1569,10 +1569,13 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
edict_t *ent; edict_t *ent;
int i; int i;
float newa; float newa;
client_t *controller;
ent = client->edict; ent = client->edict;
if (client->controller) if (client->controller)
client = client->controller; controller = client->controller;
else
controller = client;
if (!ent) if (!ent)
return; return;
@ -1613,8 +1616,8 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
if (!client->lockangles) if (!client->lockangles)
{ {
//try to keep them vaugely reliable. //try to keep them vaugely reliable.
if (client->netchan.message.cursize < client->netchan.message.maxsize/2) if (controller->netchan.message.cursize < controller->netchan.message.maxsize/2)
msg = &client->netchan.message; msg = &controller->netchan.message;
} }
if (pnum) if (pnum)
@ -1622,7 +1625,7 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
MSG_WriteByte(msg, svcfte_choosesplitclient); MSG_WriteByte(msg, svcfte_choosesplitclient);
MSG_WriteByte(msg, pnum); MSG_WriteByte(msg, pnum);
} }
if (!client->lockangles && (client->fteprotocolextensions2 & PEXT2_SETANGLEDELTA) && client->delta_sequence != -1 && !client->viewent) if (!client->lockangles && (controller->fteprotocolextensions2 & PEXT2_SETANGLEDELTA) && controller->delta_sequence != -1 && !client->viewent)
{ {
MSG_WriteByte (msg, svcfte_setangledelta); MSG_WriteByte (msg, svcfte_setangledelta);
for (i=0 ; i < 3 ; i++) for (i=0 ; i < 3 ; i++)

View File

@ -528,8 +528,8 @@ void SVNQ_New_f (void)
qboolean big; //used as a filter to exclude protocols that don't match our coord+angles mode qboolean big; //used as a filter to exclude protocols that don't match our coord+angles mode
} preferedprot[] = } preferedprot[] =
{ {
// {SCP_DARKPLACES7, true}, {SCP_DARKPLACES7, true},
// {SCP_DARKPLACES6, true}, {SCP_DARKPLACES6, true},
{SCP_FITZ666, true}, //actually 999... shh... {SCP_FITZ666, true}, //actually 999... shh...
{SCP_FITZ666, false}, {SCP_FITZ666, false},
{SCP_BJP3, false} {SCP_BJP3, false}
@ -604,7 +604,7 @@ void SVNQ_New_f (void)
protoname = "NQ"; protoname = "NQ";
} }
break; break;
/*case SCP_DARKPLACES6: case SCP_DARKPLACES6:
SV_LogPlayer(host_client, "new (DP6)"); SV_LogPlayer(host_client, "new (DP6)");
protmain = PROTOCOL_VERSION_DP6; protmain = PROTOCOL_VERSION_DP6;
protext1 &= ~PEXT_FLOATCOORDS; //always enabled, try not to break things protext1 &= ~PEXT_FLOATCOORDS; //always enabled, try not to break things
@ -615,7 +615,7 @@ void SVNQ_New_f (void)
protmain = PROTOCOL_VERSION_DP7; protmain = PROTOCOL_VERSION_DP7;
protext1 &= ~PEXT_FLOATCOORDS; //always enabled, try not to break things protext1 &= ~PEXT_FLOATCOORDS; //always enabled, try not to break things
protoname = "DPP7"; protoname = "DPP7";
break;*/ break;
default: default:
host_client->drop = true; host_client->drop = true;
protoname = "?""?""?"; protoname = "?""?""?";
@ -1824,14 +1824,12 @@ void SV_SpawnSpectator (void)
return; return;
} }
} }
} }
void SV_Begin_Core(client_t *split) void SV_Begin_Core(client_t *split)
{ //this is the client-protocol-independant core, for q1/q2 gamecode { //this is the client-protocol-independant core, for q1/q2 gamecode
client_t *oh; client_t *oh;
int i;
#ifdef HEXEN2 #ifdef HEXEN2
if (progstype == PROG_H2 && split->playerclass) if (progstype == PROG_H2 && split->playerclass)
split->edict->xv->playerclass = split->playerclass; //make sure it's set the same as the userinfo split->edict->xv->playerclass = split->playerclass; //make sure it's set the same as the userinfo
@ -1878,11 +1876,7 @@ void SV_Begin_Core(client_t *split)
// copy spawn parms out of the client_t // copy spawn parms out of the client_t
for (i=0 ; i< NUM_SPAWN_PARMS ; i++) SV_SpawnParmsToQC(split);
{
if (pr_global_ptrs->spawnparamglobals[i])
*pr_global_ptrs->spawnparamglobals[i] = split->spawn_parms[i];
}
// call the spawn function // call the spawn function
pr_global_struct->time = sv.world.physicstime; pr_global_struct->time = sv.world.physicstime;
@ -1912,11 +1906,7 @@ void SV_Begin_Core(client_t *split)
eval2 = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "stats_restored", ev_float, NULL); eval2 = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "stats_restored", ev_float, NULL);
if (eval2) if (eval2)
eval2->_float = 1; eval2->_float = 1;
for (j=0 ; j< NUM_SPAWN_PARMS ; j++) SV_SpawnParmsToQC(split);
{
if (pr_global_ptrs->spawnparamglobals[j])
*pr_global_ptrs->spawnparamglobals[j] = split->spawn_parms[j];
}
pr_global_struct->time = sv.world.physicstime; pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent);
G_FLOAT(OFS_PARM0) = sv.time - split->spawninfotime; G_FLOAT(OFS_PARM0) = sv.time - split->spawninfotime;
@ -1925,11 +1915,7 @@ void SV_Begin_Core(client_t *split)
else else
{ {
// copy spawn parms out of the client_t // copy spawn parms out of the client_t
for (i=0 ; i< NUM_SPAWN_PARMS ; i++) SV_SpawnParmsToQC(split);
{
if (pr_global_ptrs->spawnparamglobals[i])
*pr_global_ptrs->spawnparamglobals[i] = split->spawn_parms[i];
}
// call the spawn function // call the spawn function
#ifdef VM_Q1 #ifdef VM_Q1
@ -4991,13 +4977,8 @@ void Cmd_Join_f (void)
#endif #endif
if (pr_global_ptrs->SetNewParms) if (pr_global_ptrs->SetNewParms)
PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms); PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms);
for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
{ SV_SpawnParmsToClient(host_client);
if (pr_global_ptrs->spawnparamglobals[i])
host_client->spawn_parms[i] = *pr_global_ptrs->spawnparamglobals[i];
else
host_client->spawn_parms[i] = 0;
}
#ifdef VM_Q1 #ifdef VM_Q1
if (svs.gametype == GT_Q1QVM) if (svs.gametype == GT_Q1QVM)
@ -5131,14 +5112,8 @@ void Cmd_Observe_f (void)
#endif #endif
if (pr_global_ptrs->SetNewParms) if (pr_global_ptrs->SetNewParms)
PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms); PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms);
for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
{
if (pr_global_ptrs->spawnparamglobals[i])
host_client->spawn_parms[i] = *pr_global_ptrs->spawnparamglobals[i];
else
host_client->spawn_parms[i] = 0;
}
SV_SpawnParmsToClient(host_client);
SV_SpawnSpectator (); SV_SpawnSpectator ();
// call the spawn function // call the spawn function
@ -5372,7 +5347,6 @@ static void SVNQ_Spawn_f (void)
static void SVNQ_Begin_f (void) static void SVNQ_Begin_f (void)
{ {
unsigned pmodel = 0, emodel = 0; unsigned pmodel = 0, emodel = 0;
int i;
qboolean sendangles=false; qboolean sendangles=false;
if (host_client->state == cs_spawned) if (host_client->state == cs_spawned)
@ -5394,11 +5368,7 @@ static void SVNQ_Begin_f (void)
if (SpectatorConnect) if (SpectatorConnect)
{ {
// copy spawn parms out of the client_t // copy spawn parms out of the client_t
for (i=0 ; i< NUM_SPAWN_PARMS ; i++) SV_SpawnParmsToQC(host_client);
{
if (pr_global_ptrs->spawnparamglobals[i])
*pr_global_ptrs->spawnparamglobals[i] = host_client->spawn_parms[i];
}
// call the spawn function // call the spawn function
pr_global_struct->time = sv.world.physicstime; pr_global_struct->time = sv.world.physicstime;
@ -5412,11 +5382,7 @@ static void SVNQ_Begin_f (void)
sv.spawned_client_slots++; sv.spawned_client_slots++;
// copy spawn parms out of the client_t // copy spawn parms out of the client_t
for (i=0 ; i< NUM_SPAWN_PARMS ; i++) SV_SpawnParmsToQC(host_client);
{
if (pr_global_ptrs->spawnparamglobals[i])
*pr_global_ptrs->spawnparamglobals[i] = host_client->spawn_parms[i];
}
sv.skipbprintclient = host_client; sv.skipbprintclient = host_client;
#ifdef VM_Q1 #ifdef VM_Q1
@ -5951,6 +5917,7 @@ ucmd_t nqucmds[] =
{"playermodel", NULL}, {"playermodel", NULL},
{"playerskin", NULL}, {"playerskin", NULL},
{"rate", SV_Rate_f}, {"rate", SV_Rate_f},
{"rate_burstsize", NULL},
#ifdef SVRANKING #ifdef SVRANKING
{"topten", Rank_ListTop10_f}, {"topten", Rank_ListTop10_f},

View File

@ -3977,10 +3977,15 @@ void VK_UploadLightmap(lightmapinfo_t *lm)
mips.mip[0].needfree = false; mips.mip[0].needfree = false;
mips.mip[0].width = lm->width; mips.mip[0].width = lm->width;
mips.mip[0].height = lm->height; mips.mip[0].height = lm->height;
if (lightmap_bgra) switch(lightmap_fmt)
{
case TF_BGRA32:
mips.encoding = PTI_BGRX8; mips.encoding = PTI_BGRX8;
else break;
mips.encoding = PTI_RGBX8; default:
Sys_Error("Unsupported encoding\n");
break;
}
mips.mipcount = 1; mips.mipcount = 1;
VK_LoadTextureMips(tex, &mips); VK_LoadTextureMips(tex, &mips);
tex->status = TEX_LOADED; tex->status = TEX_LOADED;