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
qboolean Cam_DrawViewModel(playerview_t *pv)
{
if (cl.spectator)
if (pv->spectator)
{
if (pv->cam_state == CAM_EYECAM && cl_chasecam.ival)
return true;
@ -536,7 +536,7 @@ qboolean Cam_DrawViewModel(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 -1;
}
@ -822,7 +822,7 @@ void Cam_Track(playerview_t *pv, usercmd_t *cmd)
vec3_t vec;
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;
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)
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;
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
@ -1197,7 +1197,7 @@ void Cam_TrackPlayer(int seat, char *cmdname, char *plrarg)
return;
}
if (!cl.spectator)
if (!pv->spectator)
{
Con_Printf("Not spectating.\n");
return;

View File

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

View File

@ -1658,7 +1658,8 @@ void CLDP_ParseDarkPlaces5Entities(void) //the things I do.. :o(
}
else
{
// Con_Printf("Update %i\n", read);
if (cl_shownet.ival > 3)
Con_Printf("Update %i\n", read);
DP5_ParseDelta(to, newpack);
to->sequence = cls.netchan.incoming_sequence;
to->inactiveflag = 0;
@ -3780,6 +3781,7 @@ void CL_LinkPacketEntities (void)
le = &cl.lerpents[timer->entnum];
if (le->sequence != cl.lerpentssequence)
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);
}
@ -4716,7 +4718,7 @@ guess_pm_type:
for (i = 0; i < cl.splitclients; 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->statsf[STAT_WEAPONFRAME] = state->weaponframe;
@ -5290,7 +5292,7 @@ void CL_LinkViewModel(void)
ent.flags |= RF_WEAPONMODEL|RF_DEPTHHACK|RF_NOSHADOW;
plnum = -1;
if (cl.spectator)
if (pv->spectator)
plnum = Cam_TrackNum(pv);
if (plnum == -1)
plnum = r_refdef.playerview->playernum;
@ -5520,13 +5522,6 @@ void CL_SetUpPlayerPrediction(qboolean dopred)
CL_PredictUsercmd (0, j+1, state, &exact, &state->command);
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 x;
qboolean foundone;
playerview_t *pv = &cl.playerview[0];
x = 0;
foundone = false;
@ -172,7 +173,7 @@ static void Display_Ignorelist(void)
if (ignore_opponents.ival)
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");
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)
{
int slot, i;
int slot, i;
playerview_t *pv = &cl.playerview[0];
if (!ignore_mode.ival && (flags & 2))
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)))
return true;
else if (ignore_spec.ival == 1 && (flags == 4) && !cl.spectator)
else if (ignore_spec.ival == 1 && (flags == 4) && !pv->spectator)
return true;
if (!sendername)
@ -595,10 +597,10 @@ qboolean Ignore_Message(const char *sendername, const char *s, int flags)
if (ignore_opponents.ival && (
(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 &&
(!cl.teamplay || strcmp(cl.players[slot].team, cl.players[cl.playerview[0].playernum].team))
flags == 1 && !pv->spectator && slot != pv->playernum &&
(!cl.teamplay || strcmp(cl.players[slot].team, cl.players[pv->playernum].team))
)
{
return true;

View File

@ -273,7 +273,7 @@ void IN_JumpDown (void)
int pnum = CL_TargettedSplit(false);
playerview_t *pv = &cl.playerview[pnum];
condition = (cls.state == ca_active && cl_smartjump.ival && !prox_inmenu.ival);
@ -283,14 +283,14 @@ void IN_JumpDown (void)
else
#endif
#ifdef QUAKESTATS
if (condition && cl.playerview[pnum].stats[STAT_HEALTH] > 0 && !cls.demoplayback && !cl.spectator &&
(cls.protocol==CP_NETQUAKE || cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[cl.playerview[pnum].playernum].messagenum == cl.validsequence)
if (condition && cl.playerview[pnum].stats[STAT_HEALTH] > 0 && !cls.demoplayback && !pv->spectator &&
(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))
)
KeyDown(&in_up);
else
#endif
if (condition && cl.spectator && cl.playerview[pnum].cam_state == CAM_FREECAM)
if (condition && pv->spectator && pv->cam_state == CAM_FREECAM)
KeyDown(&in_up);
else
KeyDown(&in_jump);
@ -1404,6 +1404,7 @@ void CL_UpdateSeats(void)
targ = MAX_SPLITS;
if (cl.splitclients < targ)
{
char *ver;
char buffer[2048];
char newinfo[2048];
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).
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));
}
else if (cl.splitclients > targ)
@ -1736,6 +1745,7 @@ void CL_SendCmd (double frametime, qboolean mainloop)
}
for (plnum = 0; plnum < cl.splitclients; plnum++)
{
playerview_t *pv = &cl.playerview[plnum];
cmd = &cl.outframes[i].cmd[plnum];
memset(cmd, 0, sizeof(*cmd));
@ -1758,12 +1768,12 @@ void CL_SendCmd (double frametime, qboolean mainloop)
VectorClear(mousemovements[plnum]);
// if we are spectator, try autocam
if (cl.spectator)
Cam_Track(&cl.playerview[plnum], cmd);
if (pv->spectator)
Cam_Track(pv, cmd);
CL_FinishMove(cmd, cmd->msec, plnum);
Cam_FinishMove(&cl.playerview[plnum], cmd);
Cam_FinishMove(pv, cmd);
#ifdef CSQC_DAT
CSQC_Input_Frame(plnum, cmd);
@ -1772,7 +1782,6 @@ void CL_SendCmd (double frametime, qboolean mainloop)
if (cls.state == ca_active)
{
player_state_t *from, *to;
playerview_t *pv = &cl.playerview[plnum];
from = &cl.inframes[cl.ackedmovesequence & 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]);

View File

@ -1657,6 +1657,7 @@ This is also called on Host_Error, so it shouldn't cause any errors
void CL_Disconnect (void)
{
qbyte final[12];
int i;
connectinfo.trying = false;
@ -1741,7 +1742,8 @@ void CL_Disconnect (void)
COM_FlushTempoaryPacks();
r_worldentity.model = NULL;
cl.spectator = 0;
for (i = 0; i < cl.splitclients; i++)
cl.playerview[i].spectator = 0;
cl.sendprespawn = false;
cl.intermissionmode = IM_NONE;
cl.oldgametime = 0;
@ -2033,9 +2035,18 @@ void CL_CheckServerInfo(void)
unsigned int allowed;
#ifdef QUAKESTATS
int oldstate;
#endif
#ifndef CLIENTONLY
extern cvar_t sv_cheats;
#endif
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;
cl.teamplay = atoi(Info_ValueForKey(cl.serverinfo, "teamplay"));
@ -2073,7 +2084,8 @@ void CL_CheckServerInfo(void)
#ifndef CLIENTONLY
//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;
#endif
@ -3074,6 +3086,7 @@ void CL_ConnectionlessPacket (void)
COM_Parse(s);
if (!strcmp(com_token, "ccept"))
{
/*this is a DP server... but we don't know which version nor nq protocol*/
Con_Printf ("accept\n");
if (cls.state == ca_connected)
return; //we're already connected. don't do it again!
@ -3090,10 +3103,9 @@ void CL_ConnectionlessPacket (void)
CL_ParseEstablished();
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.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.challenge = connectinfo.challenge;
connectinfo.trying = false;
@ -3846,14 +3858,12 @@ void CL_ServerInfo_f(void)
}
#endif
/*
#ifdef WEBCLIENT
#ifdef FTPCLIENT
void CL_FTP_f(void)
{
FTP_Client_Command(Cmd_Args(), NULL);
}
#endif
*/
//fixme: make a cvar
void CL_Fog_f(void)
@ -3930,6 +3940,7 @@ void CL_Status_f(void)
switch(cls.protocol)
{
default:
case CP_UNKNOWN:
Con_Printf("Unknown protocol\n");
break;
@ -4230,9 +4241,9 @@ void CL_Init (void)
Cvar_Register (&qtvcl_forceversion1, cl_controlgroup);
Cvar_Register (&qtvcl_eztvextensions, cl_controlgroup);
//#ifdef WEBCLIENT
// Cmd_AddCommand ("ftp", CL_FTP_f);
//#endif
#ifdef FTPCLIENT
Cmd_AddCommand ("ftp", CL_FTP_f);
#endif
Cmd_AddCommandD ("changing", CL_Changing_f, "Part of network protocols. This command should not be used manually.");
Cmd_AddCommand ("disconnect", CL_Disconnect_f);
@ -5538,7 +5549,7 @@ double Host_Frame (double time)
extern cvar_t scr_chatmodecvar, r_stereo_method;
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
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].viewentity = 0; //free floating.
cl.playerview[j].spectator = true;
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].messagenum = 1;
}
}
cl.spectator = true;
cl.splitclients = 1;
}
else if (cls.fteprotocolextensions2 & PEXT2_MAXPLAYERS)
{
qboolean spec = false;
cl.allocated_client_slots = MSG_ReadByte();
if (cl.allocated_client_slots > MAX_CLIENTS)
{
@ -3109,13 +3110,14 @@ static void CLQW_ParseServerData (void)
cl.splitclients = MSG_ReadByte();
if (cl.splitclients & 128)
{
cl.spectator = true;
spec = true;
cl.splitclients &= ~128;
}
if (cl.splitclients > MAX_SPLITS)
Host_EndGame("Server sent us too many alternate clients\n");
for (pnum = 0; pnum < cl.splitclients; pnum++)
{
cl.playerview[pnum].spectator = true;
if (cls.z_ext & Z_EXT_VIEWHEIGHT)
cl.playerview[pnum].viewheight = 0;
cl.playerview[pnum].playernum = MSG_ReadByte();
@ -3137,9 +3139,11 @@ static void CLQW_ParseServerData (void)
cl.playerview[clnum].playernum = pnum;
if (cl.playerview[clnum].playernum & 128)
{
cl.spectator = true;
cl.playerview[clnum].spectator = true;
cl.playerview[clnum].playernum &= ~128;
}
else
cl.playerview[clnum].spectator = false;
if (cl.playerview[clnum].playernum >= cl.allocated_client_slots)
Host_EndGame("unsupported local player slot\n");
@ -3309,8 +3313,8 @@ static void CLQ2_ParseServerData (void)
// parse player entity number
cl.playerview[0].playernum = MSG_ReadShort ();
cl.playerview[0].viewentity = cl.playerview[0].playernum+1;
cl.playerview[0].spectator = false;
cl.splitclients = 1;
cl.spectator = false;
cl.numq2visibleweapons = 1; //give it a default.
cl.q2visibleweapons[0] = "weapon.md2";
@ -4884,7 +4888,7 @@ void CL_NewTranslation (int slot)
bottom = player->rbottomcolor;
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]);
if (local < 0)
@ -4977,11 +4981,14 @@ static void CL_ProcessUserInfo (int slot, player_info_t *player)
player->colourised = TP_FindColours(player->name);
// 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++)
{
Cam_Unlock(&cl.playerview[i]);
@ -4993,7 +5000,7 @@ static void CL_ProcessUserInfo (int slot, player_info_t *player)
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();
else if (cls.state == ca_active)
Skin_Find (player);
@ -6104,7 +6111,8 @@ static void CL_ParseWeaponStats(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)),
atof(Cmd_Argv(2)),
atof(Cmd_Argv(3))};
@ -6113,6 +6121,15 @@ static void CL_ParseItemTimer(void)
// char *timername = Cmd_Argv(6);
unsigned int entnum = strtoul(Cmd_Argv(7), NULL, 0);
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)
timeout = FLT_MAX;
@ -6121,7 +6138,12 @@ static void CL_ParseItemTimer(void)
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;
}
if (!timer)
@ -6137,8 +6159,8 @@ static void CL_ParseItemTimer(void)
timer->radius = radius;
timer->duration = timeout;
timer->entnum = entnum;
timer->start = cl.time;
timer->end = cl.time + timer->duration;
timer->start = start;
timer->end = start + timer->duration;
timer->rgb[0] = ((rgb>>16)&0xff)/255.0;
timer->rgb[1] = ((rgb>> 8)&0xff)/255.0;
timer->rgb[2] = ((rgb )&0xff)/255.0;
@ -6931,7 +6953,7 @@ void CLQW_ParseServerMessage (void)
if (cl.intermissionmode == IM_NONE)
{
TP_ExecTrigger ("f_mapend", false);
if (cl.spectator)
if (cl.playerview[destsplit].spectator)
TP_ExecTrigger ("f_specmapend", true);
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)
{
//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
return;
@ -912,7 +912,7 @@ void CL_PredictMovePNum (int seat)
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)
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)
{
#ifdef QUAKEHUD
extern qboolean sb_showscores;
#endif
int pnum;
cprint_t *p;
@ -731,7 +728,7 @@ void SCR_CheckDrawCenterString (void)
continue; //should probably allow the console with a scissor region or something.
#ifdef QUAKEHUD
if (sb_showscores) //this was annoying
if (cl.playerview[pnum].sb_showscores) //this was annoying
continue;
#endif
@ -3066,7 +3063,7 @@ void SCR_DrawTwoDimensional(int uimenu, qboolean nohud)
}
else if (cl.intermissionmode != IM_NONE)
{
Sbar_IntermissionOverlay ();
Sbar_IntermissionOverlay (r_refdef.playerview);
}
else
{

View File

@ -599,6 +599,7 @@ struct playerview_s
{
int playernum; //cl.players index for this player.
qboolean nolocalplayer; //inhibit use of qw-style players, predict based on entities.
qboolean spectator;
#ifdef PEXT_SETVIEW
int viewentity; //view is attached to this entity.
#endif
@ -610,12 +611,16 @@ struct playerview_s
float item_gettime[32]; // cl.time of aquiring item, for blinking
float faceanimtime; // use anim frame if cl.time < this
#ifdef QUAKEHUD
qboolean sb_showscores;
qboolean sb_showteamscores;
#ifdef HEXEN2
int sb_hexen2_cur_item;//hexen2 hud
float sb_hexen2_item_time;
qboolean sb_hexen2_extra_info;//show the extra stuff
qboolean sb_hexen2_infoplaque;
#endif
#endif
// the client maintains its own idea of view angles, which are
@ -752,7 +757,7 @@ typedef struct
// render a frame yet
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_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)
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
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!
if (cl.spectator || cls.demoplayback)
if (cl.playerview[i].spectator || cls.demoplayback)
{
//need join option here or something
}

View File

@ -246,7 +246,7 @@ static void CSQC_ChangeLocalPlayer(int seat)
{
if (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;
else if (csqc_playerview == &csqc_nullview)
*csqcg.player_localentnum = 0;
@ -2185,7 +2185,7 @@ static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars
#ifdef PLUGINS
Plug_SBar (r_refdef.playerview);
#else
if (Sbar_ShouldDraw())
if (Sbar_ShouldDraw(r_refdef.playerview))
{
SCR_TileClear (sb_lines);
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)
{
Sbar_IntermissionOverlay ();
Sbar_IntermissionOverlay (r_refdef.playerview);
}
}

View File

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

View File

@ -360,8 +360,8 @@ extern lightmapinfo_t **lightmap;
extern int numlightmaps;
//extern texid_t *lightmap_textures;
//extern texid_t *deluxmap_textures;
extern int lightmap_bytes; // 1, 3, or 4
extern qboolean lightmap_bgra; /*true=bgra, false=rgba*/
extern int lightmap_bytes; // 1, 3, or 4
extern uploadfmt_t lightmap_fmt; //bgra32, rgba32, rgb24, lum8
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];
//end hipnotic
qboolean sb_showscores;
qboolean sb_showteamscores;
static qboolean sbarfailed;
#ifdef HEXEN2
static qboolean sbar_hexen2;
@ -131,15 +128,15 @@ float sbar_rect_left;
int sb_lines; // scan lines to draw
void Sbar_DeathmatchOverlay (int start);
void Sbar_TeamOverlay (void);
void Sbar_DeathmatchOverlay (playerview_t *pv, int start);
void Sbar_TeamOverlay (playerview_t *pv);
static void Sbar_MiniDeathmatchOverlay (playerview_t *pv);
void Sbar_ChatModeOverlay(playerview_t *pv);
static int Sbar_PlayerNum(playerview_t *pv)
{
int num;
num = cl.spectator?Cam_TrackNum(pv):-1;
num = pv->spectator?Cam_TrackNum(pv):-1;
if (num < 0)
num = pv->playernum;
return num;
@ -716,7 +713,8 @@ Tab key down
*/
void Sbar_ShowTeamScores (void)
{
if (sb_showteamscores)
int seat = CL_TargettedSplit(false);
if (cl.playerview[seat].sb_showteamscores)
return;
#ifdef CSQC_DAT
@ -724,7 +722,7 @@ void Sbar_ShowTeamScores (void)
return;
#endif
sb_showteamscores = true;
cl.playerview[seat].sb_showteamscores = true;
sb_updates = 0;
}
@ -737,7 +735,8 @@ Tab key up
*/
void Sbar_DontShowTeamScores (void)
{
sb_showteamscores = false;
int seat = CL_TargettedSplit(false);
cl.playerview[seat].sb_showteamscores = false;
sb_updates = 0;
#ifdef CSQC_DAT
@ -755,13 +754,14 @@ Tab key down
*/
void Sbar_ShowScores (void)
{
int seat = CL_TargettedSplit(false);
if (scr_scoreboard_teamscores.ival)
{
Sbar_ShowTeamScores();
return;
}
if (sb_showscores)
if (cl.playerview[seat].sb_showscores)
return;
#ifdef CSQC_DAT
@ -769,7 +769,7 @@ void Sbar_ShowScores (void)
return;
#endif
sb_showscores = true;
cl.playerview[seat].sb_showscores = true;
sb_updates = 0;
}
@ -893,13 +893,14 @@ Tab key up
*/
void Sbar_DontShowScores (void)
{
int seat = CL_TargettedSplit(false);
if (scr_scoreboard_teamscores.ival)
{
Sbar_DontShowTeamScores();
return;
}
sb_showscores = false;
cl.playerview[seat].sb_showscores = false;
sb_updates = 0;
#ifdef CSQC_DAT
@ -2166,7 +2167,7 @@ void Sbar_DrawNormal (playerview_t *pv)
, pv->stats[STAT_AMMO] <= 10);
}
qboolean Sbar_ShouldDraw (void)
qboolean Sbar_ShouldDraw (playerview_t *pv)
{
#ifdef TEXTEDITOR
extern qboolean editoractive;
@ -2182,7 +2183,7 @@ qboolean Sbar_ShouldDraw (void)
#endif
#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;
if (UI_MenuState())
return false;
@ -2195,10 +2196,9 @@ qboolean Sbar_ShouldDraw (void)
return true;
}
void Sbar_DrawScoreboard (void)
void Sbar_DrawScoreboard (playerview_t *pv)
{
int pnum;
int deadcount=0;
qboolean isdead;
if (cls.protocol == CP_QUAKE2)
return;
@ -2214,31 +2214,27 @@ void Sbar_DrawScoreboard (void)
}
#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 = cl.playerview[pnum].cam_spec_track;
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++;
int t = pv->cam_spec_track;
if (t >= 0 && CAM_ISLOCKED(pv) && cl.players[t].statsf[STAT_HEALTH] <= 0)
isdead = true;
}
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)
Sbar_TeamOverlay();
if (cl.teamplay > 0 && !pv->sb_showscores)
Sbar_TeamOverlay(pv);
else
Sbar_DeathmatchOverlay (0);
Sbar_DeathmatchOverlay (pv, 0);
}
else if (sb_showscores)
Sbar_DeathmatchOverlay (0);
else if (sb_showteamscores)
Sbar_TeamOverlay();
else if (pv->sb_showscores)
Sbar_DeathmatchOverlay (pv, 0);
else if (pv->sb_showteamscores)
Sbar_TeamOverlay(pv);
else
return;
@ -2563,7 +2559,7 @@ static void Sbar_DrawTeamStatus(playerview_t *pv)
y = -32;
track = Cam_TrackNum(pv);
if (track == -1 || !cl.spectator)
if (track == -1 || !pv->spectator)
track = pv->playernum;
for (p = 0; p < cl.allocated_client_slots; p++)
@ -2730,7 +2726,7 @@ extern cvar_t show_speed_y;
t = Sys_DoubleTime();
if ((t - lastupstime) >= 1.0/20)
{
if (cl.spectator)
if (pv->spectator)
track = Cam_TrackNum(pv);
else
track = -1;
@ -2865,7 +2861,7 @@ void Sbar_Draw (playerview_t *pv)
// main area
if (sb_lines > 0)
{
if (cl.spectator)
if (pv->spectator)
{
if (pv->cam_state == CAM_FREECAM || pv->cam_state == CAM_PENDING)
{
@ -2879,7 +2875,7 @@ void Sbar_Draw (playerview_t *pv)
}
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 ();
// else if (cls.gamemode != GAME_DEATHMATCH)
// 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)
{
@ -2915,7 +2911,7 @@ void Sbar_Draw (playerview_t *pv)
// top line
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);
else if (cl_sbar.ival)
Sbar_DrawPic (0, -24, 320, 24, sb_scorebar); //make sure we don't get HoM
@ -3006,7 +3002,7 @@ team frags
added by Zoid
==================
*/
void Sbar_TeamOverlay (void)
void Sbar_TeamOverlay (playerview_t *pv)
{
mpic_t *pic;
int i, k;
@ -3015,8 +3011,8 @@ void Sbar_TeamOverlay (void)
team_t *tm;
int plow, phigh, pavg;
int pw,ph;
playerview_t *pv = r_refdef.playerview;
vrect_t gr = r_refdef.grect;
int rank_width = 320-32*2;
int startx;
int trackplayer;
@ -3027,11 +3023,11 @@ void Sbar_TeamOverlay (void)
// request new ping times every two second
if (!cl.teamplay)
{
Sbar_DeathmatchOverlay(0);
Sbar_DeathmatchOverlay(pv, 0);
return;
}
y = 0;
y = gr.y;
if (scr_scoreboard_drawtitle.ival)
{
@ -3039,12 +3035,12 @@ void Sbar_TeamOverlay (void)
if (pic && R_GetShaderSizes(pic, &pw, &ph, false)>0)
{
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;
}
x = l = (vid.width - 320)/2 + 36;
x = l = gr.x + (gr.width - 320)/2 + 36;
startx = x;
@ -3099,7 +3095,7 @@ void Sbar_TeamOverlay (void)
// sort the teams
Sbar_SortTeams(pv);
if (cl.spectator)
if (pv->spectator)
trackplayer = Cam_TrackNum(pv);
else
trackplayer = pv->playernum;
@ -3184,7 +3180,7 @@ void Sbar_TeamOverlay (void)
}
else
y += 8;
Sbar_DeathmatchOverlay(y);
Sbar_DeathmatchOverlay(pv, y-gr.y);
}
/*
@ -3287,7 +3283,7 @@ enum
};
#define ADDCOLUMN(id) showcolumns |= (1<<id)
void Sbar_DeathmatchOverlay (int start)
void Sbar_DeathmatchOverlay (playerview_t *pv, int start)
{
mpic_t *pic;
int i, k;
@ -3299,7 +3295,6 @@ void Sbar_DeathmatchOverlay (int start)
int skip = 10;
int showcolumns;
int startx, rank_width;
playerview_t *pv = r_refdef.playerview;
vrect_t gr = r_refdef.grect;
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_DrawChar ( px, py, CON_WHITEMASK, num[2] | 0xe000);
if ((cl.spectator && k == pv->cam_spec_track && pv->cam_state != CAM_FREECAM) ||
(!cl.spectator && k == pv->playernum))
if ((pv->spectator && k == pv->cam_spec_track && pv->cam_state != CAM_FREECAM) ||
(!pv->spectator && k == pv->playernum))
{
Font_BeginString(font_default, x, y, &px, &py);
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;
int dig;
int num;
int pnum = 0; //should be the same for all players.
sbar_rect.width = vid.width;
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]);
//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);
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);
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
if (UI_DrawIntermission()>0)
@ -3866,10 +3860,10 @@ void Sbar_IntermissionOverlay (void)
Sbar_Start();
if (!cls.deathmatch)
Sbar_CoopIntermission();
else if (cl.teamplay > 0 && !sb_showscores)
Sbar_TeamOverlay ();
Sbar_CoopIntermission(pv);
else if (cl.teamplay > 0 && !pv->sb_showscores)
Sbar_TeamOverlay (pv);
else
Sbar_DeathmatchOverlay (0);
Sbar_DeathmatchOverlay (pv, 0);
}
#endif

View File

@ -33,12 +33,12 @@ qboolean Sbar_UpdateTeamStatus(struct player_info_s *player, char *status);
void Sbar_Changed (void);
// 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_DrawScoreboard (void);
void Sbar_DrawScoreboard (playerview_t *pv);
// called every frame by screen
void Sbar_IntermissionOverlay (void);
void Sbar_IntermissionOverlay (playerview_t *pv);
// called each frame after the level has been completed
void Sbar_FinaleOverlay (void);

View File

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

View File

@ -627,7 +627,7 @@ void Validation_Auto_Response(int playernum, char *s)
Validation_Version();
versionresponsetime = Sys_DoubleTime() + 5;
}
else if (cl.spectator)
else if (cl.playerview[0].spectator)
return;
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;
vec3_t hvel;
if (cl.spectator)
if (pv->spectator)
return 0;
if (cl_bobcycle.value <= 0 || cl.intermissionmode != IM_NONE)
@ -1477,9 +1477,9 @@ void V_CalcRefdef (playerview_t *pv)
}
#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
}
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;
if (cls.state != ca_active || !cl.validsequence || cl.intermissionmode != IM_NONE)
return;
@ -2029,13 +2029,13 @@ void R_DrawNameTags(void)
if (!cl.teamplay || !scr_autoid_team.ival)
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;
else
isteam = !strcmp(cl.players[i].team, ourteam);
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.
SCR_DrawAutoID(nametagorg[i], &cl.players[i], isteam);

View File

@ -704,7 +704,8 @@ done:
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));
}
@ -732,9 +733,10 @@ static char *Macro_TF_Skin (void)
//Spike: added these:
static char *Macro_ConnectionType (void)
{
playerview_t *pv = &cl.playerview[SP];
if (!cls.state)
return "disconnected";
if (cl.spectator)
if (pv->spectator)
return "spectator";
return "connected";
}
@ -878,6 +880,7 @@ static void CountNearbyPlayers(qboolean dead)
player_state_t *state;
player_info_t *info;
static int lastframecount = -1;
playerview_t *pv = &cl.playerview[SP];
if (cls.framecount == lastframecount)
return;
@ -885,7 +888,7 @@ static void CountNearbyPlayers(qboolean dead)
vars.numenemies = vars.numfriendlies = 0;
if (!cl.spectator && !dead)
if (!pv->spectator && !dead)
vars.numfriendlies++;
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;
info = cl.players;
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()))
vars.numfriendlies++;
else
@ -2183,6 +2186,7 @@ int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr)
int flags;
player_info_t *player;
char *name;
playerview_t *pv = &cl.playerview[SP];
*offset = 0;
*plr = NULL;
@ -2275,9 +2279,9 @@ int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr)
!strncmp(name, s+1, len))
{
// 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 &&
!strcmp(cl.players[track].team, player->team)) )
{
@ -2286,8 +2290,8 @@ int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr)
}
else
{
if (i == cl.playerview[SP].playernum || ( cl.teamplay &&
!strcmp(cl.players[cl.playerview[SP].playernum].team, player->team)) )
if (i == pv->playernum || ( cl.teamplay &&
!strcmp(cl.players[pv->playernum].team, player->team)) )
{
flags |= TPM_TEAM;
}
@ -2814,8 +2818,9 @@ static qboolean CheckTrigger (void)
int i, count;
player_info_t *player;
char *myteam;
playerview_t *pv = &cl.playerview[SP];
if (cl.spectator)
if (pv->spectator)
return false;
if (tp_forceTriggers.ival)
@ -2825,9 +2830,9 @@ static qboolean CheckTrigger (void)
return false;
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++) {
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++;
}
@ -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)
{
#ifndef QUAKETC
playerview_t *pv = &cl.playerview[SP];
// if (TP_NeedRefreshSkins())
// {
// if ((state->effects & (EF_BLUE|EF_RED) ) != (oldstate->effects & (EF_BLUE|EF_RED)))
// 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;
@ -2915,11 +2921,11 @@ void TP_ParsePlayerInfo(player_state_t *oldstate, player_state_t *state, player_
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)))
{
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)))
{
@ -2935,8 +2941,9 @@ void TP_CheckPickupSound (char *s, vec3_t org, int seat)
#ifndef QUAKETC
int entnum;
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 (cl.spectator)
if (pv->spectator)
seat = -1;
//FIXME: on items/itembk2.wav kill relevant item timer.
@ -2992,17 +2999,17 @@ more:
if (vars.stat_framecounts[STAT_ITEMS] == cls.framecount)
{
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)
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)
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)
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)
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)
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;
@ -3020,11 +3027,11 @@ more:
TP_ItemTaken (item->cvar->string, item->itemflag, org, entnum, item, seat);
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);
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);
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);
}
return;
@ -3216,6 +3223,7 @@ static void TP_FindPoint (void)
item_vis_t visitem;
extern cvar_t v_viewheight;
int oldskip = pmove.skipent;
playerview_t *pv = &cl.playerview[SP];
if (vars.pointtime == realtime)
return;
@ -3223,11 +3231,11 @@ static void TP_FindPoint (void)
if (!cl.validsequence)
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);
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);
pointflags_dmm = pointflags;
@ -3274,7 +3282,7 @@ static void TP_FindPoint (void)
info = cl.players;
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;
if (
@ -3325,7 +3333,7 @@ static void TP_FindPoint (void)
if (eyes)
name = tp_name_eyes.string; //duck on 2night2
else if (cl.spectator)
else if (pv->spectator)
name = bestinfo->name;
else if (teammate)
name = tp_name_teammate.string[0] ? tp_name_teammate.string : "teammate";
@ -3341,7 +3349,7 @@ static void TP_FindPoint (void)
if (eyes)
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;
else
name = teammate ? tp_name_teammate.string : tp_name_enemy.string;
@ -3390,6 +3398,7 @@ void TP_UpdateAutoStatus(void)
char newstatusbuf[sizeof(vars.autoteamstatus)];
char *newstatus;
int level;
playerview_t *pv = &cl.playerview[SP];
if (vars.autoteamstatus_time > realtime || !*tp_autostatus.string)
return;
@ -3415,7 +3424,7 @@ void TP_UpdateAutoStatus(void)
if (tp_autostatus.latched_string)
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;
if (!cl.teamplay) //don't spam in deathmatch, that's just pointless
return;
@ -3427,6 +3436,7 @@ void TP_UpdateAutoStatus(void)
void TP_StatChanged (int stat, int value)
{
#ifdef QUAKESTATS
playerview_t *pv = &cl.playerview[SP];
int i;
if (stat == STAT_HEALTH)
{
@ -3437,14 +3447,14 @@ void TP_StatChanged (int stat, int value)
// we just respawned
vars.respawntrigger_time = realtime;
if (!cl.spectator && CountTeammates())
if (!pv->spectator && CountTeammates())
TP_ExecTrigger ("f_respawn", false);
}
}
else if (vars.health > 0)
{ // We have just died
vars.droppedweapon = cl.playerview[SP].stats[STAT_ACTIVEWEAPON];
vars.droppedweapon = pv->stats[STAT_ACTIVEWEAPON];
vars.deathtrigger_time = realtime;
strcpy (vars.lastdeathloc, Macro_Location());
@ -3453,9 +3463,9 @@ void TP_StatChanged (int stat, int value)
vars.last_numenemies = vars.numenemies;
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))
TP_ExecTrigger ("f_flagdeath", false);
else
@ -3469,14 +3479,14 @@ void TP_StatChanged (int stat, int value)
i = value &~ vars.items;
if (i & (IT_KEY1|IT_KEY2)) {
if (cl.teamfortress && !cl.spectator)
if (cl.teamfortress && !pv->spectator)
{
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;
strcpy (vars.lastdroploc, Macro_Location());
@ -3487,9 +3497,9 @@ void TP_StatChanged (int stat, int value)
}
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);
vars.activeweapon = cl.playerview[SP].stats[STAT_ACTIVEWEAPON];
vars.activeweapon = pv->stats[STAT_ACTIVEWEAPON];
}
#endif
vars.stat_framecounts[stat] = cls.framecount;
@ -3709,6 +3719,7 @@ void TP_Init (void)
qboolean TP_SuppressMessage(char *buf) {
char *s;
playerview_t *pv = &cl.playerview[SP];
for (s = buf; *s && *s != 0x7f; s++)
;
@ -3717,7 +3728,7 @@ qboolean TP_SuppressMessage(char *buf) {
*s++ = '\n';
*s++ = 0;
return (!cls.demoplayback && !cl.spectator && *s - 'A' == cl.playerview[SP].playernum);
return (!cls.demoplayback && !pv->spectator && *s - 'A' == pv->playernum);
}
return false;
}
@ -3728,6 +3739,7 @@ void CL_Say (qboolean team, char *extra)
{
extern cvar_t cl_fakename;
char text[2048], sendtext[2048], *s;
playerview_t *pv = &cl.playerview[SP];
if (Cmd_Argc() < 2)
{
@ -3748,7 +3760,7 @@ void CL_Say (qboolean team, char *extra)
Q_strncpyz (text, TP_ParseFunChars (s), sizeof(text));
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 */)
{
char buf[1024];
@ -3803,7 +3815,7 @@ void CL_Say (qboolean team, char *extra)
if (team)
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
@ -3831,7 +3843,7 @@ void CL_Say (qboolean team, char *extra)
*d = '\0';
//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

View File

@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// release version
#define FTE_VER_MAJOR 1
#define FTE_VER_MINOR 5
#define FTE_VER_MINOR 6
#if defined(__APPLE__) && defined(__MACH__)
#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 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 WEBSERVER //http/ftp servers
#define WEBCLIENT //http/ftp clients.
// #define WEBSERVER //http server
#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 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.

View File

@ -1100,7 +1100,7 @@ static vfsfile_t *QDECL FSZIP_OpenVFS(searchpathfuncs_t *handle, flocation_t *lo
if (flags & ZFL_DEFLATED)
{
#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;
#else
char *password = NULL;

View File

@ -95,9 +95,9 @@ typedef int (VARGS gnutls_certificate_verify_function)(gnutls_session_t session)
#else
#include <gnutls/gnutls.h>
#if GNUTLS_VERSION_MAJOR >= 3 && defined(HAVE_DTLS)
#include <gnutls/dtls.h>
#include <gnutls/dtls.h>
#else
#undef HAVE_DTLS
#undef HAVE_DTLS
#endif
#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)
{
#ifdef QUAKEHUD
extern qboolean sb_showscores, sb_showteamscores;
#define sb_showscores pv->sb_showscores
#define sb_showteamscores pv->sb_showteamscores
#else
#define sb_showscores 0
#define sb_showteamscores 0
#define sb_showscores 0
#define sb_showteamscores 0
#endif
plugin_t *oc=currentplug;
@ -1877,7 +1878,7 @@ void Plug_SBar(playerview_t *pv)
int cleared = false;
int hudmode;
if (!Sbar_ShouldDraw())
if (!Sbar_ShouldDraw(pv))
{
SCR_TileClear (0);
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].height = lm->height;
mips.mip[0].datasize = lm->width*lm->height*4;
if (lightmap_bgra)
switch (lightmap_fmt)
{
case TF_BGRA32:
mips.encoding = PTI_BGRX8;
else
mips.encoding = PTI_RGBX8;
break;
case TF_RGBA32:
mips.encoding = PTI_RGBX8;
break;
}
mips.mipcount = 1;
D3D11_LoadTextureMips(tex, &mips);
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);
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
return NULL;
@ -921,6 +921,7 @@ static char *(D3D8_VID_GetRGBInfo) (int *truevidwidth, int *truevidheight, enu
*fmt = TF_RGB24;
// 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;
p = (qbyte *)rect.pBits;
@ -935,6 +936,7 @@ static char *(D3D8_VID_GetRGBInfo) (int *truevidwidth, int *truevidheight, enu
p += rect.Pitch;
}
*bytestride = desc.Width*3;
*truevidwidth = desc.Width;
*truevidheight = desc.Height;
}

View File

@ -67,6 +67,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iqm", "..\..\iqm\iqm.vcproj
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmake", "gmake.vcproj", "{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "terrorgen", "..\..\plugins\terrorgen\terrorgen.vcproj", "{1E65A0D3-3371-4602-A69C-53BA389FFBD9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
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.Build.0 = 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
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1118,6 +1162,7 @@ Global
{F756A3D2-025A-43D4-9829-4074753B774B} = {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}
{1E65A0D3-3371-4602-A69C-53BA389FFBD9} = {8CED01C6-2C61-4EC5-90B6-574D9756D773}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
AMDCaProjectFile = C:\Games\Quake\wip\engine\dotnet2005\CodeAnalyst\ftequake.caw

View File

@ -4985,20 +4985,15 @@ static void BE_UpdateLightmaps(void)
int lmidx;
int glformat, gltype;
int internalformat = GL_RGBA;
switch (lightmap_bytes)
switch (lightmap_fmt)
{
case 4:
glformat = lightmap_bgra?GL_BGRA_EXT:GL_RGBA;
gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
break;
case 3:
glformat = lightmap_bgra?GL_BGR_EXT:GL_RGB;
gltype = GL_UNSIGNED_BYTE;
break;
default:
glformat = GL_LUMINANCE;
gltype = GL_UNSIGNED_BYTE;
break;
case TF_INVALID: return;
default: Sys_Error("Bad lightmap_fmt\n"); return;
case TF_BGRA32: glformat = GL_BGRA_EXT; gltype = GL_UNSIGNED_INT_8_8_8_8_REV; break;
// case TF_RGBA32: glformat = GL_RGBA; gltype = GL_UNSIGNED_INT_8_8_8_8_REV; break;
// case TF_BGR24: glformat = GL_BGR_EXT; gltype = GL_UNSIGNED_BYTE; break;
case TF_RGB24: glformat = GL_RGB; gltype = GL_UNSIGNED_BYTE; break;
case TF_LUM8: glformat = GL_LUMINANCE;gltype = GL_UNSIGNED_BYTE; break;
}
if (gl_config.gles)
internalformat = glformat;
@ -5025,16 +5020,12 @@ static void BE_UpdateLightmaps(void)
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_MAG_FILTER, GL_LINEAR);
qglTexImage2D(GL_TEXTURE_2D, 0, internalformat,
lm->width, lm->height, 0, glformat, gltype,
lm->lightmaps);
qglTexImage2D(GL_TEXTURE_2D, 0, internalformat, lm->width, lm->height, 0, glformat, gltype, lm->lightmaps);
}
else
{
GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture);
qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, t,
lm->width, b-t, glformat, gltype,
lm->lightmaps+t *lm->width*lightmap_bytes);
qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, t, lm->width, b-t, glformat, gltype, lm->lightmaps+t*lm->width*lightmap_bytes);
}
lm->modified = false;
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)
{
struct lmsect_s *lms;
if (!hm->unusedlmsects)
Sys_LockMutex(com_resourcemutex);
while (!hm->unusedlmsects)
{
int lm;
int i;
Sys_UnlockMutex(com_resourcemutex);
lm = Surf_NewLightmaps(1, SECTTEXSIZE*LMCHUNKS, SECTTEXSIZE*LMCHUNKS, false);
Sys_LockMutex(com_resourcemutex);
for (i = 0; i < LMCHUNKS*LMCHUNKS; i++)
{
lms = BZ_Malloc(sizeof(*lms));
@ -184,6 +187,7 @@ static qboolean QDECL Terr_InitLightmap(hmsection_t *s, qboolean initialise)
hm->numunusedlmsects--;
hm->numusedlmsects++;
Sys_UnlockMutex(com_resourcemutex);
Z_Free(lms);
initialise = true;
@ -2070,6 +2074,9 @@ void Terr_PurgeTerrainModel(model_t *mod, qboolean lightmapsonly, qboolean light
int cx, cy;
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);
// 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;
}
Sys_DestroyMutex(hm->entitylock);
Z_Free(hm->seed);
Z_Free(hm);
mod->terrain = NULL;
}
@ -3015,6 +3023,8 @@ void Terr_DrawTerrainModel (batch_t **batches, entity_t *e)
else
culldist = 999999999999999.f;
if (culldist < hm->maxdrawdist)
culldist = hm->maxdrawdist;
if (culldist > r_refdef.maxdist && r_refdef.maxdist>0)
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;
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);
}
if (mod->loadstate != MLS_LOADED)
@ -5258,6 +5270,25 @@ void Terr_ParseEntityLump(model_t *mod, heightmap_t *heightmap)
heightmap->culldistance = atof(value);
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))
Q_strncpyz(heightmap->skyname, value, sizeof(heightmap->skyname));
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;
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[0];
*out++ = 0xff;
in+=3;
}
out += (lm->width - br->faces[j].lmextents[0]) * 4;
*out++ = in[2];
*out++ = in[1];
*out++ = in[0];
*out++ = 0xff;
in+=3;
}
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[2];
*out++ = 0xff;
in+=3;
}
out += (lm->width - br->faces[j].lmextents[0]) * 4;
*out++ = in[0];
*out++ = in[1];
*out++ = in[2];
*out++ = 0xff;
in+=3;
}
out += (lm->width - br->faces[j].lmextents[0]) * 4;
}
}
else if (lightmap_bytes == 3)
{
if (lightmap_bgra)
break;*/
/*case TF_BGR24:
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[0];
in+=3;
}
out += (lm->width - br->faces[j].lmextents[0]) * 3;
*out++ = in[2];
*out++ = in[1];
*out++ = in[0];
in+=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[2];
in+=3;
}
out += (lm->width - br->faces[j].lmextents[0]) * 3;
*out++ = in[0];
*out++ = in[1];
*out++ = in[2];
in+=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;
hm = mod->terrain;
if (hm && hm->exteriorcontents != FTECONTENTS_EMPTY)
if (hm && hm->legacyterrain)
VFS_WRITE(file, "terrain\n", 8);
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)
{
int exterior = FTECONTENTS_SOLID;
int legacyterrain;
heightmap_t *hm;
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));
if (!strcmp(token, "terrain"))
{
legacyterrain = true;
buffer = src;
}
else if (!strcmp(token, "{"))
exterior = FTECONTENTS_EMPTY;
legacyterrain = false;
else
{
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->sectionsize = sectsize;
if (exterior)
if (legacyterrain)
{
hm->firstsegx = -1;
hm->firstsegy = -1;
@ -7404,7 +7434,9 @@ qboolean QDECL Terr_LoadTerrainModel (model_t *mod, void *buffer, size_t bufsize
hm->maxsegx = 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);
@ -7528,44 +7560,56 @@ void Mod_Terrain_Create_f(void)
char *watername;
char *groundheight;
char *waterheight;
char *seed;
vfsfile_t *file;
model_t mod;
memset(&mod, 0, sizeof(mod));
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;
}
mname = va("maps/%s.hmp", Cmd_Argv(1));
mapdesc = Cmd_Argv(2); if (!*mapdesc) mapdesc = Cmd_Argv(1);
skyname = Cmd_Argv(3); if (!*skyname) skyname = "sky1";
groundname = Cmd_Argv(4); if (!*groundname) groundname = "default";
groundheight = Cmd_Argv(5); if (!*groundheight) groundheight = "0";
watername = Cmd_Argv(6); if (!*watername) watername = "";
waterheight = Cmd_Argv(7); if (!*waterheight) waterheight = "1024";
skyname = Cmd_Argv(3);
groundname = Cmd_Argv(4);
groundheight = Cmd_Argv(5);
watername = Cmd_Argv(6);
waterheight = Cmd_Argv(7);
seed = Cmd_Argv(7);
Mod_SetEntitiesString(&mod, va(
"{\n"
"classname \"worldspawn\"\n"
"message \"%s\"\n"
"_sky sky1\n"
"_sky \"%s\"\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"
"_minysegment -2048\n"
"_maxxsegment 2048\n"
"_maxysegment 2048\n"
"//_defaultgroundtexture \"city4_2\"\n"
"//_defaultwatertexture \"*water2\"\n"
"//_defaultgroundheight -1024\n"
"//_defaultwaterheight 0\n" //hurrah, sea level.
"_seed \"%s\" /*for auto-gen plugins*/\n"
"_exterior solid\n"
"_defaultgroundtexture \"%s\"\n"
"_defaultgroundheight \"%s\"\n"
"_defaultwatertexture \"%s\"\n"
"_defaultwaterheight \"%s\"\n" //hurrah, sea level.
// "_tiles 64 64 8 8\n"
"}\n"
"{\n"
"classname info_player_start\n"
"origin \"0 0 1024\"\n"
"origin \"0 0 1024\" /*EDITME*/\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.terrain = hm = Z_Malloc(sizeof(*hm));
@ -7724,7 +7768,11 @@ void Mod_Terrain_Reload_f(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;
#endif
}
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);
// else
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
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_MAG_FILTER, GL_LINEAR);
}
switch (lightmap_bytes)
switch(lightmap_fmt) //bgra32, rgba32, rgb24, lum8
{
case 4:
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
lm->width, lm->height, 0, (lightmap_bgra?GL_BGRA_EXT:GL_RGBA), GL_UNSIGNED_INT_8_8_8_8_REV,
lightmap[i]->lightmaps);
break;
case 3:
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;
default: Sys_Error("Bad lightmap_fmt\n"); break;
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;
// 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;
// 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;
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 TF_LUM8: qglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, lm->width, lm->height, 0, GL_LUMINANCE,GL_UNSIGNED_BYTE, lightmap[i]->lightmaps); break;
}
//for completeness.
lm->lightmap_texture->width = lm->width;

View File

@ -287,23 +287,28 @@ typedef struct
typedef struct heightmap_s
{
char path[MAX_QPATH];
char skyname[MAX_QPATH];
char groundshadername[MAX_QPATH];
char defaultwatershader[MAX_QPATH]; //typically the name of the ocean or whatever.
unsigned int culldistance;
qboolean forcedefault;
float defaultwaterheight;
float defaultgroundheight;
char defaultgroundtexture[MAX_QPATH];
int firstsegx, firstsegy;
int maxsegx, maxsegy; //tex/cull sections
char skyname[MAX_QPATH]; //name of the skybox
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.
unsigned int culldistance; //entities will be culled if they're this far away (squared distance
float maxdrawdist; //maximum view distance. extends view if larger than fog implies.
unsigned char *seed; //used by whatever terrain generator.
qboolean forcedefault; //sections that cannot be loaded/generated will receive default values for stuff.
char defaultgroundtexture[MAX_QPATH];//texture used for defaulted sections
char defaultwatershader[MAX_QPATH]; //shader used for defaulted sections that have heights beneath defaultwaterheight.
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
hmcluster_t *cluster[MAXCLUSTERS*MAXCLUSTERS];
shader_t *skyshader;
shader_t *shader;
mesh_t skymesh;
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.
size_t traceseq;
size_t drawnframe;

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
#include "quakedef.h"
#ifdef WEBSERVER
#if defined(WEBSERVER) || defined(FTPSERVER)
#include "iweb.h"
#include "netinc.h"
@ -503,15 +503,18 @@ IWEBFILE *IWebFOpenRead(char *name) //fread(name, "rb");
#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
cvar_t ftpserver = CVAR("sv_ftp", "0");
cvar_t ftpserver_port = CVAR("sv_ftp_port", "21");
cvar_t httpserver = CVAR("sv_http", "0");
cvar_t httpserver_port = CVAR("sv_http_port", "80");
cvar_t sv_readlevel = CVAR("sv_readlevel", "0"); //default to allow anyone
cvar_t sv_writelevel = CVAR("sv_writelevel", "35"); //allowed to write to uploads/uname
cvar_t sv_fulllevel = CVAR("sv_fulllevel", "51"); //allowed to write anywhere, replace any file...
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.");
static cvar_t httpserver = CVAR("sv_http", "0");
static cvar_t httpserver_port = CVAR("sv_http_port", "80");
#endif
#ifdef FTPSERVER
static cvar_t ftpserver = CVAR("sv_ftp", "0");
static cvar_t ftpserver_port = CVAR("sv_ftp_port", "21");
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.");
int IWebGetSafeListeningPort(void)
{
@ -533,6 +536,7 @@ int IWebGetSafeListeningPort(void)
return base + (sequence++ % (range+1-base));
}
#endif
#endif
//this file contains functions called from each side.
@ -680,9 +684,9 @@ int IWebAuthorize(const char *name, const char *password)
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
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
if (info.s.trustlevel >= sv_readlevel.value)
return IWEBACC_READ; //read only anywhere

View File

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

View File

@ -703,13 +703,11 @@ HMODULE scintilla;
pbool resetprogssrc; //progs.src was changed, reload project info.
HWND mainwindow;
HWND gamewindow;
HWND mdibox;
HWND watches;
HWND optionsmenu;
HWND outputwindow;
HWND outputbox;
HWND projecttree;
HWND search_name;
@ -717,6 +715,240 @@ HWND search_gotodef;
HWND search_grep;
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;
void GrepAllFiles(char *string);
@ -855,21 +1087,21 @@ LRESULT CALLBACK MySubclassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
{
*colon1 = '\0';
*colon2 = '\0';
EditFile(line, atoi(colon1+1)-1, false);
EditFile(line, atoi(colon1+1)-1, 2);
}
else if (!strncmp(line, "Source file: ", 13))
EditFile(line+13, -1, false);
EditFile(line+13, -1, 2);
else if (!strncmp(line, "Including: ", 11))
EditFile(line+11, -1, false);
EditFile(line+11, -1, 2);
}
else if (!strncmp(line, "including ", 10))
EditFile(line+10, -1, false);
EditFile(line+10, -1, 2);
else if (!strncmp(line, "compiling ", 10))
EditFile(line+10, -1, false);
EditFile(line+10, -1, 2);
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))
EditFile(line+19, -1, false);
EditFile(line+19, -1, 2);
Edit_SetSel(hWnd, selrange.cpMin, selrange.cpMin); //deselect it.
}
}
@ -1385,11 +1617,7 @@ void GenericMenu(WPARAM wParam)
case IDM_OUTPUT_WINDOW:
if (outputwindow && outputbox)
{
SetFocus(outputwindow);
SetFocus(outputbox);
}
SplitterFocus(outputbox, 128);
break;
case IDM_SHOWLINENUMBERS:
{
@ -2267,6 +2495,8 @@ static LRESULT CALLBACK EditorWndProc(HWND hWnd,UINT message,
GetClientRect(hWnd, &rect);
SetWindowPos(editor->editpane, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, 0);
goto gdefault;
case WM_ERASEBKGND:
return TRUE;
case WM_PAINT:
BeginPaint(hWnd,(LPPAINTSTRUCT)&ps);
@ -2547,6 +2777,10 @@ static void EditorReload(editor_t *editor)
}
//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)
{
char title[1024];
@ -2574,7 +2808,10 @@ void EditFile(const char *name, int line, pbool setcontrol)
{
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);
if (setcontrol && neweditor->scintilla)
@ -2635,15 +2872,15 @@ void EditFile(const char *name, int line, pbool setcontrol)
wndclass.style = 0;
wndclass.lpfnWndProc = EditorWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = ghInstance;
wndclass.lpfnWndProc = EditorWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = ghInstance;
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.lpszMenuName = 0;
wndclass.lpszClassName = EDIT_WINDOW_CLASS_NAME;
wndclass.lpszMenuName = 0;
wndclass.lpszClassName = EDIT_WINDOW_CLASS_NAME;
RegisterClass(&wndclass);
neweditor->window = NULL;
@ -2658,7 +2895,7 @@ void EditFile(const char *name, int line, pbool setcontrol)
mcs.hOwner = ghInstance;
mcs.x = mcs.cx = CW_USEDEFAULT;
mcs.y = mcs.cy = CW_USEDEFAULT;
mcs.style = WS_OVERLAPPEDWINDOW;
mcs.style = WS_OVERLAPPEDWINDOW|WS_MAXIMIZE;
mcs.lParam = 0;
neweditor->window = (HWND) SendMessage (mdibox, WM_MDICREATE, 0,
@ -2685,7 +2922,12 @@ void EditFile(const char *name, int line, pbool setcontrol)
EditorReload(neweditor);
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
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)
{
SplitterRemove(watches);
gamewindow = NULL;
PostMessage(mainwindow, WM_SIZE, 0, 0);
}
break;
case WM_USER:
@ -3724,6 +3966,8 @@ void RunEngine(void)
gamewindow = (HWND) SendMessage (mdibox, WM_MDICREATE, 0, (LONG_PTR) (LPMDICREATESTRUCT) &mcs);
}
SplitterAdd(watches, 0);
SplitterFocus(watches, 64);
}
else
{
@ -5398,12 +5642,14 @@ static LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
watches = CreateWindow(WC_LISTVIEW, (LPCTSTR) NULL,
WS_CHILD | WS_VSCROLL | WS_HSCROLL | LVS_REPORT | LVS_EDITLABELS,
0, 0, 320, 200, hWnd, (HMENU) 0xCAD, ghInstance, NULL);
ShowWindow(watches, SW_SHOW);
SplitterAdd(mdibox, 32);
if (watches)
{
LVCOLUMN col;
LVITEM newi;
// ListView_SetUnicodeFormat(watches, TRUE);
ListView_SetExtendedListViewStyle(watches, LVS_EX_GRIDLINES);
memset(&col, 0, sizeof(col));
@ -5481,40 +5727,37 @@ static LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
GetClientRect(mainwindow, &rect);
if (projecttree)
{
int mdiheight, watchheight;
SetWindowPos(projecttree, NULL, 0, 0, 192, rect.bottom-rect.top - 34 - 48, 0);
SetWindowPos(projecttree, NULL, 0, 0, 192, rect.bottom-rect.top - 48, SWP_NOZORDER);
SetWindowPos(search_name, NULL, 0, rect.bottom-rect.top - 33 - 48, 192, 24, 0);
SetWindowPos(search_gotodef, NULL, 0, rect.bottom-rect.top - 33 - 24, 192/2, 24, 0);
SetWindowPos(search_grep, NULL, 192/2, rect.bottom-rect.top - 33 - 24, 192/2, 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 - 24, 192/2, 24, SWP_NOZORDER);
SetWindowPos(search_grep, NULL, 192/2, rect.bottom-rect.top - 24, 192/2, 24, SWP_NOZORDER);
if (gamewindow)
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);
splitterrect.left = 192;
}
else
SetWindowPos(mdibox?mdibox:outputbox, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top - 32, 0);
width = (rect.right-rect.left);
width/=NUMBUTTONS;
{
splitterrect.left = 0;
}
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++)
{
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;
// goto gdefault;
case WM_ERASEBKGND:
return TRUE; //background is clear... or doesn't need clearing (if its fully obscured)
case WM_PAINT:
BeginPaint(hWnd,(LPPAINTSTRUCT)&ps);
EndPaint(hWnd,(LPPAINTSTRUCT)&ps);
return TRUE;
break;
case WM_COMMAND:
i = LOWORD(wParam);
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)
{
// MSG wmsg;
@ -6031,8 +6253,7 @@ int GUIprintf(const char *msg, ...)
outlen = 0;
/*make sure its active so we can actually scroll. stupid windows*/
SetFocus(outputwindow);
SetFocus(outputbox);
SplitterFocus(outputbox, 0);
/*colour background to default*/
TreeView_SetBkColor(projecttree, -1);
@ -6274,45 +6495,14 @@ void RunCompiler(char *args, pbool quick)
void CreateOutputWindow(pbool doannoates)
{
WNDCLASS wndclass;
MDICREATESTRUCT mcs;
gui_doannotates = doannoates;
if (!mdibox) //should already be created
return;
if (!outputwindow)
if (!outputbox)
{
wndclass.style = 0;
wndclass.lpfnWndProc = OutputWindowProc;
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);
outputbox = CreateAnEditControl(mainwindow, NULL);
SplitterAdd(outputbox, 64);
}
//bring it to the front.
SendMessage(mdibox, WM_MDIACTIVATE, (WPARAM)outputwindow, 0);
SplitterFocus(outputbox, 128);
}

View File

@ -820,6 +820,7 @@ void PR_LoadGlabalStruct(qboolean muted)
globalfloat (false, input_buttons);
globalint (false, serverid);
globalvec (false, global_gravitydir);
globalstring (false, parm_string);
memset(&evalc_idealpitch, 0, sizeof(evalc_idealpitch));
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)
{
int j;
Con_DPrintf("Delayed model precache: %s\n", m);
MSG_WriteByte(&sv.reliable_datagram, svcfte_precache);
MSG_WriteShort(&sv.reliable_datagram, i);
MSG_WriteString(&sv.reliable_datagram, m);
#ifdef NQPROT
MSG_WriteByte(&sv.nqreliable_datagram, svcdp_precache);
MSG_WriteShort(&sv.nqreliable_datagram, i);
MSG_WriteString(&sv.nqreliable_datagram, m);
#endif
for (j = 0; j < sv.allocated_client_slots; j++)
{
if (svs.clients[j].state < cs_connected)
continue;
if (ISDPCLIENT(&svs.clients[j]) || (svs.clients[j].fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS))
{
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
@ -3677,6 +3688,25 @@ void PF_stuffcmd_Internal(int entnum, const char *str, unsigned int flags)
{
client_t *cl;
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)
return;
@ -5529,9 +5559,7 @@ void QCBUILTIN PF_setspawnparms (pubprogfuncs_t *prinst, struct globalvars_s *pr
// copy spawn parms out of the client_t
client = svs.clients + (i-1);
for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
if (pr_global_ptrs->spawnparamglobals[i])
*pr_global_ptrs->spawnparamglobals[i] = client->spawn_parms[i];
SV_SpawnParmsToQC(client);
}
/*
@ -5744,7 +5772,7 @@ char *PF_infokey_Internal (int entnum, const char *key)
value = ""; //could be a writebyted bot...
break;
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";
else
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;
static void QCBUILTIN PF_te_explosion2(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
qboolean old = false;
float *org = G_VECTOR(OFS_PARM0);
int start = G_FLOAT(OFS_PARM1);
int length = G_FLOAT(OFS_PARM2);
start = bound(0, start, 255);
length = bound(0, length, 255-start);
MSG_WriteByte (&sv.multicast, svc_temp_entity);
MSG_WriteByte (&sv.multicast, TEQW_EXPLOSION2);
MSG_WriteCoord (&sv.multicast, org[0]);
MSG_WriteCoord (&sv.multicast, org[1]);
MSG_WriteCoord (&sv.multicast, org[2]);
MSG_WriteByte (&sv.multicast, start);
MSG_WriteByte (&sv.multicast, length);
#ifdef NQPROT
MSG_WriteByte (&sv.nqmulticast, svc_temp_entity);
MSG_WriteByte (&sv.nqmulticast, TENQ_EXPLOSION2);
MSG_WriteCoord (&sv.nqmulticast, org[0]);
MSG_WriteCoord (&sv.nqmulticast, org[1]);
MSG_WriteCoord (&sv.nqmulticast, org[2]);
MSG_WriteByte (&sv.nqmulticast, start);
MSG_WriteByte (&sv.nqmulticast, length);
#endif
SV_MulticastProtExt(org, MULTICAST_PHS, pr_global_struct->dimension_send, 0, 0);
for(;;)
{
MSG_WriteByte (&sv.multicast, svc_temp_entity);
MSG_WriteByte (&sv.multicast, old?TE_EXPLOSION:TEQW_EXPLOSION2);
MSG_WriteCoord (&sv.multicast, org[0]);
MSG_WriteCoord (&sv.multicast, org[1]);
MSG_WriteCoord (&sv.multicast, org[2]);
if (!old)
{
MSG_WriteByte (&sv.multicast, start);
MSG_WriteByte (&sv.multicast, length);
}
#ifdef NQPROT
MSG_WriteByte (&sv.nqmulticast, svc_temp_entity);
MSG_WriteByte (&sv.nqmulticast, TENQ_EXPLOSION2);
MSG_WriteCoord (&sv.nqmulticast, org[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

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));
for (; i < NUM_SPAWN_PARMS; i++)
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;}
if (VM_NonNative(q1qvm))

View File

@ -100,6 +100,7 @@ typedef struct nqglobalvars_s
float *input_buttons;
vec3_t *global_gravitydir;
float *spawnparamglobals[NUM_SPAWN_PARMS];
string_t *parm_string;
int *serverid;
} 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);
if (e2)
e2->_float = 1;
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_SpawnParmsToQC(host_client);
pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent);
ent->area.next = ent->area.prev = NULL;

View File

@ -333,13 +333,18 @@ typedef struct
float move_msecs; //
int packetsizein; //amount of data received for this 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
{
unsigned int entnum;
unsigned int bits; //delta
unsigned int bits; //delta (fte or dpp5+)
unsigned int flags; //csqc
} *resend;
unsigned int numresend;
unsigned int maxresend;
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
@ -396,7 +401,7 @@ typedef struct //merge?
enum
{
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_SOUNDLIST, //nq skips these
PRESPAWN_VWEPMODELLIST, //qw ugly extension.
@ -504,7 +509,8 @@ typedef struct client_s
// spawn parms are carried from level to level
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 nextservertimeupdate; //next time to send STAT_TIME
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);
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_SaveSpawnparms (void);
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);
host_client->spawninfo = NULL;
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)
@ -2855,16 +2856,14 @@ void SV_MemInfo_f(void)
sz += lp->length;
fr = 0;
fr += sizeof(client_frame_t)*UPDATE_BACKUP;
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+
sizeof(*cl->pendingdeltabits)*cl->max_net_ents+
sizeof(unsigned int)*maxents*UPDATE_BACKUP+
sizeof(unsigned int)*maxents*UPDATE_BACKUP;
fr += sizeof(cl)*UPDATE_BACKUP+
sizeof(*cl->pendingdeltabits)*cl->max_net_ents;
}
else
fr = (sizeof(client_frame_t)+sizeof(entity_state_t)*cl->frameunion.frames[0].entities.max_entities)*UPDATE_BACKUP;
fr += sizeof(*cl->frameunion.frames[0].resend)*cl->frameunion.frames[0].maxresend*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;
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)

View File

@ -125,18 +125,18 @@ unsigned int SV_Q2BSP_FatPVS (model_t *mod, vec3_t org, qbyte *resultbuf, unsig
#endif
void SVFTE_ExpandFrames(client_t *client, int require)
void SV_ExpandNackFrames(client_t *client, int require)
{
client_frame_t *newframes;
char *ptr;
int i;
int maxents = require * 2; /*this is the max number of ents updated per frame. we can't track more, so...*/
if (maxents > client->max_net_ents)
maxents = client->max_net_ents;
int maxlog = require * 2; /*this is the max number of ents updated per frame. we can't track more, so...*/
if (maxlog > client->max_net_ents)
maxlog = client->max_net_ents;
ptr = Z_Malloc( sizeof(client_frame_t)*UPDATE_BACKUP+
sizeof(*client->pendingdeltabits)*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;
memcpy(newframes, client->frameunion.frames, 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;
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;
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;
}
Z_Free(client->frameunion.frames);
@ -348,10 +350,11 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
qboolean writtenheader = false;
int viewerent;
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;
int maxlog = client->frameunion.frames[currentsequence & UPDATE_MASK].entities.max_entities;
struct resendinfo_s *resend = frame->resend;
int maxlog = frame->maxresend;
//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)
{
SVFTE_ExpandFrames(client, lognum+1);
SV_ExpandNackFrames(client, lognum+1);
break;
}
resend[lognum].entnum = entnum;
@ -444,7 +447,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
if (lognum > maxlog)
{
SVFTE_ExpandFrames(client, lognum+1);
SV_ExpandNackFrames(client, lognum+1);
break;
}
resend[lognum].entnum = entnum;
@ -478,7 +481,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
if (lognum > maxlog)
{
SVFTE_ExpandFrames(client, lognum+1);
SV_ExpandNackFrames(client, lognum+1);
break;
}
resend[lognum].entnum = entnum;
@ -514,7 +517,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
if (lognum > maxlog)
{
SVFTE_ExpandFrames(client, lognum+1);
SV_ExpandNackFrames(client, lognum+1);
break;
}
resend[lognum].entnum = entnum;
@ -540,7 +543,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
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.
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)
{
int i;
client_frame_t *frame;
if (!ISQWCLIENT(client) && !ISNQCLIENT(client))
return;
@ -559,39 +563,35 @@ void SV_CSQC_DroppedPacket(client_t *client, int sequence)
Con_Printf("Server bug: No frames!\n");
return;
}
frame = &client->frameunion.frames[sequence & UPDATE_MASK];
//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);
return;
}
//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);
i = client->frameunion.frames[sequence & UPDATE_MASK].entities.num_entities;
i = frame->numresend;
while (i > 0)
{
i--;
// if (f[i] & UF_RESET)
// Con_Printf("Resend %i @ %i\n", i, sequence);
// if (f[i] & UF_REMOVE)
// Con_Printf("Remove %i @ %i\n", i, sequence);
client->pendingdeltabits[resend[i].entnum] |= resend[i].bits;
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
if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
if (frame->numresendstats)
{
client_t *sp;
unsigned short *n = client->frameunion.frames[sequence & UPDATE_MASK].resendstats;
i = client->frameunion.frames[sequence & UPDATE_MASK].numresendstats;
unsigned short *n = frame->resendstats;
i = frame->numresendstats;
while(i-->0)
{
unsigned short s = n[i];
@ -608,7 +608,7 @@ void SV_CSQC_DroppedPacket(client_t *client, int sequence)
else
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*/
resend = client->frameunion.frames[sequence & UPDATE_MASK].resend;
outno = 0;
outmax = client->frameunion.frames[sequence & UPDATE_MASK].entities.max_entities;
outmax = client->frameunion.frames[sequence & UPDATE_MASK].maxresend;
/*start writing the packet*/
MSG_WriteByte (msg, svcfte_updateentities);
@ -1564,7 +1564,7 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
}
if (outno >= outmax)
{ //expand the frames. may need some copying...
SVFTE_ExpandFrames(client, outno+1);
SV_ExpandNackFrames(client, outno+1);
break;
}
@ -1615,7 +1615,7 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
else
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;
return overflow;
}
@ -1642,7 +1642,7 @@ void SVQW_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t
if (client->delta_sequence != -1)
{
fromframe = &client->frameunion.frames[client->delta_sequence & UPDATE_MASK];
from = &fromframe->entities;
from = &fromframe->qwentities;
oldmax = from->num_entities;
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);
}
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;
int oldindex, newindex;
int oldnum, newnum;
int oldmax;
packet_entities_t *cur;
int newindex;
int curnum, newnum;
int j;
int sequence = client->netchan.incoming_sequence;
// this is the frame that we are going to delta update from
cur = &client->sentents;
if (!client->netchan.incoming_sequence)
{
oldmax = 0;
from = NULL;
}
else
{
from = &client->sentents;
oldmax = from->num_entities;
{ //first packet deltas from nothing.
//so make sure we start with nothing
cur->num_entities = 0;
}
if (to->num_entities)
{
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);
memset(&from->entities[from->max_entities], 0, sizeof(from->entities[0]) * (j - from->max_entities));
from->max_entities = j;
cur->entities = BZ_Realloc(cur->entities, sizeof(*cur->entities) * j);
memset(&cur->entities[cur->max_entities], 0, sizeof(cur->entities[0]) * (j - cur->max_entities));
cur->max_entities = j;
}
while(j > client->sentents.num_entities)
while(j > cur->num_entities)
{
from->entities[from->num_entities].number = 0;
from->num_entities++;
cur->entities[cur->num_entities].number = 0;
cur->num_entities++;
}
}
//diff the from+to states, flagging any changed state (which is combined with any state from previous packet loss
newindex = 0;
oldindex = 0;
while (newindex < to->num_entities || oldindex < oldmax)
curnum = 0;
while (newindex < to->num_entities || curnum < cur->num_entities)
{
newnum = newindex >= to->num_entities ? 0x7fff : to->entities[newindex].number;
oldnum = oldindex >= oldmax ? 0x7fff : from->entities[oldindex].number;
newnum = newindex >= to->num_entities ? 0x8000 : to->entities[newindex].number;
if (newnum < oldnum)
{ // 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);
newindex++;
}
else if (newnum > oldnum)
{ // the old entity isn't present in the new message
client->pendingdeltabits[oldnum] = E5_SERVERREMOVE;
oldindex++;
}
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;
if (newnum == curnum)
{
if (cur->entities[curnum].number)
{ //regular update
client->pendingdeltabits[newnum] |= SVDP_CalcDelta(&cur->entities[curnum], NULL/*cur->bonedata*/, &to->entities[newindex], 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++;
}
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
// 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;
oldnum = oldindex >= oldmax ? 0x7fff : from->entities[oldindex].number;
unsigned int bits;
int outno, outmax = frame->maxresend;
qboolean overflow = false;
struct resendinfo_s *resend = frame->resend;
if (newnum == oldnum)
{ // delta update from old position
//Con_Printf ("delta %i\n", newnum);
SVDP_EmitEntityDelta (&from->entities[oldindex], &to->entities[newindex], msg, false, to->bonedata);
oldindex++;
newindex++;
continue;
}
MSG_WriteByte(msg, svcdp_entities);
MSG_WriteLong(msg, 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.
if (newnum < oldnum)
{ // 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;
}
client->netchan.incoming_sequence++;
if (newnum > oldnum)
{ // the old entity isn't present in the new message
// Con_Printf("sRemove %i\n", oldnum);
MSG_WriteShort(msg, oldnum | 0x8000);
oldindex++;
continue;
//add in the bitmasks of dropped packets.
for(outno = 0, j = 1; j < to->num_entities; j++)
{
bits = client->pendingdeltabits[j];
if (!bits)
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
@ -3965,7 +3991,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
}
host_client = client;
if ((client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) || !frame->entities.entities)
if ((client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) || !frame->qwentities.entities || ISNQCLIENT(client))
{
pack = &svs.entstatebuffer;
if (pack->max_entities < client->max_net_ents)
@ -3976,7 +4002,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
}
}
else
pack = &frame->entities;
pack = &frame->qwentities;
SV_Snapshot_Clear(pack);
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)
SVDP_EmitEntitiesUpdate(client, pack, msg);
SVDP_EmitEntitiesUpdate(client, frame, pack, msg);
else
{
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)
{
int j;
for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
{
if (pr_global_ptrs->spawnparamglobals[j])
*pr_global_ptrs->spawnparamglobals[j] = client->spawn_parms[j];
}
SV_SpawnParmsToQC(client);
#ifdef VM_Q1
if (svs.gametype == GT_Q1QVM)
@ -314,11 +340,7 @@ void SV_SaveSpawnparmsClient(client_t *client, float *transferparms)
}
else
{
for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
{
if (pr_global_ptrs->spawnparamglobals[j])
client->spawn_parms[j] = *pr_global_ptrs->spawnparamglobals[j];
}
SV_SpawnParmsToClient(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)
{
int i;
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
@ -408,13 +428,8 @@ void SV_GetNewSpawnParms(client_t *cl)
if (pr_global_ptrs->SetNewParms)
PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms);
}
for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
{
if (pr_global_ptrs->spawnparamglobals[i])
cl->spawn_parms[i] = *pr_global_ptrs->spawnparamglobals[i];
else
cl->spawn_parms[i] = 0;
}
SV_SpawnParmsToClient(cl);
}
}
@ -1645,14 +1660,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
{
sv_player = host_client->edict;
SV_ExtractFromUserinfo(host_client, true);
// 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_SpawnParmsToQC(host_client);
SV_SetUpClientEdict(host_client, sv_player);
#ifndef NOLEGACY
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;
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;
ptr += sizeof(*client->frameunion.frames[i].resend)*maxents;
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);
for (i = 0; i < UPDATE_BACKUP; i++)
{
client->frameunion.frames[i].entities.max_entities = 0;
client->frameunion.frames[i].entities.entities = NULL;
client->frameunion.frames[i].qwentities.max_entities = 0;
client->frameunion.frames[i].qwentities.entities = NULL;
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);
for (i = 0; i < UPDATE_BACKUP; i++)
{
client->frameunion.frames[i].entities.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.max_entities = maxpacketentities;
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;
}
}

View File

@ -1569,10 +1569,13 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
edict_t *ent;
int i;
float newa;
client_t *controller;
ent = client->edict;
if (client->controller)
client = client->controller;
controller = client->controller;
else
controller = client;
if (!ent)
return;
@ -1613,8 +1616,8 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
if (!client->lockangles)
{
//try to keep them vaugely reliable.
if (client->netchan.message.cursize < client->netchan.message.maxsize/2)
msg = &client->netchan.message;
if (controller->netchan.message.cursize < controller->netchan.message.maxsize/2)
msg = &controller->netchan.message;
}
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, 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);
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
} preferedprot[] =
{
// {SCP_DARKPLACES7, true},
// {SCP_DARKPLACES6, true},
{SCP_DARKPLACES7, true},
{SCP_DARKPLACES6, true},
{SCP_FITZ666, true}, //actually 999... shh...
{SCP_FITZ666, false},
{SCP_BJP3, false}
@ -604,7 +604,7 @@ void SVNQ_New_f (void)
protoname = "NQ";
}
break;
/*case SCP_DARKPLACES6:
case SCP_DARKPLACES6:
SV_LogPlayer(host_client, "new (DP6)");
protmain = PROTOCOL_VERSION_DP6;
protext1 &= ~PEXT_FLOATCOORDS; //always enabled, try not to break things
@ -615,7 +615,7 @@ void SVNQ_New_f (void)
protmain = PROTOCOL_VERSION_DP7;
protext1 &= ~PEXT_FLOATCOORDS; //always enabled, try not to break things
protoname = "DPP7";
break;*/
break;
default:
host_client->drop = true;
protoname = "?""?""?";
@ -1824,14 +1824,12 @@ void SV_SpawnSpectator (void)
return;
}
}
}
void SV_Begin_Core(client_t *split)
{ //this is the client-protocol-independant core, for q1/q2 gamecode
client_t *oh;
int i;
#ifdef HEXEN2
if (progstype == PROG_H2 && split->playerclass)
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
for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
{
if (pr_global_ptrs->spawnparamglobals[i])
*pr_global_ptrs->spawnparamglobals[i] = split->spawn_parms[i];
}
SV_SpawnParmsToQC(split);
// call the spawn function
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);
if (eval2)
eval2->_float = 1;
for (j=0 ; j< NUM_SPAWN_PARMS ; j++)
{
if (pr_global_ptrs->spawnparamglobals[j])
*pr_global_ptrs->spawnparamglobals[j] = split->spawn_parms[j];
}
SV_SpawnParmsToQC(split);
pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent);
G_FLOAT(OFS_PARM0) = sv.time - split->spawninfotime;
@ -1925,11 +1915,7 @@ void SV_Begin_Core(client_t *split)
else
{
// 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] = split->spawn_parms[i];
}
SV_SpawnParmsToQC(split);
// call the spawn function
#ifdef VM_Q1
@ -4991,13 +4977,8 @@ void Cmd_Join_f (void)
#endif
if (pr_global_ptrs->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);
#ifdef VM_Q1
if (svs.gametype == GT_Q1QVM)
@ -5131,14 +5112,8 @@ void Cmd_Observe_f (void)
#endif
if (pr_global_ptrs->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 ();
// call the spawn function
@ -5372,7 +5347,6 @@ static void SVNQ_Spawn_f (void)
static void SVNQ_Begin_f (void)
{
unsigned pmodel = 0, emodel = 0;
int i;
qboolean sendangles=false;
if (host_client->state == cs_spawned)
@ -5394,11 +5368,7 @@ static void SVNQ_Begin_f (void)
if (SpectatorConnect)
{
// 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] = host_client->spawn_parms[i];
}
SV_SpawnParmsToQC(host_client);
// call the spawn function
pr_global_struct->time = sv.world.physicstime;
@ -5412,11 +5382,7 @@ static void SVNQ_Begin_f (void)
sv.spawned_client_slots++;
// 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] = host_client->spawn_parms[i];
}
SV_SpawnParmsToQC(host_client);
sv.skipbprintclient = host_client;
#ifdef VM_Q1
@ -5951,6 +5917,7 @@ ucmd_t nqucmds[] =
{"playermodel", NULL},
{"playerskin", NULL},
{"rate", SV_Rate_f},
{"rate_burstsize", NULL},
#ifdef SVRANKING
{"topten", Rank_ListTop10_f},

View File

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