tweak intermissions a little so that quakeworld mods actually works properly (especially mvds).

dynamically allocate music_playlist_* cvars. may require the use of set from configs in order to create them in advance.
add a trail to rogue's plasma weapon.
fix r_waterstyle bug
attempt to optimise qcvm slightly.
tweak copyentity to be a bit more useful.
tweak ban code slightly. 'stealth' penalty hides other penalties.
fix some d3d9 rendering issues with q3.
fix some q2 stuff.
add the NOLEGACY thing that a few people have asked for lately.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4978 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-09-01 04:45:15 +00:00
parent 7a69604a76
commit 8241ed13be
71 changed files with 1132 additions and 506 deletions

View File

@ -1061,6 +1061,14 @@ ifeq (win,$(findstring win,$(FTE_TARGET))$(findstring _SDL,$(FTE_TARGET)))
MINGL_EXE_NAME=../fteminglqw$(BITS)$(EXEPOSTFIX)
MINGL_DIR=mingl_mgw$(BITS)
ifeq ($(NOCOMPAT),1)
SV_EXE_NAME=../engine_sv$(BITS)$(EXEPOSTFIX)
GL_EXE_NAME=../engine_gl$(BITS)$(EXEPOSTFIX)
M_EXE_NAME=../engine$(BITS)$(EXEPOSTFIX)
D3D_EXE_NAME=../engine_d3d$(BITS)$(EXEPOSTFIX)
MINGL_EXE_NAME=../engine_cl_gl$(BITS)$(EXEPOSTFIX)
endif
endif
ifeq ($(FTE_TARGET),bsd)

View File

@ -120,6 +120,7 @@ static float CL_TrackScoreProp(player_info_t *pl, char rule, float *weights)
}
return 0;
}
#ifdef QUAKESTATS
case 'a': //armour value
return pl->statsf[STAT_ARMOR];
case 'h':
@ -147,6 +148,7 @@ static float CL_TrackScoreProp(player_info_t *pl, char rule, float *weights)
r += (pl->stats[STAT_ITEMS] & IT_QUAD)?weights[12]:0;
r += (pl->stats[STAT_ITEMS] & IT_INVULNERABILITY)?weights[13]:0;
return r;
#endif
case 'f': //frags
return pl->frags;
// case 'F': //team frags
@ -470,6 +472,7 @@ static int CL_FindHighTrack(int seat, char *rule)
{
i = cl.playerview[seat].cam_spec_track;
//extra hacks to prevent 'random' switching mid-game
#ifdef QUAKESTATS
if ((cl.players[j].stats[STAT_ITEMS] ^ cl.players[i].stats[STAT_ITEMS]) & (IT_INVULNERABILITY|IT_QUAD))
; //don't block if the players have different powerups
else if ((cl.players[j].stats[STAT_ITEMS] & (IT_ROCKET_LAUNCHER|IT_LIGHTNING)) && !(cl.players[i].stats[STAT_ITEMS] & (IT_ROCKET_LAUNCHER|IT_LIGHTNING)))
@ -477,6 +480,7 @@ static int CL_FindHighTrack(int seat, char *rule)
else if ((cl.players[j].stats[STAT_ITEMS] & (IT_ROCKET_LAUNCHER|IT_INVULNERABILITY))==(IT_ROCKET_LAUNCHER|IT_INVULNERABILITY) && (cl.players[i].stats[STAT_ITEMS] & (IT_ROCKET_LAUNCHER|IT_LIGHTNING)) != (IT_ROCKET_LAUNCHER|IT_INVULNERABILITY))
; //don't block if we're switching to someone with pent+rl from someone that does not.
else
#endif
return cl.playerview[seat].cam_spec_track;
}
return j;
@ -569,9 +573,11 @@ void Cam_Lock(playerview_t *pv, int playernum)
pv->cam_state = cl_chasecam.ival?CAM_EYECAM:CAM_PENDING; //instantly lock if the player is valid.
pv->viewentity = playernum+1;
*/
#ifdef QUAKESTATS
if (cls.z_ext & Z_EXT_VIEWHEIGHT)
pv->viewheight = cl.players[playernum].statsf[STAT_VIEWHEIGHT];
#endif
}
Sbar_Changed();

View File

@ -3940,6 +3940,7 @@ void CL_LinkProjectiles (void)
ent->playerindex = -1;
ent->topcolour = TOP_DEFAULT;
ent->bottomcolour = BOTTOM_DEFAULT;
ent->framestate.g[FS_REG].lerpweight[0] = 1;
#ifdef PEXT_SCALE
ent->scale = 1;
@ -4037,11 +4038,13 @@ void CL_ParsePlayerinfo (void)
memcpy(state, prevstate, sizeof(player_state_t));
info->prevcount = cl.parsecount;
#ifdef QUAKESTATS
if (cls.findtrack && info->stats[STAT_HEALTH] > 0)
{ //FIXME: is this still needed with the autotrack stuff?
Cam_Lock(&cl.playerview[0], num);
cls.findtrack = false;
}
#endif
flags = MSG_ReadShort ();
state->flags = MVD_TranslateFlags(flags);
@ -4104,6 +4107,7 @@ void CL_ParsePlayerinfo (void)
TP_ParsePlayerInfo(oldstate, state, info);
#ifdef QUAKESTATS
//can't CL_SetStatInt as we don't know if its actually us or not
cl.players[num].stats[STAT_WEAPONFRAME] = state->weaponframe;
cl.players[num].statsf[STAT_WEAPONFRAME] = state->weaponframe;
@ -4116,6 +4120,7 @@ void CL_ParsePlayerinfo (void)
pv->statsf[STAT_WEAPONFRAME] = state->weaponframe;
}
}
#endif
//add a new splitscreen autotrack view if we can
if (cl.splitclients < MAX_SPLITS && !cl.players[num].spectator)
@ -4342,6 +4347,7 @@ guess_pm_type:
TP_ParsePlayerInfo(oldstate, state, info);
#ifdef QUAKESTATS
//can't CL_SetStatInt as we don't know if its actually us or not
for (i = 0; i < cl.splitclients; i++)
{
@ -4352,6 +4358,7 @@ guess_pm_type:
pv->statsf[STAT_WEAPONFRAME] = state->weaponframe;
}
}
#endif
if (cl.worldmodel && cl.do_lerp_players && cl_predict_players.ival)
{
@ -4786,6 +4793,7 @@ void CL_LinkPlayers (void)
void CL_LinkViewModel(void)
{
#ifdef QUAKESTATS
entity_t ent;
unsigned int plnum;
@ -4813,7 +4821,7 @@ void CL_LinkViewModel(void)
if (r_refdef.playerview->stats[STAT_HEALTH] <= 0)
return;
if (cl.intermission)
if (cl.intermissionmode != IM_NONE)
return;
if (pv->stats[STAT_WEAPONMODELI] <= 0 || pv->stats[STAT_WEAPONMODELI] >= MAX_PRECACHE_MODELS)
@ -4936,6 +4944,7 @@ void CL_LinkViewModel(void)
ent.shaderRGBAf[3] = alpha;
ent.flags |= RF_TRANSLUCENT;
}
#endif
}
//======================================================================

View File

@ -290,11 +290,14 @@ void IN_JumpDown (void)
KeyDown(&in_up);
else
#endif
#ifdef QUAKESTATS
if (condition && cl.playerview[pnum].stats[STAT_HEALTH] > 0 && !cls.demoplayback && !cl.spectator &&
cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[cl.playerview[pnum].playernum].messagenum == cl.validsequence && cl.playerview[pnum].waterlevel >= 2 && (!cl.teamfortress || !(in_forward.state[pnum] & 1))
)
KeyDown(&in_up);
else if (condition && cl.spectator && !CAM_ISLOCKED(&cl.playerview[pnum]))
else
#endif
if (condition && cl.spectator && !CAM_ISLOCKED(&cl.playerview[pnum]))
KeyDown(&in_up);
else
KeyDown(&in_jump);
@ -393,6 +396,7 @@ void IN_Impulse (void)
newimp = Q_atoi(Cmd_Argv(1));
#ifdef QUAKESTATS
if (Cmd_Argc() > 2)
{
items = cl.playerview[pnum].stats[STAT_ITEMS];
@ -443,6 +447,7 @@ void IN_Impulse (void)
if (best)
newimp = best;
}
#endif
if (in_impulsespending[pnum]>=IN_IMPULSECACHE)
{
@ -698,7 +703,7 @@ void CL_ClampPitch (int pnum)
playerview_t *pv = &cl.playerview[pnum];
oldtime = realtime;
if (cl.intermission)
if (cl.intermissionmode != IM_NONE)
{
memset(pv->viewanglechange, 0, sizeof(pv->viewanglechange));
return;

View File

@ -29,7 +29,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <ctype.h>
// callbacks
void QDECL CL_Sbar_Callback(struct cvar_s *var, char *oldvalue);
#ifdef NQPROT
void QDECL Name_Callback(struct cvar_s *var, char *oldvalue);
#else
#define Name_Callback NULL
#endif
// we need to declare some mouse variables here, because the menu system
// references them even when on a unix system.
@ -204,7 +208,6 @@ entity_state_t *cl_baselines;
static_entity_t *cl_static_entities;
unsigned int cl_max_static_entities;
lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
//lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
dlight_t *cl_dlights;
unsigned int cl_maxdlights; /*size of cl_dlights array*/
@ -311,7 +314,10 @@ void CL_UpdateWindowTitle(void)
Q_snprintfz(title, sizeof(title), "%s: %s", fs_gamename.string, cls.servername);
break;
case ca_disconnected:
Q_snprintfz(title, sizeof(title), "%s: disconnected", fs_gamename.string);
if (cl.worldmodel) //pure csqc mods can have a world model and yet be disconnected. we don't really know what the current map should be called though.
Q_snprintfz(title, sizeof(title), "%s", fs_gamename.string);
else
Q_snprintfz(title, sizeof(title), "%s: disconnected", fs_gamename.string);
break;
}
@ -750,6 +756,11 @@ void CL_CheckForResend (void)
}
else if (!strcmp(cl_loopbackprotocol.string, "qwid") || !strcmp(cl_loopbackprotocol.string, "idqw"))
cls.protocol = CP_QUAKEWORLD;
#ifdef Q3CLIENT
else if (!strcmp(cl_loopbackprotocol.string, "q3"))
cls.protocol = CP_QUAKE3;
#endif
#ifdef NQPROT
else if (!strcmp(cl_loopbackprotocol.string, "fitz")) //actually proquake, because we might as well use the extra angles
{
cls.protocol = CP_NETQUAKE;
@ -765,8 +776,6 @@ void CL_CheckForResend (void)
cls.protocol = CP_NETQUAKE;
cls.protocol_nq = CPNQ_ID;
}
else if (!strcmp(cl_loopbackprotocol.string, "q3"))
cls.protocol = CP_QUAKE3;
else if (!strcmp(cl_loopbackprotocol.string, "dp6") || !strcmp(cl_loopbackprotocol.string, "dpp6"))
{
cls.protocol = CP_NETQUAKE;
@ -777,20 +786,23 @@ void CL_CheckForResend (void)
cls.protocol = CP_NETQUAKE;
cls.protocol_nq = CPNQ_DP7;
}
else if (progstype == PROG_QW || progstype == PROG_H2) //h2 depends on various extensions and doesn't really match either protocol.
{
cls.protocol = CP_QUAKEWORLD;
pext1 = Net_PextMask(1, false);
pext2 = Net_PextMask(2, false);
}
else
else if (progstype != PROG_QW && progstype != PROG_H2) //h2 depends on various extensions and doesn't really match either protocol, but we go for qw because that gives us all sorts of extensions.
{
cls.protocol = CP_NETQUAKE;
cls.protocol_nq = CPNQ_FITZ666;
//FIXME: pext
}
#endif
else
{
cls.protocol = CP_QUAKEWORLD;
pext1 = Net_PextMask(1, false);
pext2 = Net_PextMask(2, false);
}
#ifdef NETPREPARSE
if (dpcompat_nopreparse.ival)
#endif
{
if (progstype == PROG_QW && cls.protocol != CP_QUAKEWORLD)
{
@ -824,6 +836,7 @@ void CL_CheckForResend (void)
CL_FlushClientCommands(); //clear away all client->server clientcommands.
connectinfo.protocol = cls.protocol;
#ifdef NQPROT
if (connectinfo.protocol == CP_NETQUAKE)
{
if (!NET_StringToAdr (cls.servername, connectinfo.defaultport, &connectinfo.adr))
@ -868,6 +881,7 @@ void CL_CheckForResend (void)
connectinfo.trying = false;
}
else
#endif
{
if (!connectinfo.challenge)
connectinfo.challenge = rand();
@ -1491,8 +1505,10 @@ void CL_ClearState (void)
cl.playerview[i].maxspeed = 320;
cl.playerview[i].entgravity = 1;
}
for (i = 0; i < MAX_CLIENTS; i++)
#ifdef QUAKESTATS
for (i = 0; i < MAX_CLIENTS; i++) //in case some server doesn't support it
cl.players[i].stats[STAT_VIEWHEIGHT] = cl.players[i].statsf[STAT_VIEWHEIGHT] = DEFAULT_VIEWHEIGHT;
#endif
cl.minpitch = -70;
cl.maxpitch = 80;
@ -1604,7 +1620,7 @@ void CL_Disconnect (void)
r_worldentity.model = NULL;
cl.spectator = 0;
cl.sendprespawn = false;
cl.intermission = 0;
cl.intermissionmode = IM_NONE;
cl.oldgametime = 0;
#ifdef NQPROT
@ -2021,6 +2037,7 @@ void CL_CheckServerInfo(void)
if (cl.gamespeed < 0.1)
cl.gamespeed = 1;
#ifdef QUAKESTATS
s = Info_ValueForKey(cl.serverinfo, "status");
oldstate = cl.matchstate;
if (!stricmp(s, "standby"))
@ -2055,6 +2072,7 @@ void CL_CheckServerInfo(void)
}
if (oldstate != cl.matchstate)
cl.matchgametimestart = cl.gametime;
#endif
CL_CheckServerPacks();
@ -2492,7 +2510,7 @@ void CL_Changing_f (void)
SCR_BeginLoadingPlaque();
S_StopAllSounds (true);
cl.intermission = 0;
cl.intermissionmode = IM_NONE;
if (cls.state)
{
cls.state = ca_connected; // not active anymore, but not disconnected
@ -4973,7 +4991,7 @@ double Host_Frame (double time)
{
extern cvar_t scr_chatmodecvar;
if (scr_chatmodecvar.ival && !cl.intermission)
if (scr_chatmodecvar.ival && cl.intermissionmode == IM_NONE)
scr_chatmode = (cl.spectator&&cl.splitclients<2&&cls.state == ca_active)?2:1;
else
scr_chatmode = 0;
@ -5236,6 +5254,13 @@ void CL_ExecInitialConfigs(char *resetcommand)
Cbuf_AddText("\n", RESTRICT_LOCAL);
COM_ParsePlusSets(true);
#ifdef QUAKETC
def = COM_FDepthFile("default.cfg", true);
if (COM_FCheckExists ("config.cfg"))
Cbuf_AddText ("exec config.cfg\n", RESTRICT_LOCAL);
if (COM_FCheckExists ("autoexec.cfg"))
Cbuf_AddText ("exec autoexec.cfg\n", RESTRICT_LOCAL);
#else
//who should we imitate?
qrc = COM_FDepthFile("quake.rc", true); //q1
hrc = COM_FDepthFile("hexen.rc", true); //h2
@ -5255,7 +5280,6 @@ void CL_ExecInitialConfigs(char *resetcommand)
Cbuf_AddText ("exec q3config.cfg\n", RESTRICT_LOCAL);
Cbuf_AddText ("exec autoexec.cfg\n", RESTRICT_LOCAL);
}
#ifndef QUAKETC
Cbuf_AddText ("exec fte.cfg\n", RESTRICT_LOCAL);
#endif
#ifdef QUAKESPYAPI

View File

@ -4751,6 +4751,7 @@ static void CL_SetStat_Internal (int pnum, int stat, int ivalue, float fvalue)
if (cl.playerview[pnum].stats[stat] != ivalue)
Sbar_Changed ();
#ifdef QUAKESTATS
if (stat == STAT_ITEMS)
{ // set flash times
for (j=0 ; j<32 ; j++)
@ -4771,6 +4772,7 @@ static void CL_SetStat_Internal (int pnum, int stat, int ivalue, float fvalue)
if (stat == STAT_VIEWHEIGHT && ((cls.z_ext & Z_EXT_VIEWHEIGHT) || cls.protocol == CP_NETQUAKE))
cl.playerview[pnum].viewheight = fvalue;
#endif
cl.playerview[pnum].stats[stat] = ivalue;
cl.playerview[pnum].statsf[stat] = fvalue;
@ -4779,6 +4781,7 @@ static void CL_SetStat_Internal (int pnum, int stat, int ivalue, float fvalue)
TP_StatChanged(stat, ivalue);
}
#ifdef NQPROT
void CL_SetStatMovevar(int pnum, int stat, float value)
{
switch(stat)
@ -4815,6 +4818,7 @@ void CL_SetStatMovevar(int pnum, int stat, float value)
break;
}
}
#endif
//the two values are expected to be the same, they're just both provided for precision.
static void CL_SetStatNumeric (int pnum, int stat, int ivalue, float fvalue)
@ -4823,6 +4827,7 @@ static void CL_SetStatNumeric (int pnum, int stat, int ivalue, float fvalue)
return;
// Host_EndGame ("CL_SetStat: %i is invalid", stat);
#ifdef QUAKESTATS
if (stat == STAT_TIME && (cls.fteprotocolextensions & PEXT_ACCURATETIMINGS))
{
cl.oldgametime = cl.gametime;
@ -4831,6 +4836,7 @@ static void CL_SetStatNumeric (int pnum, int stat, int ivalue, float fvalue)
cl.gametime = fvalue * 0.001;
cl.gametimemark = realtime;
}
#endif
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
{
@ -4845,9 +4851,12 @@ static void CL_SetStatNumeric (int pnum, int stat, int ivalue, float fvalue)
else
CL_SetStat_Internal(pnum, stat, ivalue, fvalue);
#ifdef QUAKESTATS
if (stat == STAT_VIEWHEIGHT && ((cls.z_ext & Z_EXT_VIEWHEIGHT) || cls.protocol == CP_NETQUAKE))
cl.playerview[pnum].viewheight = fvalue;
#endif
#ifdef NQPROT
if (cls.protocol == CP_NETQUAKE && CPNQ_IS_DP)
{
if (cls.fteprotocolextensions2 & PEXT2_PREDINFO)
@ -4855,6 +4864,7 @@ static void CL_SetStatNumeric (int pnum, int stat, int ivalue, float fvalue)
else
CL_SetStatMovevar(pnum, stat, *(float*)&ivalue); //DP sucks.
}
#endif
}
static void CL_SetStatInt (int pnum, int stat, int ivalue)
{
@ -5230,8 +5240,10 @@ char *CL_ParseChat(char *text, player_info_t **player, int *msgflags)
if (flags & (TPM_TEAM|TPM_OBSERVEDTEAM) && !TP_FilterMessage(text + offset))
return NULL;
#ifdef QUAKEHUD
if (flags & (TPM_TEAM|TPM_OBSERVEDTEAM) && Sbar_UpdateTeamStatus(*player, text+offset))
return NULL;
#endif
if ((int)msg_filter.value & flags)
@ -6024,7 +6036,7 @@ void CLQW_ParseServerMessage (void)
inf->packet_entities.fixangles[0] = 2;
VectorCopy(demoangles, inf->packet_entities.fixedangles[0]);
}
else if (cl.intermission)
else if (cl.intermissionmode != IM_NONE)
{
for (destsplit = 0; destsplit < cl.splitclients; destsplit++)
{
@ -6344,13 +6356,17 @@ void CLQW_ParseServerMessage (void)
case svc_killedmonster:
//fixme: update all player stats
#ifdef QUAKESTATS
cl.playerview[destsplit].stats[STAT_MONSTERS]++;
cl.playerview[destsplit].statsf[STAT_MONSTERS]++;
#endif
break;
case svc_foundsecret:
//fixme: update all player stats
#ifdef QUAKESTATS
cl.playerview[destsplit].stats[STAT_SECRETS]++;
cl.playerview[destsplit].statsf[STAT_SECRETS]++;
#endif
break;
case svcqw_updatestatbyte:
@ -6389,14 +6405,14 @@ void CLQW_ParseServerMessage (void)
break;
case svc_intermission:
if (!cl.intermission)
if (cl.intermissionmode == IM_NONE)
{
TP_ExecTrigger ("f_mapend", false);
if (cl.spectator)
TP_ExecTrigger ("f_specmapend", true);
cl.completed_time = cl.gametime;
}
cl.intermission = 1;
cl.completed_time = cl.gametime;
cl.intermissionmode = IM_QWSCORES;
for (i=0 ; i<3 ; i++)
cl.playerview[destsplit].simorg[i] = MSG_ReadCoord ();
for (i=0 ; i<3 ; i++)
@ -6404,15 +6420,14 @@ void CLQW_ParseServerMessage (void)
break;
case svc_finale:
if (!cl.intermission)
if (cl.intermissionmode == IM_NONE)
{
for (i = 0; i < MAX_SPLITS; i++)
cl.playerview[i].simorg[2] += cl.playerview[i].viewheight;
VectorCopy (cl.playerview[destsplit].simangles, cl.playerview[destsplit].intermissionangles);
cl.completed_time = cl.gametime;
}
cl.intermission = 2;
cl.completed_time = cl.gametime;
cl.intermissionmode = IM_NQFINALE;
SCR_CenterPrint (destsplit, MSG_ReadString (), false);
break;
@ -7251,21 +7266,31 @@ void CLNQ_ParseServerMessage (void)
break;
case svc_intermission:
if (!cl.intermission)
if (cl.intermissionmode == IM_NONE)
{
TP_ExecTrigger ("f_mapend", false);
cl.intermission = 1;
cl.completed_time = cl.gametime;
cl.completed_time = cl.gametime;
}
cl.intermissionmode = IM_NQSCORES;
break;
case svc_finale:
cl.intermission = 2;
cl.completed_time = cl.gametime;
if (cl.intermissionmode == IM_NONE)
{
TP_ExecTrigger ("f_mapend", false);
cl.completed_time = cl.gametime;
}
cl.intermissionmode = IM_NQFINALE;
SCR_CenterPrint (0, MSG_ReadString (), false);
break;
case svc_cutscene:
cl.intermission = 3;
cl.completed_time = cl.gametime;
if (cl.intermissionmode == IM_NONE)
{
TP_ExecTrigger ("f_mapend", false);
cl.completed_time = cl.gametime;
}
cl.intermissionmode = IM_NQCUTSCENE;
SCR_CenterPrint (0, MSG_ReadString (), false);
break;

View File

@ -552,7 +552,7 @@ static qintptr_t VARGS Plug_GetServerInfo(void *offset, quintptr_t mask, const q
return false;
Q_strncpyz(outptr, cl.serverinfo, outlen);
Q_strncatz(outptr, va("\\intermission\\%i", cl.intermission), outlen);
Q_strncatz(outptr, va("\\intermission\\%i", cl.intermissionmode), outlen);
switch(cls.demoplayback)
{
case DPB_NONE:
@ -577,9 +577,11 @@ static qintptr_t VARGS Plug_GetServerInfo(void *offset, quintptr_t mask, const q
}
Q_strncatz(outptr, va("\\demotime\\%f", demtime-cls.demostarttime), outlen);
#ifdef QUAKEHUD
if (cl.playerview[0].statsf[STAT_MATCHSTARTTIME])
Q_strncatz(outptr, va("\\matchstart\\%f", cl.playerview[0].statsf[STAT_MATCHSTARTTIME]/1000), outlen);
else
else
#endif
Q_strncatz(outptr, va("\\matchstart\\%f", cl.matchgametimestart), outlen);
return true;
@ -697,6 +699,7 @@ static qintptr_t VARGS Plug_GetLocationName(void *offset, quintptr_t mask, const
return VM_LONG(arg[1]);
}
#ifdef QUAKEHUD
typedef struct
{
unsigned int client;
@ -787,6 +790,7 @@ static qintptr_t VARGS Plug_GetTeamInfo(void *offset, quintptr_t mask, const qin
return VM_LONG(count);
}
#endif
static qintptr_t VARGS Plug_Con_SubPrint(void *offset, quintptr_t mask, const qintptr_t *arg)
{
@ -1175,7 +1179,9 @@ void Plug_Client_Init(void)
Plug_RegisterBuiltin("LocalSound", Plug_LocalSound, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("SCR_CenterPrint", Plug_SCR_CenterPrint, PLUG_BIF_NEEDSRENDERER);
#ifdef QUAKEHUD
Plug_RegisterBuiltin("GetTeamInfo", Plug_GetTeamInfo, PLUG_BIF_NEEDSRENDERER);
#endif
Plug_RegisterBuiltin("GetLocationName", Plug_GetLocationName, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("GetPlayerInfo", Plug_GetPlayerInfo, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("LocalPlayerNumber", Plug_LocalPlayerNumber, PLUG_BIF_NEEDSRENDERER);

View File

@ -918,13 +918,13 @@ void CL_PredictMovePNum (int seat)
return;
}
if (0)//cl.intermission==1 && cls.protocol == CP_QUAKEWORLD)
if (cl.intermissionmode == IM_QWSCORES)
{
//quakeworld locks view position once you hit intermission.
VectorCopy (pv->intermissionangles, pv->simangles);
return;
}
else if (cl.intermission)
else if (cl.intermissionmode != IM_NONE)
lerpangles = false; //will do angles later.
else
{
@ -976,7 +976,7 @@ void CL_PredictMovePNum (int seat)
//these things also force-disable prediction
if ((cls.demoplayback==DPB_MVD || cls.demoplayback == DPB_EZTV) ||
cl.intermission || cl.paused || pv->pmovetype == PM_NONE || pv->pmovetype == PM_FREEZE || CAM_ISLOCKED(pv))
cl.intermissionmode != IM_NONE || cl.paused || pv->pmovetype == PM_NONE || pv->pmovetype == PM_FREEZE || CAM_ISLOCKED(pv))
{
nopred = true;
}
@ -1099,12 +1099,14 @@ void CL_PredictMovePNum (int seat)
totime -= (pe->entities[i].u.q1.msec / 1000.0f); //correct the time to match stale players. FIXME: this can push the simtime into the 'future' resulting in stuttering
if (cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
{
#ifdef QUAKESTATS
//putting weapon frames in there was probably a stupid idea.
if (!(cls.fteprotocolextensions2 & PEXT2_PREDINFO))
{
pv->stats[STAT_WEAPONFRAME] = cl.players[pv->playernum].stats[STAT_WEAPONFRAME] = pe->entities[i].u.q1.weaponframe;
pv->statsf[STAT_WEAPONFRAME] = cl.players[pv->playernum].statsf[STAT_WEAPONFRAME] = pe->entities[i].u.q1.weaponframe;
}
#endif
pv->pmovetype = tostate->pm_type;
}
break;
@ -1270,7 +1272,7 @@ void CL_PredictMovePNum (int seat)
else
VectorCopy(pmove.gravitydir, pv->gravitydir);
if (cl.intermission && le)
if (cl.intermissionmode != IM_NONE && le)
{
VectorCopy(le->angles, pv->simangles);
VectorCopy(pv->simangles, pv->viewangles);
@ -1279,7 +1281,9 @@ void CL_PredictMovePNum (int seat)
{
//keep the entity tracking the prediction position, so mirrors don't go all weird
VectorMA(pv->simorg, -pv->crouch, pv->gravitydir, le->origin);
#ifdef QUAKESTATS
if (pv->stats[STAT_HEALTH] > 0)
#endif
{
VectorScale(pv->simangles, 1, le->angles);
if (pv->pmovetype == PM_6DOF)

View File

@ -208,8 +208,6 @@ mpic_t *scr_turtle;
int clearconsole;
int clearnotify;
extern int sb_lines;
viddef_t vid; // global video state
vrect_t scr_vrect;
@ -393,10 +391,14 @@ void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode)
p = &scr_centerprint[pnum];
p->flags = 0;
p->titleimage[0] = 0;
if (cl.intermission)
if (*str != '/')
{
p->flags |= CPRINT_TYPEWRITER | CPRINT_PERSIST | CPRINT_TALIGN;
Q_strncpyz(p->titleimage, "gfx/finale.lmp", sizeof(p->titleimage));
if (cl.intermissionmode != IM_NONE)
{
p->flags |= CPRINT_TYPEWRITER | CPRINT_PERSIST | CPRINT_TALIGN;
Q_strncpyz(p->titleimage, "gfx/finale.lmp", sizeof(p->titleimage));
}
}
while (*str == '/')
@ -428,6 +430,31 @@ void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode)
p->flags ^= CPRINT_LALIGN;
else if (str[1] == 'R')
p->flags ^= CPRINT_RALIGN;
else if (str[1] == 'F')
{ //'F' is reserved for special handling via svc_finale
if (cl.intermissionmode == IM_NONE)
cl.completed_time = cl.time;
str+=2;
switch(*str++)
{
case 'R':
cl.intermissionmode = IM_NONE;
break;
case 'I':
case 'S':
cl.intermissionmode = IM_NQSCORES;
break;
case 'F':
cl.intermissionmode = IM_NQFINALE;
break;
case 0:
str--;
break;
default:
break; //no idea. suck it up for compat.
}
continue;
}
else if (str[1] == 'I')
{
char *e = strchr(str+=2, ':');
@ -624,7 +651,7 @@ void SCR_CheckDrawCenterString (void)
{
p = &scr_centerprint[pnum];
if (p->time_off <= 0 && !cl.intermission && !(p->flags & CPRINT_PERSIST))
if (p->time_off <= 0 && !(p->flags & CPRINT_PERSIST))
continue; //'/P' prefix doesn't time out
p->time_off -= host_frametime;
@ -632,8 +659,10 @@ void SCR_CheckDrawCenterString (void)
if (Key_Dest_Has(~kdm_game)) //don't let progs guis/centerprints interfere with the game menu
continue;
#ifdef QUAKEHUD
if (sb_showscores) //this was annoying
continue;
#endif
if (cl.playerview[pnum].gamerectknown == cls.framecount)
SCR_DrawCenterString(&cl.playerview[pnum].gamerect, p, font_default);
@ -1525,6 +1554,7 @@ void SCR_DrawClock(void)
void SCR_DrawGameClock(void)
{
#ifdef QUAKESTATS
float showtime;
int minutes;
int seconds;
@ -1556,6 +1586,7 @@ void SCR_DrawGameClock(void)
sprintf(str, " %02i:%02i", minutes, seconds);
SCR_StringXY(str, show_gameclock_x.value, show_gameclock_y.value);
#endif
}
/*
@ -2630,18 +2661,18 @@ void SCR_DrawTwoDimensional(int uimenu, qboolean nohud)
SCR_ShowPics_Draw();
}
else if (cl.intermission == 1)
{
Sbar_IntermissionOverlay ();
}
else if (cl.intermission == 2)
else if (cl.intermissionmode == IM_NQFINALE)
{
Sbar_FinaleOverlay ();
SCR_CheckDrawCenterString ();
}
else if (cl.intermission == 3)
else if (cl.intermissionmode == IM_NQCUTSCENE)
{
}
else if (cl.intermissionmode != IM_NONE)
{
Sbar_IntermissionOverlay ();
}
else
{
if (!nohud)

View File

@ -614,7 +614,7 @@ void VQ3_RenderView(const q3refdef_t *ref)
}
r_refdef.areabitsknown = true;
for (i = 0; i < sizeof(cl.q2frame.areabits)/sizeof(int); i++)
for (i = 0; i < MAX_MAP_AREA_BYTES/sizeof(int); i++)
((int*)r_refdef.areabits)[i] = ((int*)ref->areamask)[i] ^ ~0;
R_RenderView();
r_refdef.playerview = NULL;

View File

@ -760,7 +760,15 @@ typedef struct
qboolean paused; // send over by server
int intermission; // don't change view angle, full screen, etc
enum
{
IM_NONE, //off.
IM_NQSCORES, //+showscores forced, view still attached to regular view
IM_NQFINALE, //slow centerprint text etc, view still attached to regular view
IM_NQCUTSCENE, //no overlay at all, nor hud.
IM_QWSCORES //intermission, view locked at a specific point
} intermissionmode; // don't change view angle, full screen, etc
float completed_time; // latched ffrom time at intermission start
#define Q2MAX_VISIBLE_WEAPONS 32 //q2 has about 20.

View File

@ -1247,6 +1247,14 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y,
break;
}
if (i == 50)
{
s = (conchar_t*)(con->completionline+1);
end = COM_ParseFunString((COLOR_WHITE<<CON_FGSHIFT), va("MORE"), s+con->completionline->length, (con->completionline->maxlength-con->completionline->length)*sizeof(maskedtext[0]), true);
con->completionline->length = end - s;
break;
}
s = (conchar_t*)(con->completionline+1);
// if (desc)
// end = COM_ParseFunString((COLOR_GREEN<<CON_FGSHIFT), va("^[^2/%s\\tip\\%s^]\t", cmd, desc), s+con->completionline->length, (con->completionline->maxlength-con->completionline->length)*sizeof(maskedtext[0]), true);

View File

@ -621,11 +621,13 @@ void IN_MoveMouse(struct mouse_s *mouse, float *movements, int pnum)
mouse_y *= sensitivity.value*in_sensitivityscale;
}
#ifdef QUAKESTATS
if (cl.playerview[pnum].stats[STAT_VIEWZOOM])
{
mouse_x *= cl.playerview[pnum].stats[STAT_VIEWZOOM]/255.0f;
mouse_y *= cl.playerview[pnum].stats[STAT_VIEWZOOM]/255.0f;
}
#endif
if (!movements)
{

View File

@ -2195,7 +2195,6 @@ qboolean Key_MouseShouldBeFree(void)
return false;
}
int Sbar_TranslateHudClick(void);
/*
===================
Key_Event

View File

@ -59,25 +59,8 @@ static int cdnumtracks; //maximum cd track we can play.
//cvar abuse
static int music_playlist_last;
static cvar_t music_playlist_index = CVAR("music_playlist_index", "-1");
static cvar_t music_playlist_list[] =
{
CVAR("music_playlist_list0", ""),
CVAR("music_playlist_list1", ""),
CVAR("music_playlist_list2", ""),
CVAR("music_playlist_list3", ""),
CVAR("music_playlist_list4", ""),
CVAR("music_playlist_list5", "")
};
static cvar_t music_playlist_sampleposition[] =
{
CVAR("music_playlist_sampleposition0", "-1"),
CVAR("music_playlist_sampleposition1", "-1"),
CVAR("music_playlist_sampleposition2", "-1"),
CVAR("music_playlist_sampleposition3", "-1"),
CVAR("music_playlist_sampleposition4", "-1"),
CVAR("music_playlist_sampleposition5", "-1")
};
#define CVAR_ABUSE_LIMIT countof(music_playlist_list)
// created dynamically: CVAR("music_playlist_list0+", ""),
// created dynamically: CVAR("music_playlist_sampleposition0+", "-1"),
static qboolean Media_Changed (unsigned int mediatype)
@ -682,7 +665,7 @@ void M_Media_Remove_f (void)
}
#ifndef NOMEDIAMENU
#if !defined(NOMEDIAMENU) && !defined(NOBUILTINMENUS)
void Media_LoadTrackNames (char *listname);
@ -1161,9 +1144,11 @@ float Media_CrossFade(int musicchanel, float vol, float time)
{
if (Media_Changed(MEDIA_CVARLIST))
{
if (music_playlist_last >= 0 && music_playlist_sampleposition[music_playlist_last].value != -1)
if (music_playlist_last >= 0)
{
Cvar_SetValue(&music_playlist_sampleposition[music_playlist_last], time);
cvar_t *sampleposition = Cvar_Get(va("music_playlist_sampleposition%i", music_playlist_last), "-1", 0, "compat");
if (sampleposition && sampleposition->value != -1)
Cvar_SetValue(sampleposition, time);
}
vol = -1; //kill it NOW
}
@ -1193,7 +1178,7 @@ char *Media_NextTrack(int musicchannelnum, float *starttime)
Q_strncpyz(media_friendlyname, "", sizeof(media_friendlyname));
if (!media_playlistcurrent && (media_playlisttypes & MEDIA_PLAYLIST))
{
#ifndef NOMEDIAMENU
#if !defined(NOMEDIAMENU) && !defined(NOBUILTINMENUS)
if (!loadedtracknames)
Media_LoadTrackNames("sound/media.m3u");
#endif
@ -1205,15 +1190,25 @@ char *Media_NextTrack(int musicchannelnum, float *starttime)
}
if (!media_playlistcurrent && (media_playlisttypes & MEDIA_CVARLIST))
{
if (music_playlist_index.ival >= 0 && music_playlist_index.ival < countof(music_playlist_list))
if (music_playlist_index.ival >= 0)
{
Q_snprintfz(media_currenttrack, sizeof(media_currenttrack), "sound/cdtracks/%s", music_playlist_list[music_playlist_index.ival].string);
Q_strncpyz(media_friendlyname, "", sizeof(media_friendlyname));
media_playlistcurrent = MEDIA_CVARLIST;
music_playlist_last = music_playlist_index.ival;
*starttime = music_playlist_sampleposition[music_playlist_last].value;
if (*starttime == -1)
*starttime = 0;
cvar_t *list = Cvar_Get(va("music_playlist_list%i", music_playlist_index.ival), "", 0, "compat");
if (list)
{
cvar_t *sampleposition = Cvar_Get(va("music_playlist_sampleposition%i", music_playlist_index.ival), "-1", 0, "compat");
Q_snprintfz(media_currenttrack, sizeof(media_currenttrack), "sound/cdtracks/%s", list->string);
Q_strncpyz(media_friendlyname, "", sizeof(media_friendlyname));
media_playlistcurrent = MEDIA_CVARLIST;
music_playlist_last = music_playlist_index.ival;
if (sampleposition)
{
*starttime = sampleposition->value;
if (*starttime == -1)
*starttime = 0;
}
else
*starttime = 0;
}
}
}
if (!media_playlistcurrent && (media_playlisttypes & MEDIA_GAMEMUSIC))
@ -4343,10 +4338,10 @@ void Media_Init(void)
Cmd_AddCommand("music", Media_NamedTrack_f);
Cvar_Register(&music_playlist_index, "compat");
for (i = 0; i < countof(music_playlist_list); i++)
for (i = 0; i < 6; i++)
{
Cvar_Register(&music_playlist_list[i], "compat");
Cvar_Register(&music_playlist_sampleposition[i], "compat");
Cvar_Get(va("music_playlist_list%i", i), "", 0, "compat");
Cvar_Get(va("music_playlist_sampleposition%i", i), "-1", 0, "compat");
}
music_playlist_last = -1;
@ -4386,7 +4381,9 @@ void Media_Init(void)
Cvar_Register(&media_repeat, "Media player things");
Cmd_AddCommand ("media_add", M_Media_Add_f);
Cmd_AddCommand ("media_remove", M_Media_Remove_f);
#if !defined(NOMEDIAMENU) && !defined(NOBUILTINMENUS)
Cmd_AddCommand ("menu_media", M_Menu_Media_f);
#endif
}

View File

@ -2826,6 +2826,8 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_
if (!mods->shadertext)
{
char *body = Shader_GetShaderBody(Mod_ShaderForSkin(ent.model, mods->surfaceidx, mods->skingroup));
if (!body)
break;
mods->shadertext = Z_StrDup(body);
}
R_DrawTextField(r_refdef.grect.x, r_refdef.grect.y+16, r_refdef.grect.width, r_refdef.grect.height-16, mods->shadertext, CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_default, fs);

View File

@ -134,7 +134,7 @@ void M_Menu_Save_f (void)
if (!sv.state)
return;
if (cl.intermission)
if (cl.intermissionmode != IM_NONE)
return;
Key_Dest_Add(kdm_emenu);

View File

@ -48,7 +48,11 @@ static int rand(void)
#include "renderque.h"
#ifdef NOLEGACY
#define R_PARTSET_BUILTINS
#else
#include "r_partset.h"
#endif
struct
{
@ -3016,6 +3020,7 @@ static qboolean P_LoadParticleSet(char *name, qboolean implicit)
cfg->next = loadedconfigs;
loadedconfigs = cfg;
#ifdef PSET_CLASSIC
if (!strcmp(name, "classic"))
{
if (fallback)
@ -3028,6 +3033,7 @@ static qboolean P_LoadParticleSet(char *name, qboolean implicit)
}
return true;
}
#endif
for (i = 0; partset_list[i].name; i++)
{

View File

@ -758,6 +758,32 @@ void QCBUILTIN PF_cl_SetBindMap (pubprogfuncs_t *prinst, struct globalvars_s *pr
G_FLOAT(OFS_RETURN) = 1;
}
//void setmousetarget(float trg) = #603;
void QCBUILTIN PF_cl_setmousetarget (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
world_t *world = prinst->parms->user;
unsigned int target = world->keydestmask;
switch ((int)G_FLOAT(OFS_PARM0))
{
case 1: //1 is delta-based (mt_menu).
key_dest_absolutemouse &= ~target;
break;
case 2: //2 is absolute (mt_client).
key_dest_absolutemouse |= target;
break;
default:
PR_BIError(prinst, "PF_setmousetarget: not a valid destination\n");
}
}
//float getmousetarget(void) = #604;
void QCBUILTIN PF_cl_getmousetarget (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
world_t *world = prinst->parms->user;
unsigned int target = world->keydestmask;
G_FLOAT(OFS_RETURN) = (key_dest_absolutemouse&target)?2:1;
}
//evil builtins to pretend to be a server.
void QCBUILTIN PF_cl_sprint (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{

View File

@ -1857,6 +1857,7 @@ static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars
{
csqc_worldchanged = false;
Surf_NewMap();
CL_UpdateWindowTitle();
}
if (cl.worldmodel)
@ -2282,6 +2283,9 @@ static model_t *csqc_setmodel(pubprogfuncs_t *prinst, csqcedict_t *ent, int mode
{
cl.worldmodel = r_worldentity.model = csqc_world.worldmodel = model;
csqc_worldchanged = true;
VectorAdd(ent->v->origin, ent->v->mins, ent->v->absmin);
VectorAdd(ent->v->origin, ent->v->maxs, ent->v->absmax);
}
}
else
@ -3298,8 +3302,16 @@ void QCBUILTIN PF_soundupdate (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
float startoffset = (prinst->callargc>=8)?G_FLOAT(OFS_PARM7):0;
sfx_t *sfx = S_PrecacheSound(sample);
vec3_t org;
G_FLOAT(OFS_RETURN) = S_UpdateSound(-entity->entnum, channel, sfx, entity->v->origin, volume, attenuation, startoffset, pitchpct, flags);
VectorCopy(entity->v->origin, org);
if (entity->v->solid == SOLID_BSP)
{
VectorMA(org, 0.5, entity->v->mins, org);
VectorMA(org, 0.5, entity->v->maxs, org);
}
G_FLOAT(OFS_RETURN) = S_UpdateSound(-entity->entnum, channel, sfx, org, volume, attenuation, startoffset, pitchpct, flags);
}
void QCBUILTIN PF_stopsound (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -3327,6 +3339,7 @@ static void QCBUILTIN PF_cs_sound(pubprogfuncs_t *prinst, struct globalvars_s *p
float startoffset;
sfx_t *sfx;
vec3_t org;
entity = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
channel = G_FLOAT(OFS_PARM1);
@ -3338,8 +3351,16 @@ static void QCBUILTIN PF_cs_sound(pubprogfuncs_t *prinst, struct globalvars_s *p
startoffset = (prinst->callargc>=8)?G_FLOAT(OFS_PARM7):0;
sfx = S_PrecacheSound(sample);
VectorCopy(entity->v->origin, org);
if (entity->v->solid == SOLID_BSP)
{
VectorMA(org, 0.5, entity->v->mins, org);
VectorMA(org, 0.5, entity->v->maxs, org);
}
if (sfx)
S_StartSound(-entity->entnum, channel, sfx, entity->v->origin, volume, attenuation, startoffset, pitchpct, flags);
S_StartSound(-entity->entnum, channel, sfx, org, volume, attenuation, startoffset, pitchpct, flags);
};
static void QCBUILTIN PF_cs_pointsound(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -5190,6 +5211,7 @@ static struct {
{"frameforname", PF_frameforname, 276},//void(float modidx, string framename) frameforname = #276 (FTE_CSQC_SKELETONOBJECTS)
{"frameduration", PF_frameduration, 277},//void(float modidx, float framenum) frameduration = #277 (FTE_CSQC_SKELETONOBJECTS)
#ifdef TERRAIN
{"terrain_edit", PF_terrain_edit, 278},//void(float action, vector pos, float radius, float quant) terrain_edit = #278 (??FTE_TERRAIN_EDIT??)
{"brush_get", PF_brush_get, 0},
{"brush_create", PF_brush_create, 0},
@ -5198,6 +5220,7 @@ static struct {
{"brush_getfacepoints", PF_brush_getfacepoints, 0},
{"brush_calcfacepoints", PF_brush_calcfacepoints,0},
{"brush_findinvolume", PF_brush_findinvolume, 0},
#endif
{"touchtriggers", PF_touchtriggers, 279},//void() touchtriggers = #279;
{"skel_ragupdate", PF_skel_ragedit, 281},// (FTE_QC_RAGDOLL)
@ -5779,7 +5802,7 @@ void CSQC_Event_Sound (float *origin, wedict_t *wentity, int channel, const char
origin = wentity->v->origin;
}
S_StartSound(NUM_FOR_EDICT(csqcprogs, (edict_t*)wentity), channel, S_PrecacheSound(sample), origin, volume, attenuation, timeoffset, pitchadj, flags);
S_StartSound(NUM_FOR_EDICT(csqcprogs, (edict_t*)wentity), channel, S_PrecacheSound(sample), origin, volume/255.0, attenuation, timeoffset, pitchadj, flags);
}
qboolean CSQC_Event_ContentsTransition(world_t *w, wedict_t *ent, int oldwatertype, int newwatertype)
@ -6309,6 +6332,8 @@ void CSQC_RendererRestarted(void)
void CSQC_WorldLoaded(void)
{
csqcedict_t *worldent;
int tmp;
int wmodelindex;
if (!csqcprogs)
return;
@ -6326,7 +6351,10 @@ void CSQC_WorldLoaded(void)
worldent = (csqcedict_t *)EDICT_NUM(csqcprogs, 0);
worldent->v->solid = SOLID_BSP;
csqc_setmodel(csqcprogs, worldent, cl.worldmodel?1:0);
wmodelindex = CS_FindModel(cl.worldmodel->name, &tmp);
tmp = csqc_worldchanged;
csqc_setmodel(csqcprogs, worldent, wmodelindex);
csqc_worldchanged = tmp;
worldent->readonly = false; //just in case
@ -6347,8 +6375,6 @@ void CSQC_WorldLoaded(void)
csqcmapentitydata = NULL;
worldent->readonly = true;
csqc_worldchanged = false; //should be done elsewhere, don't do it for double-cost.
}
void CSQC_CoreDump(void)
@ -6714,7 +6740,7 @@ qboolean CSQC_DrawView(void)
*csqcg.gamespeed = 0;
}
if (csqcg.intermission)
*csqcg.intermission = cl.intermission;
*csqcg.intermission = cl.intermissionmode;
//work out which packet entities are solid
CL_SetSolidEntities ();

View File

@ -1318,32 +1318,6 @@ void QCBUILTIN PF_cl_getkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr
G_FLOAT(OFS_RETURN) = 0;
}
//void setmousetarget(float trg) = #603;
void QCBUILTIN PF_cl_setmousetarget (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
world_t *world = prinst->parms->user;
unsigned int target = world->keydestmask;
switch ((int)G_FLOAT(OFS_PARM0))
{
case 1: //1 is delta-based (mt_menu).
key_dest_absolutemouse &= ~target;
break;
case 2: //2 is absolute (mt_client).
key_dest_absolutemouse |= target;
break;
default:
PR_BIError(prinst, "PF_setmousetarget: not a valid destination\n");
}
}
//float getmousetarget(void) = #604;
void QCBUILTIN PF_cl_getmousetarget (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
world_t *world = prinst->parms->user;
unsigned int target = world->keydestmask;
G_FLOAT(OFS_RETURN) = (key_dest_absolutemouse&target)?2:1;
}
static void QCBUILTIN PF_Remove_ (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
menuedict_t *ed;

View File

@ -1916,6 +1916,34 @@ char *particle_set_high =
"}\n"
"r_trail \"progs/lspike.mdl\" tr_lavaspike\n"
/////////////////////////////////////////
//rogue plasma gun
"r_part tr_plasma\n"
"{\n"
"type texturedspark\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 97 95 191 256\n"
"scale 15\n"
"step 4\n"
"alpha 0.3\n"
"die 0.25\n"
"rgb 128 128 255\n"
"veladd -32\n"
"spawnmode spiral\n"
"spawnvel 16\n"
"randomvel 32\n"
"friction 0\n"
"scalefactor 1\n"
"blend add\n"
"lighttime 0.2\n"
"lightshadows 0\n"
"lightradius 150\n"
"lightrgb 1 1 2\n"
"lightrgbfade 5 1 0.5\n"
"lightcorona 2 0.5\n"
"}\n"
"r_trail \"progs/plasma.mdl\" tr_plasma\n"
/////////////////////////////////////////
//scrag missiles.

View File

@ -2329,7 +2329,7 @@ void Surf_DrawWorld (void)
{ //generate the info each frame, as the gamecode didn't tell us what to use.
int leafnum = CM_PointLeafnum (cl.worldmodel, r_refdef.vieworg);
int clientarea = CM_LeafArea (cl.worldmodel, leafnum);
CM_WriteAreaBits(cl.worldmodel, r_refdef.areabits, clientarea);
CM_WriteAreaBits(cl.worldmodel, r_refdef.areabits, clientarea, false);
r_refdef.areabitsknown = true;
}
#ifdef Q3BSPS

View File

@ -1089,8 +1089,10 @@ qboolean R_ApplyRenderer (rendererstate_t *newr)
return false;
time = Sys_DoubleTime();
#ifndef NOBUILTINMENUS
M_RemoveAllMenus(true);
#endif
Media_CaptureDemoEnd();
R_ShutdownRenderer(true);
Con_DPrintf("video shutdown took %f seconds\n", Sys_DoubleTime() - time);
@ -1355,6 +1357,7 @@ TRACE(("dbg: R_ApplyRenderer: starting on client state\n"));
#ifdef Q3SERVER
if (svs.gametype == GT_QUAKE3)
{
cl.worldmodel = NULL;
CG_Stop();
CG_Start();
if (cl.worldmodel)
@ -2000,8 +2003,11 @@ qbyte *R_MarkLeaves_Q3 (void)
mnode_t *node;
int portal = r_refdef.recurse;
if (r_oldviewcluster == r_viewcluster && !r_novis.value && r_viewcluster != -1)
return cvis[portal];
if (!portal)
{
if (r_oldviewcluster == r_viewcluster && !r_novis.value && r_viewcluster != -1)
return cvis[portal];
}
// development aid to let you run around and see exactly where
// the pvs ends
@ -2125,7 +2131,7 @@ qbyte *R_MarkLeaves_Q2 (void)
if (r_viewcluster2 != r_viewcluster)
{
vis = CM_ClusterPVS (cl.worldmodel, r_viewcluster2, NULL, sizeof(curframevis));
c = (cl.worldmodel->numleafs+31)/32;
c = (cl.worldmodel->numclusters+31)/32;
for (i=0 ; i<c ; i++)
((int *)curframevis[portal])[i] |= ((int *)vis)[i];
vis = curframevis[portal];

View File

@ -22,10 +22,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#include "shader.h"
extern cvar_t *hud_tracking_show;
#define CON_ALTMASK (CON_2NDCHARSETTEXT|CON_WHITEMASK)
#ifdef QUAKEHUD
extern cvar_t *hud_tracking_show;
cvar_t scr_scoreboard_drawtitle = CVARD("scr_scoreboard_drawtitle", "1", "Wastes screen space when looking at the scoreboard.");
cvar_t scr_scoreboard_forcecolors = CVARD("scr_scoreboard_forcecolors", "0", "Makes the scoreboard colours obey enemycolor/teamcolor rules."); //damn americans
cvar_t scr_scoreboard_newstyle = CVARD("scr_scoreboard_newstyle", "1", "Display team colours and stuff in a style popularised by Electro. Looks more modern, but might not quite fit classic huds."); // New scoreboard style ported from Electro, by Molgrum
@ -172,6 +174,7 @@ int Sbar_BottomColour(player_info_t *p)
return p->rbottomcolor;
}
#endif
//Draws a pre-marked-up string with no width limit. doesn't support new lines
void Draw_ExpandedString(float x, float y, conchar_t *str)
{
@ -252,6 +255,7 @@ void Draw_FunStringWidth(float x, float y, const void *str, int width, int right
}
Font_EndString(font_default);
}
#ifdef QUAKEHUD
static qboolean largegame = false;
@ -1347,9 +1351,7 @@ void Sbar_Hexen2DrawNum (float x, float y, int num, int digits)
//=============================================================================
int fragsort[MAX_CLIENTS];
int playerteam[MAX_CLIENTS];
int scoreboardlines;
typedef struct {
char team[16+1];
int frags;
@ -1384,6 +1386,22 @@ void Sbar_PQ_Team_Reset(void)
memset(nqteam, 0, sizeof(nqteam));
}
#endif
unsigned int Sbar_ColorForMap (unsigned int m)
{
if (m >= 16)
return m;
m = (m < 0) ? 0 : ((m > 13) ? 13 : m);
m *= 16;
return m < 128 ? m + 8 : m + 8;
}
int scoreboardlines;
int fragsort[MAX_CLIENTS];
/*
===============
Sbar_SortFrags
@ -1413,15 +1431,17 @@ void Sbar_SortFrags (qboolean includespec, qboolean doteamsort)
for (i=0 ; i<scoreboardlines ; i++)
for (j = i + 1; j < scoreboardlines; j++)
{
int w1, w2;
#ifdef QUAKEHUD
int t1 = playerteam[fragsort[i]];
int t2 = playerteam[fragsort[j]];
int w1, w2;
//teams are already sorted by frags
w1 = t1<0?-999:-teamsort[t1];
w2 = t2<0?-999:-teamsort[t2];
//okay, they're on the same team then? go ahead and sort by personal frags
if (!doteamsort || w1 == w2)
#endif
{
w1 = cl.players[fragsort[i]].frags;
w2 = cl.players[fragsort[j]].frags;
@ -1435,6 +1455,8 @@ void Sbar_SortFrags (qboolean includespec, qboolean doteamsort)
}
}
#ifdef QUAKEHUD
void Sbar_SortTeams (playerview_t *pv)
{
int i, j, k;
@ -1528,18 +1550,6 @@ void Sbar_SortTeams (playerview_t *pv)
}
}
unsigned int Sbar_ColorForMap (unsigned int m)
{
if (m >= 16)
return m;
m = (m < 0) ? 0 : ((m > 13) ? 13 : m);
m *= 16;
return m < 128 ? m + 8 : m + 8;
}
/*
===============
Sbar_SoloScoreboard
@ -2107,7 +2117,7 @@ void Sbar_DrawNormal (playerview_t *pv)
qboolean Sbar_ShouldDraw (void)
{
#ifdef TEXTEDITOR
#ifdef TEXTEDITOR
extern qboolean editoractive;
#endif
qboolean headsup;
@ -3794,4 +3804,4 @@ void Sbar_FinaleOverlay (void)
return;
#endif
}
#endif

View File

@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// the status bar is only redrawn if something has changed, but if anything
// does, the entire thing will be redrawn for the next vid.numpages frames.
#ifdef QUAKEHUD
#define SBAR_HEIGHT 24
extern int sb_lines; // scan lines to draw
@ -28,9 +29,6 @@ extern int sb_lines; // scan lines to draw
void Sbar_Init (void);
struct player_info_s;
qboolean Sbar_UpdateTeamStatus(struct player_info_s *player, char *status);
#ifdef GLQUAKE
void Sbar_ReInit (void);
#endif
void Sbar_Changed (void);
// call whenever any of the client stats represented on the sbar changes
@ -44,7 +42,6 @@ void Sbar_IntermissionOverlay (void);
// called each frame after the level has been completed
void Sbar_FinaleOverlay (void);
void Sbar_SortFrags (qboolean includespec, qboolean teamsort);
void Sbar_PQ_Team_New(unsigned int team, unsigned int shirt);
void Sbar_PQ_Team_Frags(unsigned int team, int frags);
@ -52,7 +49,24 @@ void Sbar_PQ_Team_Reset(void);
void Sbar_Start (void);
void Sbar_Flush (void);
int Sbar_TranslateHudClick(void);
#else
#define sb_lines 0
#define Sbar_Init()
#define Sbar_Start()
#define Sbar_Changed()
#define Sbar_Draw(pv)
#define Sbar_Flush()
#define Sbar_ShouldDraw() false
#define Sbar_DrawScoreboard()
#define Sbar_FinaleOverlay()
#define Sbar_IntermissionOverlay()
#define Sbar_TranslateHudClick() 0
#endif
unsigned int Sbar_ColorForMap (unsigned int m);
void Sbar_SortFrags (qboolean includespec, qboolean teamsort);
extern int scoreboardlines;
extern int fragsort[];

View File

@ -429,7 +429,7 @@ static qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdec
buffer->pos = 0;
if (p_ov_open_callbacks(buffer, &buffer->vf, NULL, 0, callbacks))
{
Con_Printf("Input does not appear to be an Ogg bitstream.\n");
Con_Printf("Input does not appear to be an Ogg Vorbis bitstream.\n");
return false;
}

View File

@ -482,9 +482,6 @@ char *Sys_GetNameForAddress(dllhandle_t *module, void *address)
}
#endif
#define MINIMUM_WIN_MEMORY MINIMUM_MEMORY
#define MAXIMUM_WIN_MEMORY 0x8000000
int starttime;
qboolean ActiveApp, Minimized;
qboolean WinNT; //NT has a) proper unicode support that does not unconditionally result in errors. b) a few different registry paths.
@ -3946,6 +3943,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
parms.binarydir = bindir;
COM_InitArgv (parms.argc, parms.argv);
#ifdef PLUGINS
c = COM_CheckParm("--plugwrapper");
if (c)
{
@ -3958,6 +3956,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
return thefunc();
return 0;
}
#endif
c = COM_CheckParm("-qcdebug");
if (c)

View File

@ -161,7 +161,7 @@ float V_CalcBob (playerview_t *pv, qboolean queryold)
if (cl.spectator)
return 0;
if (cl_bobcycle.value <= 0 || cl.intermission)
if (cl_bobcycle.value <= 0 || cl.intermissionmode != IM_NONE)
return 0;
if (!pv->onground || cl.paused)
@ -654,6 +654,7 @@ V_CalcPowerupCshift
*/
void V_CalcPowerupCshift (void)
{
#ifdef QUAKESTATS
int im = 0;
int s;
@ -695,6 +696,7 @@ void V_CalcPowerupCshift (void)
if (cl.cshifts[CSHIFT_POWERUP].percent<0)
cl.cshifts[CSHIFT_POWERUP].percent=0;
#endif
}
@ -1113,8 +1115,10 @@ void V_ApplyAFov(playerview_t *pv)
float afov = r_refdef.afov;
if (!afov) //make sure its sensible.
afov = scr_fov.value;
#ifdef QUAKESTATS
if (pv && pv->stats[STAT_VIEWZOOM])
afov *= pv->stats[STAT_VIEWZOOM]/255.0f;
#endif
afov = min(afov, 170);
ws = 1;
@ -1158,8 +1162,13 @@ void V_ApplyRefdef (void)
r_refdef.playerview->gamerect = r_refdef.grect;
}
#ifndef QUAKEHUD
r_refdef.vrect = r_refdef.grect;
#else
// intermission is always full screen
if (cl.intermission || !r_refdef.drawsbar)
if (cl.intermissionmode != IM_NONE || !r_refdef.drawsbar)
size = 120;
else
size = scr_viewsize.value;
@ -1184,7 +1193,7 @@ void V_ApplyRefdef (void)
else
size = scr_viewsize.value;
if (cl.intermission || !r_refdef.drawsbar)
if (cl.intermissionmode != IM_NONE || !r_refdef.drawsbar)
{
full = true;
size = 100.0;
@ -1230,6 +1239,7 @@ void V_ApplyRefdef (void)
}
r_refdef.vrect.x += r_refdef.grect.x;
r_refdef.vrect.y += r_refdef.grect.y;
#endif
if (r_refdef.dirty & RDFD_FOV)
V_ApplyAFov(r_refdef.playerview);
@ -1283,7 +1293,7 @@ void V_ClearRefdef(playerview_t *pv)
r_refdef.fov_x = 0;
r_refdef.fov_y = 0;
r_refdef.drawsbar = !cl.intermission;
r_refdef.drawsbar = cl.intermissionmode == IM_NONE;
r_refdef.flags = 0;
r_refdef.areabitsknown = false;
@ -1340,6 +1350,7 @@ void V_CalcRefdef (playerview_t *pv)
V_AddIdle (pv);
viewheight = pv->viewheight;
#ifdef QUAKESTATS
if (viewheight == DEFAULT_VIEWHEIGHT)
{
if (view_message && view_message->flags & PF_GIB)
@ -1348,18 +1359,18 @@ void V_CalcRefdef (playerview_t *pv)
viewheight = 16; // corpse view height
}
viewheight += pv->crouch;
if (pv->stats[STAT_HEALTH] < 0 && (!cl.spectator || pv->cam_state == CAM_EYECAM) && v_deathtilt.value) // PF_GIB will also set PF_DEAD
{
if (!cl.spectator || cl_chasecam.ival)
r_refdef.viewangles[ROLL] = 80*v_deathtilt.value; // dead view angle
}
else
#endif
{
// v_viewheight only affects the view if the player is alive
viewheight += bob;
}
viewheight += pv->crouch;
VectorMA(r_refdef.vieworg, -viewheight, pv->gravitydir, r_refdef.vieworg);
@ -1560,6 +1571,7 @@ static void SCR_DrawAutoID(vec3_t org, player_info_t *pl, qboolean isteam)
{255, 0, 0, 1}
};
#ifdef QUAKESTATS
extern cvar_t tp_name_sg,tp_name_ssg,tp_name_ng,tp_name_sng,tp_name_gl,tp_name_rl,tp_name_lg;
static cvar_t *wbitnames[] =
{
@ -1571,6 +1583,7 @@ static void SCR_DrawAutoID(vec3_t org, player_info_t *pl, qboolean isteam)
&tp_name_rl,
&tp_name_lg
};
#endif
VectorCopy(org, tagcenter);
tagcenter[2] += 32;
@ -1596,6 +1609,7 @@ static void SCR_DrawAutoID(vec3_t org, player_info_t *pl, qboolean isteam)
x = center[0]*r_refdef.vrect.width+r_refdef.vrect.x;
y = (1-center[1])*r_refdef.vrect.height+r_refdef.vrect.y;
#ifdef QUAKESTATS
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
{
health = pl->statsf[STAT_HEALTH];
@ -1605,6 +1619,7 @@ static void SCR_DrawAutoID(vec3_t org, player_info_t *pl, qboolean isteam)
haveinfo = true;
}
else
#endif
{
health = pl->tinfo.health;
armour = pl->tinfo.armour;
@ -1652,6 +1667,7 @@ static void SCR_DrawAutoID(vec3_t org, player_info_t *pl, qboolean isteam)
if (health <= 0) //armour+weapons are not relevant when dead
return;
#ifdef QUAKESTATS
if (scr_autoid_armour.ival)
{
//display armour bar above that
@ -1704,6 +1720,7 @@ static void SCR_DrawAutoID(vec3_t org, player_info_t *pl, qboolean isteam)
Draw_ExpandedString(x + barwidth*0.5 + 4, y, buffer);
}
}
#endif
}
#include "pr_common.h"
@ -1832,7 +1849,7 @@ void R_DrawNameTags(void)
if ((!cl.spectator && !cls.demoplayback || !scr_autoid.ival) && (!cl.teamplay || !scr_autoid_team.ival))
return;
if (cls.state != ca_active || !cl.validsequence || cl.intermission)
if (cls.state != ca_active || !cl.validsequence || cl.intermissionmode != IM_NONE)
return;
if (r_refdef.playerview->cam_state != CAM_FREECAM && r_refdef.playerview->cam_spec_track >= 0)
@ -1910,7 +1927,7 @@ void V_RenderPlayerViews(playerview_t *pv)
oldstris = cl_numstris;
CL_LinkViewModel ();
if (cl.intermission)
if (cl.intermissionmode != IM_NONE)
{ // intermission / finale rendering
V_CalcIntermissionRefdef (pv);
}
@ -2059,7 +2076,7 @@ void V_RenderView (void)
if (cls.state != ca_active)
return;
if (cl.intermission)
if (cl.intermissionmode != IM_NONE)
maxviews = 1;
R_PushDlights ();

View File

@ -30,7 +30,6 @@
#include "quakedef.h"
#if 1 //def ZQUAKETEAMPLAY
//#include "version.h"
#include "sound.h"
@ -320,6 +319,7 @@ static char *Macro_Gamedir (void)
return macro_buf;
}
#ifdef QUAKESTATS
static char *Macro_Health (void)
{
sprintf(macro_buf, "%i", cl.playerview[SP].stats[STAT_HEALTH]);
@ -535,6 +535,7 @@ static char *Macro_Powerups (void)
return macro_buf;
}
#endif
static char *Macro_Location (void)
{
@ -621,6 +622,7 @@ static char *Macro_PointNameAtLocation (void)
return vars.pointname;
}
#ifdef QUAKESTATS
static char *Macro_Need (void)
{
int i, weapon;
@ -696,6 +698,7 @@ done:
return macro_buf;
}
#endif
static char *Skin_To_TFSkin (char *myskin)
{
@ -832,6 +835,7 @@ static char *Macro_Point_LED(void)
return macro_buf;
}
#ifdef QUAKESTATS
static char *Macro_MyStatus_LED(void)
{
int count;
@ -864,6 +868,7 @@ static char *Macro_MyStatus_LED(void)
return macro_buf;
}
#endif
static void CountNearbyPlayers(qboolean dead)
{
@ -1035,6 +1040,7 @@ char *Macro_LastDropTime (void)
return macro_buf;
}
#ifdef QUAKESTATS
char *Macro_CombinedHealth(void)
{
float h;
@ -1124,6 +1130,7 @@ char *Macro_LastTrigger_Match(void)
{
return "---";
}
#endif
/*
$matchname
@ -1153,6 +1160,7 @@ $triggermatch is the last chat message that exec'd a msg_trigger.
static void TP_InitMacros(void)
{
Cmd_AddMacro("latency", Macro_Latency, false);
#ifdef QUAKESTATS
Cmd_AddMacro("health", Macro_Health, true);
Cmd_AddMacro("armortype", Macro_ArmorType, true);
Cmd_AddMacro("armor", Macro_Armor, true);
@ -1167,6 +1175,8 @@ static void TP_InitMacros(void)
Cmd_AddMacro("bestweapon", Macro_BestWeapon, true);
Cmd_AddMacro("bestammo", Macro_BestAmmo, true);
Cmd_AddMacro("powerups", Macro_Powerups, true);
Cmd_AddMacro("droppedweapon", Macro_DroppedWeapon, true);
#endif
Cmd_AddMacro("location", Macro_Location, false);
Cmd_AddMacro("deathloc", Macro_LastDeath, true);
Cmd_AddMacro("tookatloc", Macro_TookAtLoc, true);
@ -1174,36 +1184,38 @@ static void TP_InitMacros(void)
Cmd_AddMacro("took", Macro_Took, true);
Cmd_AddMacro("tf_skin", Macro_TF_Skin, true);
Cmd_AddMacro("droppedweapon", Macro_DroppedWeapon, true);
//ones added by Spike, for fuhquake compatability
Cmd_AddMacro("connectiontype", Macro_ConnectionType, false);
Cmd_AddMacro("demoplayback", Macro_demoplayback, false);
Cmd_AddMacro("need", Macro_Need, true);
Cmd_AddMacro("point", Macro_PointName, true);
Cmd_AddMacro("pointatloc", Macro_PointNameAtLocation, true);
Cmd_AddMacro("pointloc", Macro_PointLocation, true);
Cmd_AddMacro("matchname", Macro_Match_Name, false);
Cmd_AddMacro("matchtype", Macro_Match_Type, false);
Cmd_AddMacro("ledpoint", Macro_Point_LED, true);
#ifdef QUAKESTATS
Cmd_AddMacro("need", Macro_Need, true);
Cmd_AddMacro("ledstatus", Macro_MyStatus_LED, true);
#endif
Cmd_AddMacro("ledpoint", Macro_Point_LED, true);
Cmd_AddMacro("droploc", Macro_LastDrop, true);
Cmd_AddMacro("droptime", Macro_LastDropTime, true);
Cmd_AddMacro("matchstatus", Macro_Match_Status, false);
Cmd_AddMacro("mp3info", Macro_MP3Info, false);
Cmd_AddMacro("triggermatch", Macro_LastTrigger_Match, false);
// Cmd_AddMacro("matchstatus", Macro_Match_Status, false);
// Cmd_AddMacro("mp3info", Macro_MP3Info, false);
// Cmd_AddMacro("triggermatch", Macro_LastTrigger_Match, false);
//new, fte only (at least when first implemented)
#ifdef QUAKESTATS
Cmd_AddMacro("chealth", Macro_CombinedHealth, true);
#endif
//added for ezquake compatability
Cmd_AddMacro("lastip", Macro_LastIP, false);
// Cmd_AddMacro("lastip", Macro_LastIP, false);
Cmd_AddMacro("ping", Macro_Latency, false);
#ifdef QUAKESTATS
Cmd_AddMacro("colored_armor", Macro_Coloured_Armour, true); //*shudder*
Cmd_AddMacro("colored_powerups", Macro_Coloured_Powerups, true);
Cmd_AddMacro("colored_short_powerups", Macro_Coloured_Short_Powerups, true);
#endif
Cmd_AddMacro("gamedir", Macro_Gamedir, false);
Cmd_AddMacro("lastloc", Macro_Last_Location, true);
Cmd_AddMacro("lastpowerup", Macro_LastSeenPowerup, true);
@ -1234,6 +1246,7 @@ static char *TP_ParseMacroString (char *s)
{
static char mbuf[MAX_MACRO_VALUE];
switch (s[2]) {
#ifdef QUAKESTATS
case 'a':
macro_string = Macro_ArmorType();
if (!macro_string[0])
@ -1262,7 +1275,7 @@ static char *TP_ParseMacroString (char *s)
mbuf[0] = 0;
macro_string = mbuf;
break;
#endif
// todo: %[w], %[b]
default:
@ -1282,13 +1295,17 @@ static char *TP_ParseMacroString (char *s)
{
switch (s[1])
{
#ifdef QUAKESTATS
case 'a': macro_string = Macro_Armor(); break;
case 'A': macro_string = Macro_ArmorType(); break;
case 'b': macro_string = Macro_BestWeaponAndAmmo(); break;
case 'c': macro_string = Macro_Cells(); break;
#endif
case 'd': macro_string = Macro_LastDeath(); break;
// case 'D':
#ifdef QUAKESTATS
case 'h': macro_string = Macro_Health(); break;
#endif
case 'i': macro_string = Macro_TookAtLoc(); break;
case 'j': macro_string = Macro_LastPointAtLoc(); break;
case 'k': macro_string = Macro_LastTookOrPointed(); break;
@ -1302,14 +1319,18 @@ static char *TP_ParseMacroString (char *s)
case 'E': macro_string = Macro_Count_Last_NearbyEnemyPlayers(); break;
case 'P':
#ifdef QUAKESTATS
case 'p': macro_string = Macro_Powerups(); break;
#endif
case 'q': macro_string = Macro_LastSeenPowerup(); break;
// case 'r': macro_string = Macro_LastReportedLoc(); break;
case 's': macro_string = Macro_EnemyStatus_LED(); break;
case 'S': macro_string = Macro_TF_Skin(); break;
case 't': macro_string = Macro_PointNameAtLocation(); break;
#ifdef QUAKESTATS
case 'u': macro_string = Macro_Need(); break;
case 'w': macro_string = Macro_WeaponAndAmmo(); break;
#endif
case 'x': macro_string = Macro_PointName(); break;
case 'X': macro_string = Macro_Took(); break;
case 'y': macro_string = Macro_PointLocation(); break;
@ -2898,6 +2919,7 @@ void TP_ParsePlayerInfo(player_state_t *oldstate, player_state_t *state, player_
void TP_CheckPickupSound (char *s, vec3_t org, int seat)
{
#ifndef QUAKETC
int entnum;
item_t *item;
//if we're spectating, we don't want to do any actual triggers, so pretend it was someone else.
@ -3004,6 +3026,7 @@ more:
return;
TP_ItemTaken (item->cvar->string, item->itemflag, org, entnum, item, seat);
}
#endif
}
qboolean R_CullSphere (vec3_t org, float radius);
@ -3389,7 +3412,7 @@ void TP_UpdateAutoStatus(void)
void TP_StatChanged (int stat, int value)
{
int i;
#ifdef QUAKESTATS
if (stat == STAT_HEALTH)
{
if (value > 0)
@ -3453,7 +3476,7 @@ void TP_StatChanged (int stat, int value)
TP_ExecTrigger ("f_weaponchange", false);
vars.activeweapon = cl.playerview[SP].stats[STAT_ACTIVEWEAPON];
}
#endif
vars.stat_framecounts[stat] = cls.framecount;
TP_UpdateAutoStatus();
@ -3827,6 +3850,6 @@ void CL_SayTeam_f (void)
vars.autoteamstatus_time = realtime + 3;
CL_Say (true, NULL);
}
#endif

View File

@ -154,10 +154,35 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
//set any additional defines or libs in win32
#define SVRANKING
#define LOADERTHREAD
#ifdef MINIMAL
#ifdef NOLEGACY
//these are only the features that really make sense in a more modern engine
#define QUAKETC //skip some legacy stuff
#define SPRMODELS //quake1 sprite models
#define INTERQUAKEMODELS
#define RTLIGHTS //realtime lighting
#define Q2BSPS //quake 2 bsp support
#define Q3BSPS //quake 3 bsp support
// #define TERRAIN //heightmap support
#define ZLIB //zip/pk3 support
#define WEBCLIENT //http/ftp clients.
#define IMAGEFMT_DDS //a sort of image file format.
#define PSET_SCRIPT
// #define PLUGINS //qvm/dll plugins.
// #define SUPPORT_ICE //Interactive Connectivity Establishment protocol, for peer-to-peer connections
#define CSQC_DAT //support for csqc
// #define VOICECHAT
#undef AVAIL_JPEGLIB
#undef AVAIL_XZDEC
#if defined(_WIN32) && !defined(MULTITHREAD) //always thread on win32 non-minimal builds
#define MULTITHREAD
#endif
#elif defined(MINIMAL)
#define QUAKESTATS
#define QUAKEHUD
#define CL_MASTER //this is useful
#undef AVAIL_JPEGLIB //no jpeg support
@ -178,6 +203,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#endif
#else
#define NETPREPARSE
#define QUAKESTATS
#define QUAKEHUD
#define SVRANKING
#define USE_SQLITE
#ifdef SERVERONLY
#define USE_MYSQL //allow mysql in dedicated servers.
@ -647,8 +676,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define UNUSED(x) (x = x) // for pesky compiler / lint warnings
#define MINIMUM_MEMORY 0x550000
// up / down
#define PITCH 0
@ -658,8 +685,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// fall over
#define ROLL 2
#define SOUND_CHANNELS 8
#define MAX_QPATH 128 // max length of a quake game pathname
#define MAX_OSPATH 1024 // max length of a filesystem pathname (260 on windows, but needs to be longer for utf8)
@ -686,7 +711,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//#define MAX_EDICTS ((1<<22)-1) // expandable up to 22 bits
#define MAX_EDICTS ((1<<18)-1) // expandable up to 22 bits
#endif
#define MAX_LIGHTSTYLES 255
#define MAX_LIGHTSTYLES 255 //255 = 'invalid', and thus only 0-254 are the valid indexes.
#define MAX_STANDARDLIGHTSTYLES 64
#define MAX_PRECACHE_MODELS 2048 // these are sent over the net as bytes/shorts
#define MAX_PRECACHE_SOUNDS 1024 // so they cannot be blindly increased
@ -707,6 +732,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
#define MAX_QW_STATS 32
enum {
#ifdef QUAKESTATS
STAT_HEALTH = 0,
//STAT_FRAGS = 1,
STAT_WEAPONMODELI = 2,
@ -825,10 +851,11 @@ STAT_MOVEVARS_MAXAIRSPEED = 252, // DP
STAT_MOVEVARS_STEPHEIGHT = 253, // DP
STAT_MOVEVARS_AIRACCEL_QW = 254, // DP
STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION = 255, // DP
#endif
MAX_CL_STATS = 256
};
#ifdef QUAKEHUD
//
// item flags
//
@ -869,6 +896,7 @@ STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION = 255, // DP
#define IT_SIGIL2 (1<<29)
#define IT_SIGIL3 (1<<30)
#define IT_SIGIL4 (1<<31)
#endif
//
// print flags

View File

@ -3337,6 +3337,7 @@ void Cmd_Init (void)
Cvar_Register(&dpcompat_set, "Darkplaces compatibility");
Cvar_Register (&cl_warncmd, "Warnings");
Cvar_Register (&cfg_save_all, "client operation options");
Cvar_Register (&cfg_save_auto, "client operation options");
#ifndef SERVERONLY
rcon_level.ival = atof(rcon_level.enginevalue); //client is restricted to not be allowed to change restrictions.

View File

@ -2451,7 +2451,7 @@ void Mod_GenerateMeshVBO(galiasinfo_t *galias)
vbobctx_t vboctx;
//don't fail on dedicated servers
if (!BE_VBO_Begin)
if (!BE_VBO_Begin || !galias->numverts)
return;
group = galias->ofsanimations;

View File

@ -39,6 +39,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../../plugins/plugin.h"
#include "../../plugins/engine.h"
#ifdef NOLEGACY
#undef USERBE
#endif
#ifdef USERBE
#include "pr_common.h"

View File

@ -5408,6 +5408,7 @@ char *COM_Effectinfo_ForNumber(unsigned int efnum)
/*remaps map checksums from known non-cheat GPL maps to authentic id1 maps*/
unsigned int COM_RemapMapChecksum(unsigned int checksum)
{
#ifndef NOLEGACY
static const struct {
char *name;
unsigned int gpl2;
@ -5466,6 +5467,7 @@ unsigned int COM_RemapMapChecksum(unsigned int checksum)
if (checksum == sums[i].gpl2)
return sums[i].id12;
}
#endif
return checksum;
}

View File

@ -6046,7 +6046,15 @@ qbyte *CM_ClusterPVS (model_t *mod, int cluster, qbyte *buffer, unsigned int buf
if (buffersize < (mod->numclusters+7)>>3)
Sys_Error("CM_ClusterPVS with too small a buffer\n");
if (mod->fromgame != fg_quake2)
if (mod->fromgame == fg_quake2)
{
if (cluster == -1)
memset (buffer, 0, (mod->numclusters+7)>>3);
else
CM_DecompressVis (mod, ((qbyte*)prv->q2vis) + prv->q2vis->bitofs[cluster][DVIS_PVS], buffer);
return buffer;
}
else
{
if (cluster != -1 && prv->q3pvs->numclusters)
{
@ -6058,12 +6066,6 @@ qbyte *CM_ClusterPVS (model_t *mod, int cluster, qbyte *buffer, unsigned int buf
return buffer;
}
}
if (cluster == -1)
memset (buffer, 0, (mod->numclusters+7)>>3);
else
CM_DecompressVis (mod, ((qbyte*)prv->q2vis) + prv->q2vis->bitofs[cluster][DVIS_PVS], buffer);
return buffer;
}
qbyte *CM_ClusterPHS (model_t *mod, int cluster)
@ -6231,7 +6233,7 @@ that area in the same flood as the area parameter
This is used by the client refreshes to cull visibility
=================
*/
int CM_WriteAreaBits (model_t *mod, qbyte *buffer, int area)
int CM_WriteAreaBits (model_t *mod, qbyte *buffer, int area, qboolean merge)
{
cminfo_t *prv = (cminfo_t*)mod->meshinfo;
int i;
@ -6242,11 +6244,13 @@ int CM_WriteAreaBits (model_t *mod, qbyte *buffer, int area)
if (map_noareas.value)
{ // for debugging, send everything
memset (buffer, 255, bytes);
if (!merge)
memset (buffer, 255, bytes);
}
else
{
memset (buffer, 0, bytes);
if (!merge)
memset (buffer, 0, bytes);
floodnum = prv->q2areas[area].floodnum;
for (i=0 ; i<prv->numareas ; i++)

View File

@ -109,7 +109,9 @@ unsigned int Net_PextMask(int maskset, qboolean fornq)
mask |= PEXT_VIEW2;
#endif
#ifdef PEXT_ACCURATETIMINGS
mask |= PEXT_ACCURATETIMINGS;
#ifdef QUAKESTATS //needs stat_time
mask |= PEXT_ACCURATETIMINGS;
#endif
#endif
#ifdef PEXT_ZLIBDL
mask |= PEXT_ZLIBDL;

View File

@ -23,7 +23,7 @@ struct
qintptr_t (*initfunction)(qintptr_t *args);
} staticplugins[] =
{
#ifdef USERBE
#if defined(USERBE) && !defined(QUAKETC)
// {"Bullet", Plug_Bullet_Init},
{"ODE", Plug_ODE_Init},
#endif
@ -1631,7 +1631,12 @@ int Plug_ConnectionlessClientPacket(char *buffer, int size)
#ifndef SERVERONLY
void Plug_SBar(playerview_t *pv)
{
#ifdef QUAKEHUD
extern qboolean sb_showscores, sb_showteamscores;
#else
#define sb_showscores 0
#define sb_showteamscores 0
#endif
plugin_t *oc=currentplug;
int ret;

View File

@ -2530,9 +2530,13 @@ void QCBUILTIN PF_num_for_edict (pubprogfuncs_t *prinst, struct globalvars_s *pr
void QCBUILTIN PF_edict_for_num(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
world_t *w = prinst->parms->user;
edict_t *ent;
ent = (edict_t*)EDICT_NUM(prinst, G_FLOAT(OFS_PARM0));
unsigned int num = G_FLOAT(OFS_PARM0);
if (num >= w->num_edicts)
RETURN_EDICT(prinst, w->edicts);
ent = (edict_t*)EDICT_NUM(prinst, num);
RETURN_EDICT(prinst, ent);
}
@ -2613,6 +2617,33 @@ void QCBUILTIN PF_Spawn (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals
RETURN_EDICT(prinst, ed);
}
//EXTENSION: DP_QC_COPYENTITY
//void(entity from, entity to) copyentity = #400
//copies data from one entity to another
void QCBUILTIN PF_copyentity (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
world_t *w = prinst->parms->user;
wedict_t *in, *out;
in = G_WEDICT(prinst, OFS_PARM0);
if (prinst->callargc <= 1)
out = (wedict_t*)ED_Alloc(prinst);
else
out = G_WEDICT(prinst, OFS_PARM1);
if (!out || out->isfree)
PR_BIError(prinst, "PF_copyentity: destination is free");
if (out->readonly)
PR_BIError(prinst, "PF_copyentity: destination is read-only");
memcpy(out->v, in->v, w->edict_size);
World_LinkEdict(w, out, false);
RETURN_EDICT(prinst, out);
}
//Entities
////////////////////////////////////////////////////
//String functions

View File

@ -130,6 +130,7 @@ void QCBUILTIN PF_stov (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
void QCBUILTIN PF_strzone(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_strunzone(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_Spawn (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_copyentity (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_droptofloor (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_checkbottom (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_min (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
@ -273,6 +274,7 @@ void QCBUILTIN PF_setattachment(pubprogfuncs_t *prinst, struct globalvars_s *pr_
void QCBUILTIN PF_physics_enable(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_physics_addforce(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_physics_addtorque(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
#ifdef TERRAIN
void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_brush_get(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_brush_create(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
@ -281,6 +283,7 @@ void QCBUILTIN PF_brush_selected(pubprogfuncs_t *prinst, struct globalvars_s *pr
void QCBUILTIN PF_brush_getfacepoints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_brush_calcfacepoints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_brush_findinvolume(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
#endif
void QCBUILTIN PF_touchtriggers(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
@ -717,6 +720,7 @@ enum csqc_input_event
CSIE_JOYAXIS = 6, /*axis, value, devid*/
};
#ifdef TERRAIN
enum terrainedit_e
{
ter_reload, //
@ -754,6 +758,7 @@ enum terrainedit_e
ter_tex_mask //string tex
};
#endif
enum
{

View File

@ -90,7 +90,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define Z_EXT_VWEP (1<<7)
//#define Z_EXT_PF_SOLID (1<<8) //conflicts with many FTE extensions.
#ifdef QUAKESTATS
#define SUPPORTED_Z_EXTENSIONS (Z_EXT_PM_TYPE|Z_EXT_PM_TYPE_NEW|Z_EXT_VIEWHEIGHT|Z_EXT_SERVERTIME|Z_EXT_PITCHLIMITS|Z_EXT_JOIN_OBSERVE|Z_EXT_VWEP)
#else
#define SUPPORTED_Z_EXTENSIONS (Z_EXT_PM_TYPE|Z_EXT_PM_TYPE_NEW|Z_EXT_PITCHLIMITS|Z_EXT_JOIN_OBSERVE|Z_EXT_VWEP)
#endif
#define PROTOCOL_VERSION_FTE (('F'<<0) + ('T'<<8) + ('E'<<16) + ('X' << 24)) //fte extensions.
@ -825,8 +829,11 @@ enum clcq2_ops_e
#define FITZ_B_ALPHA (1<<2)
#define RMQFITZ_B_SCALE (1<<3)
#ifdef QUAKESTATS
#define DEFAULT_VIEWHEIGHT 22
#else
#define DEFAULT_VIEWHEIGHT 0 //so csqc can position the camera without any worries.
#endif
// svc_print messages have an id, so messages can be filtered

View File

@ -788,12 +788,13 @@ static void SelectPassTexture(unsigned int tu, shaderpass_t *pass)
else
{
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_COLORVERTEX, TRUE);
// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1); //default state anyway.
last = D3DTA_DIFFUSE;
}
}
else
last = D3DTA_CURRENT;
switch (pass->blendmode)
{
case PBM_DOTPRODUCT:
@ -801,7 +802,7 @@ static void SelectPassTexture(unsigned int tu, shaderpass_t *pass)
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_TEXTURE);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);
// IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, last);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, last);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
break;
@ -818,9 +819,9 @@ static void SelectPassTexture(unsigned int tu, shaderpass_t *pass)
}
else
{
// IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, last);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, last);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
}
break;
case PBM_ADD:
@ -837,12 +838,12 @@ static void SelectPassTexture(unsigned int tu, shaderpass_t *pass)
case PBM_DECAL:
if (!tu)
goto forcemod;
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, last);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_TEXTURE);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, D3DTA_TEXTURE);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, last);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, last);
// IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
break;
case PBM_OVERBRIGHT:
@ -1130,7 +1131,7 @@ static void alphagenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *srcb, v
if (!Matrix3_Compare(shaderstate.curentity->axis, (void *)axisDefault))
{
Matrix3_Multiply_Vec3(shaderstate.curentity->axis, v2, v2);
Matrix3_Multiply_Vec3(shaderstate.curentity->axis, v1, v2);
}
else
{
@ -1140,7 +1141,7 @@ static void alphagenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *srcb, v
for (i = 0; i < cnt; i++)
{
VectorSubtract(v2, mesh->xyz_array[i], v1);
f = DotProduct(v1, mesh->normals_array[i] ) * Q_rsqrt(DotProduct(v1,v1));
f = DotProduct(v1, mesh->normals_array[i]) * Q_rsqrt(DotProduct(v1,v1));
f = f * f * f * f * f;
dst[i][3] = bound (0.0f, (int)(f*255), 255);
}
@ -1184,13 +1185,12 @@ static unsigned int BE_GenerateColourMods(unsigned int vertcount, const shaderpa
else
{
allocvertexbuffer(shaderstate.dyncol_buff, shaderstate.dyncol_size, &shaderstate.dyncol_offs, (void**)&map, vertcount*sizeof(D3DCOLOR));
for (vertcount = 0, mno = 0; mno < shaderstate.nummeshes; mno++)
for (mno = 0; mno < shaderstate.nummeshes; mno++)
{
m = shaderstate.meshlist[mno];
colourgenbyte(pass, m->numvertexes, m->colors4b_array, m->colors4f_array[0], (byte_vec4_t*)map, m);
alphagenbyte(pass, m->numvertexes, m->colors4b_array, m->colors4f_array[0], (byte_vec4_t*)map, m);
map += m->numvertexes*4;
vertcount += m->numvertexes;
}
d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dyncol_buff));
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, shaderstate.dyncol_buff, shaderstate.dyncol_offs - vertcount*sizeof(D3DCOLOR), sizeof(D3DCOLOR)));
@ -1209,9 +1209,19 @@ static void tcgen_environment(float *st, unsigned int numverts, float *xyz, floa
vec3_t rorg;
if (!normal)
{
for (i = 0 ; i < numverts ; i++, st += 2 )
{
st[0] = xyz[0];
st[1] = xyz[1];
}
return;
}
RotateLightVector(shaderstate.curentity->axis, shaderstate.curentity->origin, r_origin, rorg);
for (i = 0 ; i < numverts ; i++, xyz += 3, normal += 3, st += 2 )
for (i = 0 ; i < numverts ; i++, xyz += sizeof(vecV_t)/sizeof(vec_t), normal += 3, st += 2 )
{
VectorSubtract (rorg, xyz, viewer);
VectorNormalizeFast (viewer);
@ -1237,7 +1247,7 @@ static float *tcgen(const shaderpass_t *pass, int cnt, float *dst, const mesh_t
case TC_GEN_BASE:
return (float*)mesh->st_array;
case TC_GEN_LIGHTMAP:
return (float*)mesh->lmst_array;
return (float*)mesh->lmst_array[0];
case TC_GEN_NORMAL:
return (float*)mesh->normals_array;
case TC_GEN_SVECTOR:
@ -1356,24 +1366,32 @@ static void GenerateTCMods(const shaderpass_t *pass, float *dest)
// unsigned int fvertex = 0; //unused variable
int i;
float *src;
float *out;
for (mno = 0; mno < shaderstate.nummeshes; mno++)
{
mesh = shaderstate.meshlist[mno];
src = tcgen(pass, mesh->numvertexes, dest + mesh->vbofirstvert*2, mesh);
#if 0
out = dest + mesh->vbofirstvert*2;
#else
out = dest;
dest += mesh->numvertexes*2;
#endif
src = tcgen(pass, mesh->numvertexes, out, mesh);
//tcgen might return unmodified info
if (pass->numtcmods)
{
tcmod(&pass->tcmods[0], mesh->numvertexes, src, dest + mesh->vbofirstvert*2, mesh);
for (i = 1; i < pass->numtcmods; i++)
for (i = 0; i < pass->numtcmods; i++)
{
tcmod(&pass->tcmods[i], mesh->numvertexes, dest + mesh->vbofirstvert*2, dest + mesh->vbofirstvert*2, mesh);
tcmod(&pass->tcmods[i], mesh->numvertexes, src, out, mesh);
src = out;
}
}
else if (src != dest)
else if (src != out)
{
memcpy(dest + mesh->vbofirstvert*2, src, sizeof(vec2_t)*mesh->numvertexes);
memcpy(out, src, sizeof(vec2_t)*mesh->numvertexes);
}
// dest += mesh->numvertexes*2;
}
}
@ -1959,7 +1977,7 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertbase, unsigned in
vertcount += m->numvertexes;
}
d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[0]));
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.dynst_buff[0], shaderstate.dynst_offs[0] - vertcount*sizeof(byte_vec4_t), sizeof(byte_vec4_t)));
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, shaderstate.dynst_buff[0], shaderstate.dynst_offs[0] - vertcount*sizeof(byte_vec4_t), sizeof(byte_vec4_t)));
}
}
@ -2123,7 +2141,8 @@ static void BE_DrawMeshChain_Internal(void)
int i;
unsigned int mno;
unsigned int passno = 0;
shaderpass_t *pass = shaderstate.curshader->passes;
shaderpass_t *pass;
shader_t *useshader = shaderstate.curshader;
extern cvar_t r_polygonoffset_submodel_factor;
float pushdepth;
// float pushfactor;
@ -2143,9 +2162,33 @@ static void BE_DrawMeshChain_Internal(void)
// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&shaderstate.depthfactor);
// }
switch (shaderstate.mode)
{
case BEM_LIGHT:
// useshader = shaderstate.curshader->bemoverrides[shaderstate.lightmode];
// if (!useshader)
useshader = shaderstate.shader_rtlight;
if (!useshader->prog)
return;
break;
case BEM_DEPTHDARK:
// useshader = shaderstate.shader_depthblack;
return;
break;
case BEM_STENCIL:
return;
case BEM_DEPTHONLY:
// useshader = shaderstate.shader_depthonly;
return;
break;
default:
useshader = shaderstate.curshader;
break; //no need to switch the shader
}
//if anything is dynamic ALL must be dynamic
//might want to flag this for multi-mesh batches on pre-t&l cards too, so that there's no gaps.
if (shaderstate.curshader->numdeforms)
if ((useshader->flags & SHADER_NEEDSARRAYS) && shaderstate.nummeshes > 0)
shaderstate.batchvbo = NULL;
if (shaderstate.batchvbo)
@ -2202,7 +2245,7 @@ static void BE_DrawMeshChain_Internal(void)
/*index buffers are also common (note that we may still need to stream these when dealing with bsp geometry, to cope with gaps. this is faster than using multiple draw calls.)*/
if (shaderstate.batchvbo)
{
if (shaderstate.nummeshes != 1)
if (shaderstate.nummeshes != 1 || (useshader->flags & SHADER_NEEDSARRAYS))
{ //in this case, the vertex data is static, but the index data can have gaps.
//we're streaming index buffer data only so that we can avoid repeated draw calls. if this stuff was properly built in the first place we wouldn't need to do this. :s
idxcount = 0;
@ -2256,6 +2299,7 @@ static void BE_DrawMeshChain_Internal(void)
switch (shaderstate.mode)
{
#if 0
case BEM_LIGHT:
if (shaderstate.shader_rtlight->prog)
BE_RenderMeshProgram(shaderstate.shader_rtlight, vertbase, vertfirst, vertcount, idxfirst, idxcount);
@ -2312,16 +2356,17 @@ static void BE_DrawMeshChain_Internal(void)
BE_SubmitMeshChain(vertbase, vertfirst, vertcount, idxfirst, idxcount);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED|D3DCOLORWRITEENABLE_GREEN|D3DCOLORWRITEENABLE_BLUE|D3DCOLORWRITEENABLE_ALPHA);
break;
#endif
default:
case BEM_STANDARD:
if (shaderstate.curshader->prog)
if (useshader->prog)
{
BE_RenderMeshProgram(shaderstate.curshader, vertbase, vertfirst, vertcount, idxfirst, idxcount);
BE_RenderMeshProgram(useshader, vertbase, vertfirst, vertcount, idxfirst, idxcount);
}
else
{
/*now go through and flush each pass*/
for (passno = 0; passno < shaderstate.curshader->numpasses; passno += pass->numMergedPasses)
for (passno = 0, pass = useshader->passes; passno < shaderstate.curshader->numpasses; passno += pass->numMergedPasses)
{
if (!BE_DrawMeshChain_SetupPass(pass+passno, vertcount))
continue;
@ -3212,6 +3257,7 @@ static void R_DrawPortal(batch_t *batch, batch_t **blist)
glplane[3] = -plane.dist;
IDirect3DDevice9_SetClipPlane(pD3DDev9, 0, glplane);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_CLIPPLANEENABLE, D3DCLIPPLANE0);
Surf_SetupFrame();
R_RenderScene();
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_CLIPPLANEENABLE, 0);

View File

@ -663,7 +663,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../libs/speex,..\client,../libs/freetype2/include,../common,../server,../gl,../sw,../qclib,../libs,../libs/dxsdk7/include"
PreprocessorDefinitions="_DEBUG;GLQUAKE;WIN32;_WINDOWS;MULTITHREAD;BOTLIB_STATIC;USE_MSVCRT_DEBUG;GLSLONLY"
PreprocessorDefinitions="_DEBUG;GLQUAKE;WIN32;_WINDOWS;MULTITHREAD;BOTLIB_STATIC;USE_MSVCRT_DEBUG"
BasicRuntimeChecks="3"
SmallerTypeCheck="true"
RuntimeLibrary="1"

View File

@ -1279,14 +1279,14 @@ static void Matrix3_Transpose (mat3_t in, mat3_t out)
out[2][0] = in[0][2];
out[2][1] = in[1][2];
}
static void Matrix3_Multiply_Vec3 (mat3_t a, vec3_t b, vec3_t product)
static void Matrix3_Multiply_Vec3 (const mat3_t a, const vec3_t b, vec3_t product)
{
product[0] = a[0][0]*b[0] + a[0][1]*b[1] + a[0][2]*b[2];
product[1] = a[1][0]*b[0] + a[1][1]*b[1] + a[1][2]*b[2];
product[2] = a[2][0]*b[0] + a[2][1]*b[1] + a[2][2]*b[2];
}
static int Matrix3_Compare(mat3_t in, mat3_t out)
static int Matrix3_Compare(const mat3_t in, const mat3_t out)
{
return memcmp(in, out, sizeof(mat3_t));
}
@ -2396,13 +2396,11 @@ static void alphagen(const shaderpass_t *pass, int cnt, avec4_t *const src, avec
case ALPHA_GEN_SPECULAR:
{
mat3_t axis;
AngleVectors(shaderstate.curentity->angles, axis[0], axis[1], axis[2]);
VectorSubtract(r_origin, shaderstate.curentity->origin, v1);
if (!Matrix3_Compare(axis, axisDefault))
if (!Matrix3_Compare(shaderstate.curentity->axis, axisDefault))
{
Matrix3_Multiply_Vec3(axis, v1, v2);
Matrix3_Multiply_Vec3(shaderstate.curentity->axis, v1, v2);
}
else
{
@ -4392,6 +4390,32 @@ static qboolean BE_GenTempMeshVBO(vbo_t **vbo, mesh_t *m)
shaderstate.dummyvbo.normals.gl.vbo = 0;
}
if (m->snormals_array)
{
memcpy(buffer+len, m->snormals_array, sizeof(*m->snormals_array) * m->numvertexes);
shaderstate.dummyvbo.svector.gl.addr = (void*)len;
shaderstate.dummyvbo.svector.gl.vbo = shaderstate.streamvbo[shaderstate.streamid];
len += sizeof(*m->snormals_array) * m->numvertexes;
}
else
{
shaderstate.dummyvbo.svector.gl.addr = NULL;
shaderstate.dummyvbo.svector.gl.vbo = 0;
}
if (m->tnormals_array)
{
memcpy(buffer+len, m->tnormals_array, sizeof(*m->tnormals_array) * m->numvertexes);
shaderstate.dummyvbo.tvector.gl.addr = (void*)len;
shaderstate.dummyvbo.tvector.gl.vbo = shaderstate.streamvbo[shaderstate.streamid];
len += sizeof(*m->tnormals_array) * m->numvertexes;
}
else
{
shaderstate.dummyvbo.tvector.gl.addr = NULL;
shaderstate.dummyvbo.tvector.gl.vbo = 0;
}
if (m->bonenums)
{
memcpy(buffer+len, m->bonenums, sizeof(*m->bonenums) * m->numvertexes);

View File

@ -223,7 +223,7 @@ typedef struct {
void (*StainNode) (struct mnode_s *node, float *parms);
void (*MarkLights) (struct dlight_s *light, int bit, struct mnode_s *node);
int (*ClusterForPoint) (struct model_s *model, vec3_t point); //pvs index. may be negative (ie: no pvs).
int (*ClusterForPoint) (struct model_s *model, vec3_t point); //pvs index (leaf-1 for q1bsp). may be negative (ie: no pvs).
qbyte *(*ClusterPVS) (struct model_s *model, int cluster, qbyte *buffer, unsigned int buffersize);
} modelfuncs_t;
@ -1041,7 +1041,7 @@ int CM_ClusterSize (struct model_s *mod);
int CM_LeafContents (struct model_s *mod, int leafnum);
int CM_LeafCluster (struct model_s *mod, int leafnum);
int CM_LeafArea (struct model_s *mod, int leafnum);
int CM_WriteAreaBits (struct model_s *mod, qbyte *buffer, int area);
int CM_WriteAreaBits (struct model_s *mod, qbyte *buffer, int area, qboolean merge);
int CM_PointLeafnum (struct model_s *mod, vec3_t p);
qbyte *CM_ClusterPVS (struct model_s *mod, int cluster, qbyte *buffer, unsigned int buffersize);
qbyte *CM_ClusterPHS (struct model_s *mod, int cluster);

View File

@ -1156,6 +1156,7 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2],
{
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(r_refdef.m_projection);
qglMatrixMode(GL_MODELVIEW);
}
//portals to mask are relative to the old view still.
GLBE_SelectEntity(&r_worldentity);
@ -1197,7 +1198,7 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2],
if (r_refdef.m_projection[5]<0)
r_refdef.flipcull ^= SHADER_CULL_FLIP;
r_framecount++;
Surf_SetupFrame();
//FIXME: just call Surf_DrawWorld instead?
R_RenderScene();
// if (qglClipPlane)
@ -1227,6 +1228,7 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2],
/*put GL back the way it was*/
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(r_refdef.m_projection);
qglMatrixMode(GL_MODELVIEW);
}
GLBE_SelectEntity(&r_worldentity);

View File

@ -787,7 +787,6 @@ static void Shader_DeformVertexes ( shader_t *shader, shaderpass_t *pass, char *
{
deformv->type = DEFORMV_BULGE;
Shader_ParseVector (shader, ptr, deformv->args);
shader->flags |= SHADER_DEFORMV_BULGE;
}
else if ( !Q_stricmp (token, "move") )
{
@ -798,12 +797,10 @@ static void Shader_DeformVertexes ( shader_t *shader, shaderpass_t *pass, char *
else if ( !Q_stricmp (token, "autosprite") )
{
deformv->type = DEFORMV_AUTOSPRITE;
shader->flags |= SHADER_AUTOSPRITE;
}
else if ( !Q_stricmp (token, "autosprite2") )
{
deformv->type = DEFORMV_AUTOSPRITE2;
shader->flags |= SHADER_AUTOSPRITE;
}
else if ( !Q_stricmp (token, "projectionShadow") )
deformv->type = DEFORMV_PROJECTION_SHADOW;
@ -4308,6 +4305,19 @@ done:;
#endif
s->passes->numMergedPasses = s->numpasses;
}
else if (s->numdeforms)
s->flags |= SHADER_NEEDSARRAYS;
else
{
for (i = 0; i < s->numpasses; i++)
{
if (s->passes[i].numtcmods || (s->passes[i].tcgen != TC_GEN_BASE && s->passes[i].tcgen != TC_GEN_LIGHTMAP) || !(s->passes[i].flags & SHADER_PASS_NOCOLORARRAY))
{
s->flags |= SHADER_NEEDSARRAYS;
break;
}
}
}
}
/*
void Shader_UpdateRegistration (void)

View File

@ -485,6 +485,26 @@ qboolean GLInitialise (char *renderer)
else
hInstGL = NULL;
if (!hInstGL)
{ //gog has started shipping glquake using a 3dfxopengl->nglide->direct3d chain of wrappers.
//this bypasses issues with (not that) recent gl drivers giving up on limiting extension string lengths and paletted textures
//instead, we explicitly try to use the opengl32.dll from the windows system32 directory to try and avoid using the wrapper.
unsigned int emode;
wchar_t wbuffer[MAX_OSPATH];
GetSystemDirectoryW(wbuffer, countof(wbuffer));
narrowen(opengldllname, sizeof(opengldllname), wbuffer);
Q_strncatz(opengldllname, "\\opengl32.dll", sizeof(opengldllname));
Con_DPrintf ("Loading renderer dll \"%s\"", opengldllname);
emode = SetErrorMode(SEM_FAILCRITICALERRORS);
hInstGL = Sys_LoadLibrary(opengldllname, NULL);
SetErrorMode(emode);
if (hInstGL)
Con_DPrintf (" Success\n");
else
Con_DPrintf (" Failed\n");
}
if (!hInstGL)
{
unsigned int emode;

View File

@ -537,10 +537,10 @@ struct shader_s
SHADER_NOPICMIP = 1 << 2,
SHADER_CULL_FRONT = 1 << 3,
SHADER_CULL_BACK = 1 << 4,
SHADER_DEFORMV_BULGE = 1 << 5,
SHADER_AUTOSPRITE = 1 << 6,
// SHADER_DEFORMV_BULGE = 1 << 5,
// SHADER_AUTOSPRITE = 1 << 6,
SHADER_FLARE = 1 << 7,
//8
SHADER_NEEDSARRAYS = 1 << 8, //shader uses deforms or rgbmod tcmods or something that will not work well with sparse vbos
SHADER_ENTITY_MERGABLE = 1 << 9,
SHADER_VIDEOMAP = 1 << 10,
SHADER_DEPTHWRITE = 1 << 11, //some pass already wrote depth. not used by the renderer.

View File

@ -618,6 +618,34 @@ r_part tr_lavaspike
}
r_trail "progs/lspike.mdl" tr_lavaspike
/////////////////////////////////////////
//rogue plasma gun
r_part tr_plasma
{
type texturedspark
texture "particles/fteparticlefont.tga"
tcoords 1 97 95 191 256
scale 15
step 4
alpha 0.3
die 0.25
rgb 128 128 255
veladd -32
spawnmode spiral
spawnvel 16
randomvel 32
friction 0
scalefactor 1
blend add
lighttime 0.2
lightshadows 0
lightradius 150
lightrgb 1 1 2
lightrgbfade 5 1 0.5
lightcorona 2 0.5
}
r_trail "progs/plasma.mdl" tr_plasma
/////////////////////////////////////////
//scrag missiles.

View File

@ -41,6 +41,12 @@
#define QCFAULT return (pr_xstatement=(st-pr_statements)-1),PR_HandleFault
#ifdef __GNUC__
#define errorif(x) if(__builtin_expect(x,0))
#else
#define errorif(x) if(x)
#endif
//rely upon just st
{
#ifdef DEBUGABLE
@ -48,7 +54,7 @@ cont: //last statement may have been a breakpoint
s = st-pr_statements;
s+=1;
if (prinst.watch_ptr && prinst.watch_ptr->_int != prinst.watch_old._int)
errorif (prinst.watch_ptr && prinst.watch_ptr->_int != prinst.watch_old._int)
{
//this will fire on the next instruction after the variable got changed.
pr_xstatement = s;
@ -131,7 +137,7 @@ reeval:
break;
case OP_DIV_F:
/* if (!OPB->_float)
/* errorif (!OPB->_float)
{
pr_xstatement = st-pr_statements;
printf ("Division by 0 in %s\n", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name));
@ -141,7 +147,7 @@ reeval:
break;
case OP_DIV_VF:
tmpf = OPB->_float;
/* if (!tmpf)
/* errorif (!tmpf)
{
pr_xstatement = st-pr_statements;
printf ("Division by 0 in %s\n", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name));
@ -234,7 +240,7 @@ reeval:
OPC->_float = (float)(!(OPA->function & ~0xff000000));
break;
case OP_NOT_ENT:
OPC->_float = (float)(PROG_TO_EDICT(progfuncs, OPA->edict) == (edictrun_t *)sv_edicts);
OPC->_float = (float)(!(OPA->edict));//(PROG_TO_EDICT(progfuncs, OPA->edict) == (edictrun_t *)sv_edicts);
break;
case OP_EQ_F:
@ -341,7 +347,7 @@ reeval:
//store a value to a pointer
case OP_STOREP_IF:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
errorif (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
if (OPB->_int == -1)
break;
@ -351,7 +357,7 @@ reeval:
ptr->_float = (float)OPA->_int;
break;
case OP_STOREP_FI:
if (QCPOINTERWRITEFAIL(OPB, sizeof(int)))
errorif (QCPOINTERWRITEFAIL(OPB, sizeof(int)))
{
if (OPB->_int == -1)
break;
@ -366,7 +372,7 @@ reeval:
case OP_STOREP_FLD: // integers
case OP_STOREP_S:
case OP_STOREP_FNC: // pointers
if (QCPOINTERWRITEFAIL(OPB, sizeof(int)))
errorif (QCPOINTERWRITEFAIL(OPB, sizeof(int)))
{
if (OPB->_int == -1)
break;
@ -379,7 +385,7 @@ reeval:
ptr->_int = OPA->_int;
break;
case OP_STOREP_V:
if (QCPOINTERWRITEFAIL(OPB, sizeof(vec3_t)))
errorif (QCPOINTERWRITEFAIL(OPB, sizeof(vec3_t)))
{
if (OPB->_int == -1)
break;
@ -392,8 +398,10 @@ reeval:
break;
case OP_STOREP_C: //store character in a string
if (QCPOINTERWRITEFAIL(OPB, sizeof(char)))
errorif (QCPOINTERWRITEFAIL(OPB, sizeof(char)))
{
if (OPB->_int == -1)
break;
QCFAULT(&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
@ -402,7 +410,7 @@ reeval:
//get a pointer to a field var
case OP_ADDRESS:
if ((unsigned)OPA->edict >= (unsigned)sv_num_edicts)
errorif ((unsigned)OPA->edict >= (unsigned)num_edicts)
{
pr_xstatement = st-pr_statements;
if (PR_RunWarning (&progfuncs->funcs, "OP_ADDRESS references invalid entity in %s\n", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name)))
@ -416,7 +424,7 @@ reeval:
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
if (!ed || ed->readonly)
errorif (!ed || ed->readonly)
{
//boot it over to the debugger
@ -437,11 +445,18 @@ reeval:
}
//Whilst the next block would technically be correct, we don't use it as it breaks too many quake mods.
// if (ed->isfree)
// {
// pr_xstatement = st-pr_statements;
// PR_RunError (progfuncs, "assignment to free entitiy in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
// }
#ifdef NOLEGACY
errorif (ed->isfree)
{
pr_xstatement = st-pr_statements;
if (PR_RunWarning (&progfuncs->funcs, "assignment to free entitiy in %s", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name)))
{
st--;
goto cont;
}
break;
}
#endif
OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->funcs.fieldadjust));
break;
@ -453,7 +468,7 @@ reeval:
case OP_LOAD_ENT:
case OP_LOAD_S:
case OP_LOAD_FNC:
if ((unsigned)OPA->edict >= (unsigned)sv_num_edicts)
errorif ((unsigned)OPA->edict >= (unsigned)num_edicts)
{
pr_xstatement = st-pr_statements;
if (PR_RunWarning (&progfuncs->funcs, "OP_LOAD references invalid entity %i in %s\n", OPA->edict, PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name)))
@ -468,12 +483,19 @@ reeval:
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int + progfuncs->funcs.fieldadjust);
OPC->_int = ptr->_int;
#ifdef NOLEGACY
if (ed->isfree)
OPC->_int = 0;
else
#endif
{
ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int + progfuncs->funcs.fieldadjust);
OPC->_int = ptr->_int;
}
break;
case OP_LOAD_V:
if ((unsigned)OPA->edict >= (unsigned)sv_num_edicts)
errorif ((unsigned)OPA->edict >= (unsigned)num_edicts)
{
pr_xstatement = st-pr_statements;
if (PR_RunWarning (&progfuncs->funcs, "OP_LOAD_V references invalid entity %i in %s\n", OPA->edict, PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name)))
@ -490,10 +512,21 @@ reeval:
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int + progfuncs->funcs.fieldadjust);
OPC->_vector[0] = ptr->_vector[0];
OPC->_vector[1] = ptr->_vector[1];
OPC->_vector[2] = ptr->_vector[2];
#ifdef NOLEGACY
if (ed->isfree)
{
OPC->_vector[0] = 0;
OPC->_vector[1] = 0;
OPC->_vector[2] = 0;
}
else
#endif
{
ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int + progfuncs->funcs.fieldadjust);
OPC->_vector[0] = ptr->_vector[0];
OPC->_vector[1] = ptr->_vector[1];
OPC->_vector[2] = ptr->_vector[2];
}
break;
//==================
@ -583,7 +616,7 @@ reeval:
fnum &= ~0xff000000; //the callee's function index.
//if it's an external call, switch now (before any function pointers are used)
if (!PR_SwitchProgsParms(progfuncs, newpr) || !fnum || fnum > pr_progs->numfunctions)
errorif (!PR_SwitchProgsParms(progfuncs, newpr) || !fnum || fnum > pr_progs->numfunctions)
{
char *msg = fnum?"OP_CALL references invalid function in %s\n":"NULL function from qc (inside %s).\n";
PR_SwitchProgsParms(progfuncs, callerprogs);
@ -621,6 +654,10 @@ reeval:
prinst.numtempstringsstack = prinst.numtempstrings;
#endif
(*externs->globalbuiltins[i]) (&progfuncs->funcs, (struct globalvars_s *)current_progstate->globals);
//in case ed_alloc was called
num_edicts = sv_num_edicts;
if (prinst.continuestatement!=-1)
{
st=&pr_statements[prinst.continuestatement];
@ -781,7 +818,7 @@ reeval:
{
i = (unsigned int)OPB->_float;
ptr = (eval_t*)PR_StringToNative(&progfuncs->funcs, OPA->_int);
if ((size_t)i > strlen((char*)ptr))
errorif ((size_t)i > strlen((char*)ptr))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer read in %s (%i bytes into %s)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), i, ptr);
@ -799,7 +836,7 @@ reeval:
case OP_LOADP_S:
case OP_LOADP_FNC:
i = OPA->_int + OPB->_int*4;
if ((unsigned int)i > prinst.addressableused-sizeof(int))
errorif ((unsigned int)i > prinst.addressableused-sizeof(int))
{
if (i == -1)
{
@ -815,7 +852,7 @@ reeval:
case OP_LOADP_V:
i = OPA->_int + OPB->_int*4; //NOTE: inconsistant!
if ((unsigned int)i > prinst.addressableused-sizeof(vec3_t))
errorif ((unsigned int)i > prinst.addressableused-sizeof(vec3_t))
{
if (i == -1)
{
@ -848,7 +885,7 @@ reeval:
case OP_FETCH_GBL_E:
case OP_FETCH_GBL_FNC:
i = OPB->_float;
if((unsigned)i > (unsigned)((eval_t *)&glob[st->a-1])->_int)
errorif((unsigned)i > (unsigned)((eval_t *)&glob[st->a-1])->_int)
{
pr_xstatement = st-pr_statements;
PR_RunError(&progfuncs->funcs, "array index out of bounds: %s[%d] (max %d)", PR_GlobalStringNoContents(progfuncs, st->a), i, ((eval_t *)&glob[st->a-1])->_int);
@ -857,7 +894,7 @@ reeval:
break;
case OP_FETCH_GBL_V:
i = OPB->_float;
if((unsigned)i > (unsigned)((eval_t *)&glob[st->a-1])->_int)
errorif((unsigned)i > (unsigned)((eval_t *)&glob[st->a-1])->_int)
{
pr_xstatement = st-pr_statements;
PR_RunError(&progfuncs->funcs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i);
@ -890,7 +927,7 @@ reeval:
/*OPC->_vector[2] = */OPB->_vector[2] *= tmpf;
break;
case OP_MULSTOREP_F:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
errorif (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
@ -899,7 +936,7 @@ reeval:
OPC->_float = ptr->_float *= OPA->_float;
break;
case OP_MULSTOREP_VF:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
errorif (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
@ -914,7 +951,7 @@ reeval:
/*OPC->_float = */OPB->_float /= OPA->_float;
break;
case OP_DIVSTOREP_F:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
errorif (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
@ -931,7 +968,7 @@ reeval:
/*OPC->_vector[2] =*/ OPB->_vector[2] += OPA->_vector[2];
break;
case OP_ADDSTOREP_F:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
errorif (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
@ -940,7 +977,7 @@ reeval:
OPC->_float = ptr->_float += OPA->_float;
break;
case OP_ADDSTOREP_V:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
errorif (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
@ -959,7 +996,7 @@ reeval:
/*OPC->_vector[2] = */OPB->_vector[2] -= OPA->_vector[2];
break;
case OP_SUBSTOREP_F:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
errorif (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
@ -968,7 +1005,7 @@ reeval:
OPC->_float = ptr->_float -= OPA->_float;
break;
case OP_SUBSTOREP_V:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
errorif (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
@ -982,7 +1019,7 @@ reeval:
OPB->_float = (int)OPB->_float | (int)OPA->_float;
break;
case OP_BITSETSTOREP_F:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
errorif (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
@ -994,7 +1031,7 @@ reeval:
OPB->_float = (int)OPB->_float & ~(int)OPA->_float;
break;
case OP_BITCLRSTOREP_F:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
errorif (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
@ -1153,7 +1190,7 @@ reeval:
case OP_GLOAD_ENT:
case OP_GLOAD_S:
case OP_GLOAD_FNC:
if (OPA->_int < 0 || OPA->_int*4 >= current_progstate->globals_size)
errorif (OPA->_int < 0 || OPA->_int*4 >= current_progstate->globals_size)
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad indexed global read in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPA->_int, current_progstate->globals_size);
@ -1162,7 +1199,7 @@ reeval:
OPC->_int = ptr->_int;
break;
case OP_GLOAD_V:
if (OPA->_int < 0 || (OPA->_int+2)*4 >= current_progstate->globals_size)
errorif (OPA->_int < 0 || (OPA->_int+2)*4 >= current_progstate->globals_size)
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad indexed global read in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPA->_int, current_progstate->globals_size);
@ -1178,7 +1215,7 @@ reeval:
case OP_GSTOREP_FLD:
case OP_GSTOREP_S:
case OP_GSTOREP_FNC:
if (OPB->_int < 0 || OPB->_int*4 >= current_progstate->globals_size)
errorif (OPB->_int < 0 || OPB->_int*4 >= current_progstate->globals_size)
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad indexed global write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
@ -1187,7 +1224,7 @@ reeval:
ptr->_int = OPA->_int;
break;
case OP_GSTOREP_V:
if (OPB->_int < 0 || (OPB->_int+2)*4 >= current_progstate->globals_size)
errorif (OPB->_int < 0 || (OPB->_int+2)*4 >= current_progstate->globals_size)
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad indexed global write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
@ -1199,7 +1236,7 @@ reeval:
break;
case OP_BOUNDCHECK:
if ((unsigned int)OPA->_int < (unsigned int)st->c || (unsigned int)OPA->_int >= (unsigned int)st->b)
errorif ((unsigned int)OPA->_int < (unsigned int)st->c || (unsigned int)OPA->_int >= (unsigned int)st->b)
{
printf("Progs boundcheck failed. Value is %i. Must be between %u and %u\n", OPA->_int, st->c, st->b);
QCFAULT(&progfuncs->funcs, "Progs boundcheck failed. Value is %i. Must be between %u and %u\n", OPA->_int, st->c, st->b);

View File

@ -449,7 +449,7 @@ int PDECL PR_InitEnts(pubprogfuncs_t *ppf, int max_ents)
prinst.max_fields_size = prinst.fields_size;
prinst.edicttable = PRHunkAlloc(progfuncs, prinst.maxedicts*sizeof(struct edicts_s *), "edicttable");
progfuncs->funcs.edicttable = prinst.edicttable = PRHunkAlloc(progfuncs, prinst.maxedicts*sizeof(struct edicts_s *), "edicttable");
sv_edicts = PRHunkAlloc(progfuncs, externs->edictsize, "edict0");
prinst.edicttable[0] = sv_edicts;
((edictrun_t*)prinst.edicttable[0])->fields = PRAddressableExtend(progfuncs, NULL, prinst.fields_size, prinst.max_fields_size-prinst.fields_size);
@ -515,7 +515,7 @@ static void PDECL PR_Configure (pubprogfuncs_t *ppf, size_t addressable_size, in
prinst.profiling = profiling;
prinst.maxedicts = 1;
prinst.edicttable = &sv_edicts;
progfuncs->funcs.edicttable = prinst.edicttable = &sv_edicts;
sv_num_edicts = 1; //set up a safty buffer so things won't go horribly wrong too often
sv_edicts=(struct edict_s *)&tempedict;
tempedict.readonly = true;
@ -1415,8 +1415,8 @@ static void PDECL PR_CloseProgs(pubprogfuncs_t *ppf)
for ( i=1 ; i<inst->inst.maxedicts; i++)
{
e = (edictrun_t *)(inst->inst.edicttable[i]);
inst->inst.edicttable[i] = NULL;
e = (edictrun_t *)(inst->funcs.edicttable[i]);
inst->funcs.edicttable[i] = NULL;
if (e)
{
// e->entnum = i;

View File

@ -2134,7 +2134,7 @@ int PDECL PR_LoadEnts(pubprogfuncs_t *ppf, const char *file, float killonspawnfl
sv_num_edicts = 1; //set up a safty buffer so things won't go horribly wrong too often
sv_edicts=(struct edict_s *)&tempedict;
prinst.edicttable = &sv_edicts;
progfuncs->funcs.edicttable = prinst.edicttable = &sv_edicts;
sv_num_edicts = numents; //should be fine

View File

@ -1466,6 +1466,7 @@ static int PR_ExecuteCode16 (progfuncs_t *fte_restrict progfuncs, int s, int *ft
unsigned short op;
eval_t *switchref = (eval_t*)glob;
unsigned int num_edicts = sv_num_edicts;
#define OPA ((eval_t *)&glob[st->a])
#define OPB ((eval_t *)&glob[st->b])
@ -1527,6 +1528,7 @@ static int PR_ExecuteCode32 (progfuncs_t *fte_restrict progfuncs, int s, int *ft
float tmpf;
int tmpi;
eval_t *switchref = (eval_t*)glob;
unsigned int num_edicts = sv_num_edicts;
unsigned int op;

View File

@ -157,13 +157,13 @@ struct pubprogfuncs_s
string_t (PDECL *TempString) (pubprogfuncs_t *prinst, const char *str);
string_t (PDECL *StringToProgs) (pubprogfuncs_t *prinst, const char *str);
string_t (PDECL *StringToProgs) (pubprogfuncs_t *prinst, const char *str); //commonly makes a semi-permanent mapping from some table to the string value. mapping can be removed via RemoveProgsString
const char *(ASMCALL *StringToNative) (pubprogfuncs_t *prinst, string_t str);
int (PDECL *QueryField) (pubprogfuncs_t *prinst, unsigned int fieldoffset, etype_t *type, char **name, evalc_t *fieldcache); //find info on a field definition at an offset
void (PDECL *EntClear) (pubprogfuncs_t *progfuncs, struct edict_s *e);
void (PDECL *FindPrefixGlobals) (pubprogfuncs_t *progfuncs, int prnum, char *prefix, void (PDECL *found) (pubprogfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type, void *ctx), void *ctx);
void (PDECL *FindPrefixGlobals) (pubprogfuncs_t *progfuncs, int prnum, char *prefix, void (PDECL *found) (pubprogfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type, void *ctx), void *ctx); //calls the callback for each named global found
void *(PDECL *AddressableAlloc) (pubprogfuncs_t *progfuncs, unsigned int ammount); /*returns memory within the qc block, use stringtoprogs to get a usable qc pointer/string*/
@ -174,13 +174,15 @@ struct pubprogfuncs_s
void (PDECL *AddSharedVar) (pubprogfuncs_t *progfuncs, int start, int size);
void (PDECL *AddSharedFieldVar) (pubprogfuncs_t *progfuncs, int num, char *relstringtable);
char *(PDECL *RemoveProgsString) (pubprogfuncs_t *progfuncs, string_t str);
int (PDECL *GetFuncArgCount) (pubprogfuncs_t *progfuncs, func_t func);
void (PDECL *GenerateStatementString) (pubprogfuncs_t *progfuncs, int statementnum, char *out, int outlen);
int (PDECL *GetFuncArgCount) (pubprogfuncs_t *progfuncs, func_t func); //ask how many args a function is meant to have
void (PDECL *GenerateStatementString) (pubprogfuncs_t *progfuncs, int statementnum, char *out, int outlen); //disassembles a specific statement. for debugging reports.
fdef_t *(PDECL *FieldInfo) (pubprogfuncs_t *progfuncs, unsigned int *count);
char *(PDECL *UglyValueString) (pubprogfuncs_t *progfuncs, etype_t type, union eval_s *val);
pbool (PDECL *ParseEval) (pubprogfuncs_t *progfuncs, union eval_s *eval, int type, const char *s);
void (PDECL *SetStringField) (pubprogfuncs_t *progfuncs, struct edict_s *ed, string_t *fld, const char *str, pbool str_is_static); //if ed is null, fld points to a global. if str_is_static, then s doesn't need its own memory allocated.
pbool (PDECL *DumpProfile) (pubprogfuncs_t *progfuncs, pbool resetprofiles);
struct edict_s **edicttable;
};
typedef struct progexterns_s {
@ -266,7 +268,11 @@ typedef union eval_s
#define PR_LoadEnts(pf, s, kf) (*pf->load_ents) (pf, s, kf)
#define PR_SaveEnts(pf, buf, size, maxsize, mode) (*pf->save_ents) (pf, buf, size, maxsize, mode)
#if 0//def _DEBUG
#define EDICT_NUM(pf, num) (*pf->EDICT_NUM) (pf, num)
#else
#define EDICT_NUM(pf, num) (pf->edicttable[num])
#endif
#define NUM_FOR_EDICT(pf, e) (*pf->NUM_FOR_EDICT) (pf, (struct edict_s*)(e))
#define SetGlobalEdict(pf, ed, ofs) (*pf->SetGlobalEdict) (pf, ed, ofs)
#define PR_VarString(pf,first) (*pf->VarString) (pf,first)

View File

@ -1,6 +1,7 @@
#if !defined(MINIMAL) && !defined(OMIT_QCC)
#include "qcc.h"
#include <math.h>
//FIXME: #define IAMNOTLAZY
@ -4477,7 +4478,44 @@ static QCC_sref_t QCC_PR_Inline(QCC_sref_t fdef, QCC_sref_t *arglist, unsigned i
ctx.result = nullsref;
ctx.func = &functions[eval->function];
if ((int)ctx.func->code <= 0)
{
char *fname = ctx.func->name;
if (argcount == 1)
{
const QCC_eval_t *eval = QCC_SRef_EvalConst(arglist[0]);
if (eval && !strcmp(fname, "sin"))
return QCC_MakeFloatConst(sin(eval->_float));
if (eval && !strcmp(fname, "cos"))
return QCC_MakeFloatConst(cos(eval->_float));
if (eval && !strcmp(fname, "floor"))
return QCC_MakeFloatConst(floor(eval->_float));
if (eval && !strcmp(fname, "ceil"))
return QCC_MakeFloatConst(ceil(eval->_float));
if (eval && !strcmp(fname, "rint"))
return QCC_MakeFloatConst((int)((eval->_float>0)?(eval->_float+0.5):(eval->_float-0.5)));
if (eval && !strcmp(fname, "fabs"))
return QCC_MakeFloatConst(fabs(eval->_float));
if (eval && !strcmp(fname, "sqrt"))
return QCC_MakeFloatConst(sqrt(eval->_float));
if (eval && !strcmp(fname, "log"))
return QCC_MakeFloatConst(log(eval->_float));
if (eval && !strcmp(fname, "log10"))
return QCC_MakeFloatConst(log10(eval->_float));
if (eval && !strcmp(fname, "ftoi"))
return QCC_MakeIntConst(eval->_float);
if (eval && !strcmp(fname, "itof"))
return QCC_MakeFloatConst(eval->_int);
}
else if (argcount == 2)
{
const QCC_eval_t *a1 = QCC_SRef_EvalConst(arglist[0]);
const QCC_eval_t *a2 = QCC_SRef_EvalConst(arglist[1]);
if (a1 && a2 && !strcmp(fname, "pow"))
return QCC_MakeFloatConst(pow(a1->_float, a2->_float));
}
return nullsref; //don't try to inline builtins. that simply cannot work.
}
//FIXME: inefficient: we can't revert this on failure, so make sure its done early, just in case.
if (argcount && arglist[0].sym->generatedfor == &def_ret)

View File

@ -1,6 +1,6 @@
#include "quakedef.h"
#ifndef CLIENTONLY
#if !defined(CLIENTONLY) && defined(NETPREPARSE)
/*Testing this code should typically be done with the three following mods:
Prydon gate
Nexuiz
@ -657,50 +657,49 @@ void NPP_NQFlush(void)
{
client_t *cl;
int i;
char *h2finale = NULL;
char *h2title = NULL;
#ifdef HEXEN2
if (progstype == PROG_H2)
{
/*hexen2 does something like this in the client, but we don't support those protocols, so translate to something usable*/
char *title[13] = {"gfx/finale.lmp", "gfx/meso.lmp", "gfx/egypt.lmp", "gfx/roman.lmp", "gfx/castle.lmp", "gfx/castle.lmp", "gfx/end-1.lmp", "gfx/end-2.lmp", "gfx/end-3.lmp", "gfx/castle.lmp", "gfx/mpend.lmp", "gfx/mpmid.lmp", "gfx/end-3.lmp"};
int lookup[13] = {394, 395, 396, 397, 358, strcmp(T_GetString(400+5*2+1), "BAD STRING")?400+5*2+1:400+4*2, 386+6, 386+7, 386+8, 391, 538, 545, 561};
//5 is the demo sell screen, which changes depending on hexen2 vs portals.
if (buffer[1] < 13)
{
h2title = title[buffer[1]];
h2finale = T_GetString(lookup[buffer[1]]);
}
}
#endif
for (i = 0, cl = svs.clients; i < sv.allocated_client_slots; i++, cl++)
{
if (cl->state == cs_spawned && ISQWCLIENT(cl))
{
#ifdef HEXEN2
char *h2finale = NULL;
char *h2title = NULL;
/*
if (cl->zquake_extensions & Z_EXT_SERVERTIME)
{
ClientReliableCheckBlock(cl, 6);
ClientReliableWrite_Byte(cl, svc_updatestatlong);
ClientReliableWrite_Byte(cl, STAT_TIME);
ClientReliableWrite_Long(cl, (int)(sv.world.physicstime * 1000));
cl->nextservertimeupdate = sv.world.physicstime+10;
}
*/
if (progstype == PROG_H2)
{
/*hexen2 does something like this in the client, but we don't support those protocols, so translate to something usable*/
char *title[13] = {"gfx/finale.lmp", "gfx/meso.lmp", "gfx/egypt.lmp", "gfx/roman.lmp", "gfx/castle.lmp", "gfx/castle.lmp", "gfx/end-1.lmp", "gfx/end-2.lmp", "gfx/end-3.lmp", "gfx/castle.lmp", "gfx/mpend.lmp", "gfx/mpmid.lmp", "gfx/end-3.lmp"};
int lookup[13] = {394, 395, 396, 397, 358, strcmp(T_GetString(400+5*2+1), "BAD STRING")?400+5*2+1:400+4*2, 386+6, 386+7, 386+8, 391, 538, 545, 561};
//5 is the demo sell screen, which changes depending on hexen2 vs portals.
if (buffer[1] < 13)
{
h2title = title[buffer[1]];
h2finale = T_GetString(lookup[buffer[1]]);
}
}
if (h2finale)
{
ClientReliableCheckBlock(cl, 3 + strlen(h2title) + 3 + strlen(h2finale) + 1);
ClientReliableWrite_Byte(cl, svc_finale);
ClientReliableWrite_Byte(cl, '/');
ClientReliableWrite_Byte(cl, 'I');
ClientReliableWrite_SZ(cl, h2title, strlen(h2title));
ClientReliableWrite_Byte(cl, ':');
ClientReliableWrite_Byte(cl, '/');
ClientReliableWrite_Byte(cl, 'P');
ClientReliableWrite_String(cl, h2finale);
}
else if (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
{ //special intermission mode to leave the view attached to the viewentity (as required for nq - especially rogue's finale) instead of hacking it to some specific point
ClientReliableCheckBlock(cl, 5);
ClientReliableWrite_Byte(cl, svc_finale);
ClientReliableWrite_String(cl, "/FI");
}
else
#endif
{
ClientReliableCheckBlock(cl, 16);
ClientReliableWrite_Byte(cl, svc_intermission);
@ -718,9 +717,17 @@ void NPP_NQFlush(void)
writedest = NULL;
}
break;
// case svc_finale:
// case svc_finale: //finale does exist in vanilla qw. apparently. hurrah.
// bufferlen = 0;
// break;
case svc_cutscene:
//finale with no text. and explicitly no flags (which mostly prevents the 'completed' banner appearing), should be equivelent.
buffer[0] = svc_finale;
buffer[1] = '/';
buffer[2] = '.';
buffer[3] = 0;
bufferlen = 4;
break;
case svc_setview:
requireextension = PEXT_SETVIEW;
@ -1005,7 +1012,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw)
protocollen = 1;
break;
case svc_finale:
protocollen = 2;
nullterms = 1;
break;
case svcdp_skybox:
protocollen = 2;//it's just a string
@ -1023,7 +1030,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw)
ignoreprotocol = true;
break;
case svc_cutscene:
ignoreprotocol = true;
nullterms = 1;
break;
case 51:
protocollen = 3;
@ -1993,7 +2000,7 @@ void NPP_QWWriteByte(int dest, qbyte data) //replacement write func (nq to qw)
protocollen = 1 + destprim->coordsize*3 + destprim->anglesize*3;
break;
case svc_finale:
protocollen = 2;
nullterms = 1;
break;
case svc_updatepl:
case svc_muzzleflash:

View File

@ -4036,8 +4036,8 @@ void QCBUILTIN PF_applylightstyle(int style, const char *val, vec3_t rgb)
Con_Printf("WARNING: Bad lightstyle %i.\n", style);
return;
}
if (strlen(val) > MAX_STYLESTRING-1)
Con_Printf("WARNING: Style string is longer than standard (%i). Some clients could crash.\n", MAX_STYLESTRING-1);
if (strlen(val) >= 64)
Con_Printf("WARNING: Style string is longer than standard (%i). Some clients could crash.\n", 63);
// change the string in sv
@ -4413,6 +4413,11 @@ sizebuf_t *NQWriteDest (int dest)
return NULL;
}
#else
static sizebuf_t *NQWriteDest (int dest)
{
return QWWriteDest(dest);
}
#endif
client_t *Write_GetClient(void)
@ -4446,6 +4451,7 @@ void QCBUILTIN PF_WriteByte (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
return;
#endif
#ifdef NETPREPARSE
if (dpcompat_nopreparse.ival)
;
else if (progstype != PROG_QW)
@ -4459,9 +4465,10 @@ void QCBUILTIN PF_WriteByte (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
NPP_QWWriteByte(dest, val);
return;
}
#endif
#endif
if (dest == MSG_ONE)
{
{ //WARNING: THIS IS BUGGY. DO NOT MAKE MODS THAT TAKE THIS PATH
client_t *cl = Write_GetClient();
if (!cl)
return;
@ -4494,6 +4501,7 @@ void QCBUILTIN PF_WriteChar (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
return;
#endif
#ifdef NETPREPARSE
if (dpcompat_nopreparse.ival)
;
else if (progstype != PROG_QW)
@ -4507,6 +4515,7 @@ void QCBUILTIN PF_WriteChar (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
NPP_QWWriteChar(dest, val);
return;
}
#endif
#endif
if (dest == MSG_ONE)
{
@ -4542,6 +4551,7 @@ void QCBUILTIN PF_WriteShort (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
return;
#endif
#ifdef NETPREPARSE
if (dpcompat_nopreparse.ival)
;
else if (progstype != PROG_QW)
@ -4556,6 +4566,8 @@ void QCBUILTIN PF_WriteShort (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
return;
}
#endif
#endif
if (dest == MSG_ONE)
{
client_t *cl = Write_GetClient();
@ -4589,6 +4601,7 @@ void QCBUILTIN PF_WriteLong (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
return;
#endif
#ifdef NETPREPARSE
if (dpcompat_nopreparse.ival)
;
else if (progstype != PROG_QW)
@ -4603,6 +4616,8 @@ void QCBUILTIN PF_WriteLong (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
return;
}
#endif
#endif
if (dest == MSG_ONE)
{
client_t *cl = Write_GetClient();
@ -4636,6 +4651,7 @@ void QCBUILTIN PF_WriteAngle (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
return;
#endif
#ifdef NETPREPARSE
if (dpcompat_nopreparse.ival)
;
else if (progstype != PROG_QW)
@ -4650,6 +4666,8 @@ void QCBUILTIN PF_WriteAngle (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
return;
}
#endif
#endif
if (dest == MSG_ONE)
{
client_t *cl = Write_GetClient();
@ -4683,6 +4701,7 @@ void QCBUILTIN PF_WriteCoord (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
return;
#endif
#ifdef NETPREPARSE
if (dpcompat_nopreparse.ival)
;
else if (progstype != PROG_QW)
@ -4697,6 +4716,8 @@ void QCBUILTIN PF_WriteCoord (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
return;
}
#endif
#endif
if (dest == MSG_ONE)
{
client_t *cl = Write_GetClient();
@ -4730,6 +4751,7 @@ void QCBUILTIN PF_WriteFloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
return;
#endif
#ifdef NETPREPARSE
if (dpcompat_nopreparse.ival)
;
else if (progstype != PROG_QW)
@ -4744,6 +4766,8 @@ void QCBUILTIN PF_WriteFloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
return;
}
#endif
#endif
if (dest == MSG_ONE)
{
client_t *cl = Write_GetClient();
@ -4776,6 +4800,7 @@ void PF_WriteString_Internal (int target, const char *str)
)
return;
#ifdef NETPREPARSE
if (dpcompat_nopreparse.ival)
;
else if (progstype != PROG_QW)
@ -4790,6 +4815,8 @@ void PF_WriteString_Internal (int target, const char *str)
return;
}
#endif
#endif
if (target == MSG_ONE)
{
client_t *cl = Write_GetClient();
@ -4830,6 +4857,7 @@ void QCBUILTIN PF_WriteEntity (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
)
return;
#ifdef NETPREPARSE
if (dpcompat_nopreparse.ival)
;
else if (progstype != PROG_QW)
@ -4844,6 +4872,8 @@ void QCBUILTIN PF_WriteEntity (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
return;
}
#endif
#endif
if (dest == MSG_ONE)
{
client_t *cl = Write_GetClient();
@ -5447,7 +5477,9 @@ void QCBUILTIN PF_multicast (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
o = G_VECTOR(OFS_PARM0);
to = G_FLOAT(OFS_PARM1);
#ifdef NETPREPARSE
NPP_Flush();
#endif
SV_Multicast (o, to);
}
@ -6390,22 +6422,6 @@ static void QCBUILTIN PF_OpenPortal (pubprogfuncs_t *prinst, struct globalvars_s
}
//EXTENSION: DP_QC_COPYENTITY
//void(entity from, entity to) copyentity = #400
//copies data from one entity to another
static void QCBUILTIN PF_copyentity (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
edict_t *in, *out;
in = G_EDICT(prinst, OFS_PARM0);
out = G_EDICT(prinst, OFS_PARM1);
memcpy(out->v, in->v, sv.world.edict_size);
World_LinkEdict(&sv.world, (wedict_t*)out, false);
}
//EXTENSION: DP_QC_FINDCHAIN
//entity(string field, string match) findchain = #402
@ -6603,8 +6619,10 @@ const char *SV_CheckRejectConnection(netadr_t *adr, const char *uinfo, unsigned
//others are limited by packet sizes, so the count can vary...
//features
#ifdef PEXT_VIEW2
if (pext1 & PEXT_VIEW2)
Info_SetValueForKey(clfeatures, "PEXT_VIEW2", "1", sizeof(clfeatures));
#endif
if (pext1 & PEXT_LIGHTSTYLECOL)
Info_SetValueForKey(clfeatures, "PEXT_LIGHTSTYLECOL", "1", sizeof(clfeatures));
if ((pext1 & PEXT_CSQC) || (protocol == SCP_DARKPLACES6) || (protocol == SCP_DARKPLACES7))
@ -7757,6 +7775,7 @@ void QCBUILTIN PF_sv_trailparticles(pubprogfuncs_t *prinst, struct globalvars_s
MSG_WriteCoord(&sv.multicast, end[1]);
MSG_WriteCoord(&sv.multicast, end[2]);
#ifdef NQPROT
MSG_WriteByte(&sv.nqmulticast, svcdp_trailparticles);
MSG_WriteEntity(&sv.nqmulticast, ednum);
MSG_WriteShort(&sv.nqmulticast, efnum);
@ -7766,6 +7785,7 @@ void QCBUILTIN PF_sv_trailparticles(pubprogfuncs_t *prinst, struct globalvars_s
MSG_WriteCoord(&sv.nqmulticast, end[0]);
MSG_WriteCoord(&sv.nqmulticast, end[1]);
MSG_WriteCoord(&sv.nqmulticast, end[2]);
#endif
SV_MulticastProtExt(start, MULTICAST_PHS, pr_global_struct->dimension_send, PEXT_CSQC, 0);
#endif
@ -7790,11 +7810,13 @@ void QCBUILTIN PF_sv_pointparticles(pubprogfuncs_t *prinst, struct globalvars_s
MSG_WriteCoord(&sv.multicast, org[1]);
MSG_WriteCoord(&sv.multicast, org[2]);
#ifdef NQPROT
MSG_WriteByte(&sv.nqmulticast, svcdp_pointparticles1);
MSG_WriteShort(&sv.nqmulticast, efnum);
MSG_WriteCoord(&sv.nqmulticast, org[0]);
MSG_WriteCoord(&sv.nqmulticast, org[1]);
MSG_WriteCoord(&sv.nqmulticast, org[2]);
#endif
}
else
{
@ -7808,6 +7830,7 @@ void QCBUILTIN PF_sv_pointparticles(pubprogfuncs_t *prinst, struct globalvars_s
MSG_WriteCoord(&sv.multicast, vel[2]);
MSG_WriteShort(&sv.multicast, count);
#ifdef NQPROT
MSG_WriteByte(&sv.nqmulticast, svcdp_pointparticles);
MSG_WriteShort(&sv.nqmulticast, efnum);
MSG_WriteCoord(&sv.nqmulticast, org[0]);
@ -7817,6 +7840,7 @@ void QCBUILTIN PF_sv_pointparticles(pubprogfuncs_t *prinst, struct globalvars_s
MSG_WriteCoord(&sv.nqmulticast, vel[1]);
MSG_WriteCoord(&sv.nqmulticast, vel[2]);
MSG_WriteShort(&sv.nqmulticast, count);
#endif
}
SV_MulticastProtExt(org, MULTICAST_PHS, pr_global_struct->dimension_send, PEXT_CSQC, 0);
#endif
@ -9630,6 +9654,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"frameforname", PF_frameforname, 0, 0, 0, 276, D("float(float modidx, string framename)", "Looks up a framegroup from a model by name, avoiding the need for hardcoding. Returns -1 on error.")},// (FTE_CSQC_SKELETONOBJECTS)
{"frameduration", PF_frameduration, 0, 0, 0, 277, D("float(float modidx, float framenum)", "Retrieves the duration (in seconds) of the specified framegroup.")},// (FTE_CSQC_SKELETONOBJECTS)
#ifdef TERRAIN
{"terrain_edit", PF_terrain_edit, 0, 0, 0, 278, D("void(float action, optional vector pos, optional float radius, optional float quant, ...)", "Realtime terrain editing. Actions are the TEREDIT_ constants.")},// (??FTE_TERRAIN_EDIT??
#define qcbrushface \
@ -9651,7 +9676,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"brush_findinvolume",PF_brush_findinvolume,0, 0, 0, 0, D("int(float modelid, vector *planes, float *dists, int numplanes, int *out_brushes, int *out_faces, int maxresults)", "Allows you to easily obtain a list of brushes+faces within the given bounding region. If out_faces is not null, the same brush might be listed twice.")},
// {"brush_editplane", PF_brush_editplane, 0, 0, 0, 0, D("float(float modelid, int brushid, int faceid, in brushface *face)", "Changes a surface's texture info.")},
// {"brush_transformselected",PF_brush_transformselected,0,0,0, 0, D("int(float modelid, int brushid, float *matrix)", "Transforms selected brushes by the given transform")},
#endif
{"touchtriggers", PF_touchtriggers, 0, 0, 0, 279, D("void(optional entity ent, optional vector neworigin)", "Triggers a touch events between self and every SOLID_TRIGGER entity that it is in contact with. This should typically just be the triggers touch functions. Also optionally updates the origin of the moved entity.")},//
@ -9805,7 +9830,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
//DP extras
//DP_QC_COPYENTITY
{"copyentity", PF_copyentity, 0, 0, 0, 400, "void(entity from, entity to)"},// (DP_QC_COPYENTITY)
{"copyentity", PF_copyentity, 0, 0, 0, 400, D("entity(entity from, optional entity to)", "Copies all fields from one entity to another.")},// (DP_QC_COPYENTITY)
//DP_SV_SETCOLOR
{"setcolors", PF_setcolors, 0, 0, 0, 401, D("void(entity ent, float colours)", "Changes a player's colours. The bits 0-3 are the lower/trouser colour, bits 4-7 are the upper/shirt colours.")},//DP_SV_SETCOLOR
//DP_QC_FINDCHAIN
@ -10874,10 +10899,12 @@ void PR_DumpPlatform_f(void)
//not putting other svcs here, qc shouldn't otherwise need to generate svcs directly.
{"SVC_CGAMEPACKET", "const float", QW|NQ, "Direct ssqc->csqc message. Must only be multicast. The data triggers a CSQC_Parse_Event call in the csqc for the csqc to read the contents. The server *may* insert length information for clients connected via proxies which are not able to cope with custom csqc payloads. This should only ever be used in conjunction with the MSG_MULTICAST destination.", svcfte_cgamepacket},
#ifndef QUAKETC
{"MSG_BROADCAST", "const float", QW|NQ, "The byte(s) will be unreliably sent to all players. MSG_ constants are valid arguments to the Write* builtin family.", MSG_BROADCAST},
{"MSG_ONE", "const float", QW|NQ, "The byte(s) will be reliably sent to the player specified in the msg_entity global.", MSG_ONE},
{"MSG_ONE", "const float", QW|NQ, "The byte(s) will be reliably sent to the player specified in the msg_entity global. WARNING: in quakeworld servers without network preparsing enabled, this can result in illegible server messages (due to individual reliable messages being split between multiple backbuffers/packets). NQ has larger reliable buffers which avoids this issue, but still kicks the client.", MSG_ONE},
{"MSG_ALL", "const float", QW|NQ, "The byte(s) will be reliably sent to all players.", MSG_ALL},
{"MSG_INIT", "const float", QW|NQ, "The byte(s) will be written into the signon buffer. Clients will see these messages when they connect later. This buffer is only flushed on map changes, so spamming it _WILL_ result in overflows.", MSG_INIT},
#endif
{"MSG_MULTICAST", "const float", QW|NQ, "The byte(s) will be written into the multicast buffer for more selective sending. Messages sent this way will never be split across packets, and using this for csqc-only messages will not break protocol translation.", MSG_MULTICAST},
{"MSG_ENTITY", "const float", QW|NQ, "The byte(s) will be written into the entity buffer. This is a special value used only inside 'SendEntity' functions.", MSG_CSQC},
@ -11027,6 +11054,7 @@ void PR_DumpPlatform_f(void)
{"HASH_REPLACE", "const float", ALL, "Used with hash_add. Attempts to remove the old value instead of adding two values for a single key.", 256},
{"HASH_ADD", "const float", ALL, "Used with hash_add. The new entry will be inserted in addition to the existing entry.", 512},
#ifdef QUAKESTATS
{"STAT_HEALTH", "const float", CS, "Player's health.", STAT_HEALTH},
{"STAT_WEAPONMODELI", "const float", CS, "This is the modelindex of the current viewmodel (renamed from the original name 'STAT_WEAPON' due to confusions).", STAT_WEAPONMODELI},
{"STAT_AMMO", "const float", CS, "player.currentammo", STAT_AMMO},
@ -11047,6 +11075,7 @@ void PR_DumpPlatform_f(void)
{"STAT_VIEWZOOM", "const float", CS, "Scales fov and sensitiity. Part of DP_VIEWZOOM.", STAT_VIEWZOOM},
{"STAT_USER", "const float", QW|NQ|CS, "Custom user stats start here (lower values are reserved for engine use).", 32},
#endif
{"VF_MIN", "const float", CS|MENU, "The top-left of the 3d viewport in screenspace. The VF_ values are used via the setviewprop/getviewprop builtins.", VF_MIN},
{"VF_MIN_X", "const float", CS|MENU, NULL, VF_MIN_X},
@ -11153,6 +11182,7 @@ void PR_DumpPlatform_f(void)
{"LFLAG_SHADOWMAP", "const float", CS, NULL, LFLAG_SHADOWMAP},
{"LFLAG_CREPUSCULAR", "const float", CS, NULL, LFLAG_CREPUSCULAR},
#ifdef TERRAIN
{"TEREDIT_RELOAD", "const float", CS, NULL, ter_reload},
{"TEREDIT_SAVE", "const float", CS, NULL, ter_save},
{"TEREDIT_SETHOLE", "const float", CS, NULL, ter_sethole},
@ -11179,6 +11209,7 @@ void PR_DumpPlatform_f(void)
{"TEREDIT_ENTS_WIPE", "const float", CS, NULL, ter_ents_wipe},
{"TEREDIT_ENTS_CONCAT", "const float", CS, NULL, ter_ents_concat},
{"TEREDIT_ENTS_GET", "const float", CS, NULL, ter_ents_get},
#endif
{"SLIST_HOSTCACHEVIEWCOUNT", "const float", CS|MENU, NULL, SLIST_HOSTCACHEVIEWCOUNT},
{"SLIST_HOSTCACHETOTALCOUNT", "const float", CS|MENU, NULL, SLIST_HOSTCACHETOTALCOUNT},

View File

@ -784,6 +784,9 @@ typedef struct
#define BAN_VIP (1u<<7) //mods might give the user special rights, via the *VIP infokey. the engine itself currently does not do anything but track it.
#define BAN_BLIND (1u<<8) //player's pvs is wiped.
#define BAN_SPECONLY (1u<<9) //player is forced to spectate
#define BAN_STEALTH (1u<<10)//player is not told of their bans
#define BAN_ALL (BAN_BAN|BAN_PERMIT|BAN_CUFF|BAN_MUTE|BAN_CRIPPLED|BAN_DEAF|BAN_LAGGED|BAN_VIP|BAN_BLIND|BAN_SPECONLY|BAN_STEALTH)
typedef struct bannedips_s {
unsigned int banflags;
@ -1286,15 +1289,13 @@ void Rank_RegisterCommands(void);
int Rank_GetPass (char *name);
extern cvar_t rank_needlogin;
qboolean ReloadRanking(client_t *cl, const char *newname);
#endif
client_t *SV_GetClientForString(const char *name, int *id);
qboolean SV_MayCheat(void);
qboolean ReloadRanking(client_t *cl, const char *newname);
#endif

View File

@ -41,6 +41,25 @@ cvar_t sv_cheats = SCVARF("sv_cheats", "0", CVAR_LATCH);
extern cvar_t sv_public;
static const struct banflags_s
{
unsigned int banflag;
const char *names[2];
} banflags[] =
{
{BAN_BAN, "ban"},
{BAN_PERMIT, "safe", "permit"},
{BAN_CUFF, "cuff"},
{BAN_MUTE, "mute"},
{BAN_CRIPPLED, "cripple"},
{BAN_DEAF, "deaf"},
{BAN_LAGGED, "lag", "lagged"},
{BAN_VIP, "vip"},
{BAN_BLIND, "blind"},
{BAN_SPECONLY, "spec"},
{BAN_STEALTH, "stealth"}
};
//generic helper function for naming players.
client_t *SV_GetClientForString(const char *name, int *id)
{
@ -263,7 +282,7 @@ static void SV_Noclip_f (void)
}
}
#ifdef QUAKESTATS
/*
==================
SV_Give_f
@ -342,6 +361,7 @@ static void SV_Give_f (void)
*/
}
}
#endif
static int QDECL ShowMapList (const char *name, qofs_t flags, time_t mtime, void *parm, searchpathfuncs_t *spath)
{
@ -731,12 +751,14 @@ void SV_Map_f (void)
if (host_client->protocol == SCP_BAD)
continue;
#ifdef NQPROT
if (ISNQCLIENT(host_client))
{
SVNQ_New_f();
host_client->send_message = true;
}
else
#endif
SV_New_f();
}
}
@ -849,10 +871,9 @@ void SV_EvaluatePenalties(client_t *cl)
{
bannedips_t *banip;
unsigned int penalties = 0, delta, p;
char *penaltyreason[10];
char *activepenalties[10];
char *reasons[10] = {NULL};
char *penaltynames[10] = {"ban", "safe", "cuff", "mute", "crippled", "deaf", "lag", "vip", "blind", "spec"};
char *penaltyreason[countof(banflags)];
const char *activepenalties[countof(banflags)];
char *reasons[countof(banflags)] = {NULL};
int numpenalties = 0;
int numreasons = 0;
int i;
@ -914,7 +935,10 @@ void SV_EvaluatePenalties(client_t *cl)
//deaf+mute sees no (other) penalty messages
if (((penalties|delta) & (BAN_MUTE|BAN_DEAF)) == (BAN_MUTE|BAN_DEAF))
delta = 0;
delta &= ~(BAN_MUTE|BAN_DEAF);
if (penalties & BAN_STEALTH)
delta = 0; //don't announce ANY.
if (cl->controller)
delta = 0; //don't spam it for every player in a splitscreen client.
@ -928,20 +952,20 @@ void SV_EvaluatePenalties(client_t *cl)
SV_PrintToClient(cl, PRINT_HIGH, "VIP expired\n");
}
for (i = 0; i < sizeof(penaltyreason)/sizeof(penaltyreason[0]); i++)
for (i = 0; i < countof(banflags); i++)
{
p = 1u<<i;
p = banflags[i].banflag;
if (delta & p)
{
if (penalties & p)
{
if (penaltynames[i])
activepenalties[numpenalties++] = penaltynames[i];
if (banflags[i].names[0])
activepenalties[numpenalties++] = banflags[i].names[0];
if (reasons[i] && *reasons[i])
reasons[numreasons++] = reasons[i];
}
else
SV_PrintToClient(cl, PRINT_HIGH, va("Penalty expired: %s\n", penaltynames[i]));
SV_PrintToClient(cl, PRINT_HIGH, va("Penalty expired: %s\n", banflags[i].names[0]));
}
}
@ -1146,11 +1170,15 @@ static void SV_FilterIP_f (void)
bannedips_t proto;
extern cvar_t filterban;
char *s;
int i;
if (Cmd_Argc() < 2)
{
Con_Printf("%s <address/mask|adress/maskbits> [flags] [+time] [reason]\n", Cmd_Argv(0));
Con_Printf("allowed flags: ban,safe,cuff,mute,cripple,deaf,lag,blind,spec. time is in seconds (omitting the plus will be taken to mean unix time).\n");
Con_Printf("allowed flags: %s", banflags[0].names[0]);
for (i = 1; i < countof(banflags); i++)
Con_Printf(",%s", banflags[i].names[0]);
Con_Printf(". time is in seconds (omitting the plus will be taken to mean unix time).\n");
return;
}
@ -1172,28 +1200,16 @@ static void SV_FilterIP_f (void)
{
s=COM_ParseToken(s,",");
if (!Q_strcasecmp(com_token, ","))
;
else if (!Q_strcasecmp(com_token, "ban"))
proto.banflags |= BAN_BAN;
else if (!Q_strcasecmp(com_token, "safe") || !Q_strcasecmp(com_token, "permit"))
proto.banflags |= BAN_PERMIT;
else if (!Q_strcasecmp(com_token, "cuff"))
proto.banflags |= BAN_CUFF;
else if (!Q_strcasecmp(com_token, "mute"))
proto.banflags |= BAN_MUTE;
else if (!Q_strcasecmp(com_token, "cripple"))
proto.banflags |= BAN_CRIPPLED;
else if (!Q_strcasecmp(com_token, "deaf"))
proto.banflags |= BAN_DEAF;
else if (!Q_strcasecmp(com_token, "lag") || !Q_strcasecmp(com_token, "lagged"))
proto.banflags |= BAN_LAGGED;
else if (!Q_strcasecmp(com_token, "vip"))
proto.banflags |= BAN_VIP;
else if (!Q_strcasecmp(com_token, "blind"))
proto.banflags |= BAN_BLIND;
else if (!Q_strcasecmp(com_token, "spec"))
proto.banflags |= BAN_SPECONLY;
else
i = -1;
else for (i = 0; i < countof(banflags); i++)
{
if (!Q_strcasecmp(com_token, banflags[i].names[0]) || (banflags[i].names[1] && !Q_strcasecmp(com_token, banflags[i].names[1])))
{
proto.banflags |= banflags[i].banflag;
break;
}
}
if (i == countof(banflags))
Con_Printf("Unknown ban/penalty flag: %s. ignoring.\n", com_token);
}
//if no flags were specified,
@ -1256,45 +1272,32 @@ static void SV_FilterList_f (void)
int filtercount = 0;
bannedips_t *nb;
char adr[MAX_ADR_SIZE];
char banflags[1024];
char banflagtext[1024];
int i;
time_t curtime = SV_BanTime();
static const char *banflagnames[] = {
"ban",
"safe",
"cuff",
"mute",
"cripple",
"deaf",
"lag",
"vip",
"blind",
"spec",
NULL
};
SV_KillExpiredBans();
for (nb = svs.bannedips; nb; )
{
*banflags = 0;
for (i = 0; banflagnames[i]; i++)
*banflagtext = 0;
for (i = 0; i < countof(banflags); i++)
{
if (nb->banflags & (1u<<i))
if (nb->banflags & banflags[i].banflag)
{
if (*banflags)
Q_strncatz(banflags, ",", sizeof(banflags));
Q_strncatz(banflags, banflagnames[i], sizeof(banflags));
if (*banflagtext)
Q_strncatz(banflagtext, ",", sizeof(banflagtext));
Q_strncatz(banflagtext, banflags[i].names[0], sizeof(banflagtext));
}
}
if (nb->expiretime)
{
time_t secs = nb->expiretime - curtime;
Con_Printf("%s %s +"fPRIllu":%02u\n", NET_AdrToStringMasked(adr, sizeof(adr), &nb->adr, &nb->adrmask), banflags, (unsigned long long)(secs/60), (unsigned int)(secs%60));
Con_Printf("%s %s +"fPRIllu":%02u\n", NET_AdrToStringMasked(adr, sizeof(adr), &nb->adr, &nb->adrmask), banflagtext, (unsigned long long)(secs/60), (unsigned int)(secs%60));
}
else
Con_Printf("%s %s\n", NET_AdrToStringMasked(adr, sizeof(adr), &nb->adr, &nb->adrmask), banflags);
Con_Printf("%s %s\n", NET_AdrToStringMasked(adr, sizeof(adr), &nb->adr, &nb->adrmask), banflagtext);
filtercount++;
nb = nb->next;
}
@ -1311,8 +1314,9 @@ static void SV_Unfilter_f (void)
netadr_t unbanadr = {0};
netadr_t unbanmask = {0};
char adr[MAX_ADR_SIZE];
unsigned int banflags, nf;
unsigned int clearbanflags, nf;
char *s;
int i;
SV_KillExpiredBans();
@ -1334,48 +1338,36 @@ static void SV_Unfilter_f (void)
}
s = Cmd_Argv(2);
banflags = 0;
clearbanflags = 0;
while(*s)
{
s=COM_ParseToken(s,",");
if (!Q_strcasecmp(com_token, ","))
;
else if (!Q_strcasecmp(com_token, "ban"))
banflags |= BAN_BAN;
else if (!Q_strcasecmp(com_token, "safe") || !Q_strcasecmp(com_token, "permit"))
banflags |= BAN_PERMIT;
else if (!Q_strcasecmp(com_token, "cuff"))
banflags |= BAN_CUFF;
else if (!Q_strcasecmp(com_token, "mute"))
banflags |= BAN_MUTE;
else if (!Q_strcasecmp(com_token, "cripple"))
banflags |= BAN_CRIPPLED;
else if (!Q_strcasecmp(com_token, "deaf"))
banflags |= BAN_DEAF;
else if (!Q_strcasecmp(com_token, "lag") || !Q_strcasecmp(com_token, "lagged"))
banflags |= BAN_LAGGED;
else if (!Q_strcasecmp(com_token, "vip"))
banflags |= BAN_VIP;
else if (!Q_strcasecmp(com_token, "blind"))
banflags |= BAN_BLIND;
else if (!Q_strcasecmp(com_token, "spec"))
banflags |= BAN_SPECONLY;
else
i = -1;
else for (i = 0; i < countof(banflags); i++)
{
if (!Q_strcasecmp(com_token, banflags[i].names[0]) || (banflags[i].names[1] && !Q_strcasecmp(com_token, banflags[i].names[1])))
{
clearbanflags |= banflags[i].banflag;
break;
}
}
if (i == countof(banflags))
Con_Printf("Unknown ban/penalty flag: %s. ignoring.\n", com_token);
}
//if no flags were specified, assume all
if (!banflags)
banflags = BAN_BAN|BAN_PERMIT|BAN_CUFF|BAN_MUTE|BAN_CRIPPLED|BAN_DEAF|BAN_LAGGED|BAN_VIP|BAN_BLIND|BAN_SPECONLY;
if (!clearbanflags)
clearbanflags = BAN_ALL;
for (link = &svs.bannedips ; (nb = *link) ; )
{
if ((nb->banflags & banflags) && (all || (NET_CompareAdr(&nb->adr, &unbanadr) && NET_CompareAdr(&nb->adrmask, &unbanmask))))
if ((nb->banflags & clearbanflags) && (all || (NET_CompareAdr(&nb->adr, &unbanadr) && NET_CompareAdr(&nb->adrmask, &unbanmask))))
{
found = true;
if (!all)
Con_Printf("unfiltered %s\n", NET_AdrToStringMasked(adr, sizeof(adr), &nb->adr, &nb->adrmask));
nf = nb->banflags & banflags;
nf = nb->banflags & clearbanflags;
nb->banflags -= nf;
if (!nb->banflags)
{
@ -1457,19 +1449,8 @@ static void SV_WriteIP_f (void)
bannedips_t *bi;
char *s;
char adr[MAX_ADR_SIZE];
char banflags[1024];
char banflagtext[1024];
int i;
static const char *banflagnames[] = {
"ban",
"safe",
"cuff",
"mute",
"cripple",
"deaf",
"lag",
"vip",
NULL
};
SV_KillExpiredBans();
@ -1487,22 +1468,22 @@ static void SV_WriteIP_f (void)
bi = svs.bannedips;
while (bi)
{
*banflags = 0;
for (i = 0; banflagnames[i]; i++)
*banflagtext = 0;
for (i = 0; i < countof(banflags); i++)
{
if (bi->banflags & (1u<<i))
if (bi->banflags & banflags[i].banflag)
{
if (*banflags)
Q_strncatz(banflags, ",", sizeof(banflags));
Q_strncatz(banflags, banflagnames[i], sizeof(banflags));
if (*banflagtext)
Q_strncatz(banflagtext, ",", sizeof(banflagtext));
Q_strncatz(banflagtext, banflags[i].names[0], sizeof(banflagtext));
}
}
if (bi->reason[0])
s = va("addip %s %s "fPRIllu" \"%s\"\n", NET_AdrToStringMasked(adr, sizeof(adr), &bi->adr, &bi->adrmask), banflags, (unsigned long long) bi->expiretime, bi->reason);
s = va("addip %s %s "fPRIllu" \"%s\"\n", NET_AdrToStringMasked(adr, sizeof(adr), &bi->adr, &bi->adrmask), banflagtext, (unsigned long long) bi->expiretime, bi->reason);
else if (bi->expiretime)
s = va("addip %s %s "fPRIllu"\n", NET_AdrToStringMasked(adr, sizeof(adr), &bi->adr, &bi->adrmask), banflags, (unsigned long long) bi->expiretime);
s = va("addip %s %s "fPRIllu"\n", NET_AdrToStringMasked(adr, sizeof(adr), &bi->adr, &bi->adrmask), banflagtext, (unsigned long long) bi->expiretime);
else
s = va("addip %s %s\n", NET_AdrToStringMasked(adr, sizeof(adr), &bi->adr, &bi->adrmask), banflags);
s = va("addip %s %s\n", NET_AdrToStringMasked(adr, sizeof(adr), &bi->adr, &bi->adrmask), banflagtext);
VFS_WRITE(f, s, strlen(s));
bi = bi->next;
}
@ -2757,7 +2738,9 @@ void SV_InitOperatorCommands (void)
Cmd_AddCommand ("user", SV_User_f);
Cmd_AddCommand ("god", SV_God_f);
#ifdef QUAKESTATS
Cmd_AddCommand ("give", SV_Give_f);
#endif
Cmd_AddCommand ("noclip", SV_Noclip_f);
}

View File

@ -2537,7 +2537,7 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t *
}
}
#ifdef NQPROT
void SVNQ_EmitEntityState(sizebuf_t *msg, entity_state_t *ent)
{
edict_t *ed = EDICT_NUM(svprogfuncs, ent->number);
@ -2707,6 +2707,7 @@ int glowsize=0, glowcolor=0, colourmod=0;
if (bits & DPU_MODEL2) MSG_WriteByte(msg, (int)ent->modelindex >> 8);
}
}
#endif
typedef struct gibfilter_s {
struct gibfilter_s *next;
@ -3084,6 +3085,7 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
if (state->effects & EF_FULLBRIGHT) //wrap the field for fte clients (this is horrible)
state->hexen2flags |= MLS_FULLBRIGHT;
#ifdef NQPROT
if (progstype != PROG_QW)
{
if (progstype == PROG_TENEBRAE)
@ -3163,6 +3165,7 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
}
}
}
#endif
if (!ent->xv->colormod[0] && !ent->xv->colormod[1] && !ent->xv->colormod[2])
{
@ -3719,6 +3722,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
}
else
{
#ifdef QUAKESTATS
// Z_EXT_TIME protocol extension
// every now and then, send an update so that extrapolation
// on client side doesn't stray too far off
@ -3741,6 +3745,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
client->nextservertimeupdate = sv.world.physicstime+10;
}
}
#endif
// send over the players in the PVS
if (svs.gametype != GT_HALFLIFE)

View File

@ -824,8 +824,10 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
for (i = 0; i < svs.allocated_client_slots; i++)
{
#ifdef SVRANKING
if (svs.clients[i].state && ISQWCLIENT(&svs.clients[i]))
ReloadRanking(&svs.clients[i], svs.clients[i].name);
#endif
if (svs.clients[i].spawninfo) //don't remember this stuff.
Z_Free(svs.clients[i].spawninfo);

View File

@ -2329,7 +2329,7 @@ client_t *SVC_DirectConnect(void)
newcl = &temp;
memset (newcl, 0, sizeof(client_t));
#ifdef NQPROT
if (protocol >= SCP_NETQUAKE && protocol < SCP_DARKPLACES6)
{ //NQ protocols lack stuff like protocol extensions.
//its the wild west where nothing is known about the client and everything breaks.
@ -2356,6 +2356,7 @@ client_t *SVC_DirectConnect(void)
break;
}
}
#endif
newcl->userid = nextuserid;
newcl->fteprotocolextensions = protextsupported;
@ -2996,12 +2997,14 @@ client_t *SVC_DirectConnect(void)
PIN_ShowMessages(newcl);
}
#ifdef NQPROT
if (ISNQCLIENT(newcl))
{
newcl->netchan.message.maxsize = sizeof(newcl->netchan.message_buf);
host_client = newcl;
SVNQ_New_f();
}
#endif
newcl->redirect = redirect;
@ -3815,6 +3818,7 @@ qboolean SV_ReadPackets (float *delay)
net_from = cl->netchan.remote_address; //not sure if anything depends on this, but lets not screw them up willynilly
#ifdef NQPROT
if (ISNQCLIENT(cl))
{
if (cl->state >= cs_connected)
@ -3828,6 +3832,7 @@ qboolean SV_ReadPackets (float *delay)
}
}
else
#endif
{
/*QW*/
if (Netchan_Process(&cl->netchan))
@ -4966,7 +4971,10 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose)
if (strncmp(newname, cl->name, sizeof(cl->namebuf)-1))
{
if ((cl->penalties & BAN_MUTE) && *cl->name && verbose) //!verbose is a gamecode-forced update, where the gamecode is expected to know what its doing.
SV_ClientTPrintf (cl, PRINT_HIGH, "Muted players may not change their names\n");
{
if (!(cl->penalties & BAN_STEALTH))
SV_ClientTPrintf (cl, PRINT_HIGH, "Muted players may not change their names\n");
}
else
{
@ -4999,8 +5007,6 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose)
#ifdef SVRANKING
if (ReloadRanking(cl, newname))
{
#endif
#ifdef SVRANKING
}
else if (cl->state >= cs_spawned && *rank_filename.string && verbose)
SV_ClientTPrintf(cl, PRINT_HIGH, "Your rankings name has not been changed\n");

View File

@ -1647,7 +1647,10 @@ qboolean SV_MVD_Record (mvddest_t *dest)
else if (sv_demoExtensions.ival)
{ /*everything*/
extern cvar_t pext_replacementdeltas;
demo.recorder.fteprotocolextensions = PEXT_CSQC | PEXT_COLOURMOD | PEXT_DPFLAGS | PEXT_CUSTOMTEMPEFFECTS | PEXT_ENTITYDBL | PEXT_ENTITYDBL2 | PEXT_FATNESS | PEXT_HEXEN2 | PEXT_HULLSIZE | PEXT_LIGHTSTYLECOL | PEXT_MODELDBL | PEXT_SCALE | PEXT_SETATTACHMENT | PEXT_SETVIEW | PEXT_SOUNDDBL | PEXT_SPAWNSTATIC2 | PEXT_TRANS | PEXT_VIEW2;
demo.recorder.fteprotocolextensions = PEXT_CSQC | PEXT_COLOURMOD | PEXT_DPFLAGS | PEXT_CUSTOMTEMPEFFECTS | PEXT_ENTITYDBL | PEXT_ENTITYDBL2 | PEXT_FATNESS | PEXT_HEXEN2 | PEXT_HULLSIZE | PEXT_LIGHTSTYLECOL | PEXT_MODELDBL | PEXT_SCALE | PEXT_SETATTACHMENT | PEXT_SETVIEW | PEXT_SOUNDDBL | PEXT_SPAWNSTATIC2 | PEXT_TRANS;
#ifdef PEXT_VIEW2
demo.recorder.fteprotocolextensions |= PEXT_VIEW2;
#endif
demo.recorder.fteprotocolextensions2 = PEXT2_VOICECHAT | PEXT2_SETANGLEDELTA | PEXT2_PRYDONCURSOR | (pext_replacementdeltas.ival?PEXT2_REPLACEMENTDELTAS:0);
/*enable these, because we might as well (stat ones are always useful)*/
demo.recorder.zquake_extensions = Z_EXT_PM_TYPE | Z_EXT_PM_TYPE_NEW | Z_EXT_VIEWHEIGHT | Z_EXT_SERVERTIME | Z_EXT_PITCHLIMITS | Z_EXT_JOIN_OBSERVE | Z_EXT_VWEP;

View File

@ -2550,7 +2550,9 @@ qboolean SV_Physics (void)
PR_ExecuteProgram (svprogfuncs, EndFrameQC);
}
#ifdef NETPREPARSE
NPP_Flush(); //flush it just in case there was an error and we stopped preparsing. This is only really needed while debugging.
#endif
sv.world.physicstime += host_frametime;
}

View File

@ -1367,9 +1367,8 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
client->nextservertimeupdate = sv.physicstime;
*/
ent = client->edict;
#ifdef NQPROT
ent = client->edict;
if (progstype != PROG_QW)
{
if (ISQWCLIENT(client))
@ -1789,6 +1788,7 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf
else
#endif
{
#ifdef QUAKESTATS
statsf[STAT_HEALTH] = ent->v->health; //sorry, but mneh
statsi[STAT_WEAPONMODELI] = SV_ModelIndex(PR_GetString(svprogfuncs, ent->v->weaponmodel));
if ((unsigned)statsi[STAT_WEAPONMODELI] >= client->maxmodels)
@ -1822,7 +1822,9 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf
statsi[STAT_VIEWZOOM] = 255;
else
statsi[STAT_VIEWZOOM] = ent->xv->viewzoom*255;
#endif
#ifdef NQPROT
if (client->protocol == SCP_DARKPLACES7 || (client->fteprotocolextensions2 & PEXT2_PREDINFO))
{
float *statsfi;
@ -1850,6 +1852,7 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf
statsfi[STAT_MOVEVARS_AIRACCEL_QW] = 1;
statsfi[STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION] = sv_gravity.value;
}
#endif
SV_UpdateQCStats(ent, statsi, statss, statsf);
}

View File

@ -438,6 +438,7 @@ void SV_New_f (void)
host_client->prespawn_idx = 0;
}
#ifdef NQPROT
void SVNQ_New_f (void)
{
extern cvar_t coop;
@ -499,7 +500,6 @@ void SVNQ_New_f (void)
op = host_client->protocol;
switch(host_client->protocol)
{
#ifdef NQPROT
case SCP_NETQUAKE:
case SCP_PROQUAKE:
case SCP_FITZ666:
@ -545,7 +545,6 @@ void SVNQ_New_f (void)
maxplayers = 255;
protoname = "DPP7";
break;
#endif
default:
host_client->drop = true;
protoname = "?""?""?";
@ -635,7 +634,7 @@ void SVNQ_New_f (void)
host_client->netchan.nqunreliableonly = 2;
}
#endif
@ -1546,7 +1545,9 @@ void SVQW_Spawn_f (void)
client_t *client, *split;
edict_t *ent;
#ifdef QUAKESTATS
int secret_total, secret_found, monsters_total, monsters_found;
#endif
if (host_client->state != cs_connected)
{
@ -1664,11 +1665,15 @@ void SVQW_Spawn_f (void)
memset (split->statss, 0, sizeof(split->statss));
}
#ifdef QUAKESTATS
secret_total = pr_global_struct->total_secrets;
secret_found = pr_global_struct->found_secrets;
monsters_total = pr_global_struct->total_monsters;
monsters_found = pr_global_struct->killed_monsters;
#endif
}
#ifdef QUAKESTATS
ClientReliableWrite_Begin (host_client, svcqw_updatestatlong, 6);
ClientReliableWrite_Byte (host_client, STAT_TOTALSECRETS);
ClientReliableWrite_Long (host_client, secret_total);
@ -1684,6 +1689,8 @@ void SVQW_Spawn_f (void)
ClientReliableWrite_Begin (host_client, svcqw_updatestatlong, 6);
ClientReliableWrite_Byte (host_client, STAT_MONSTERS);
ClientReliableWrite_Long (host_client, monsters_found);
#endif
// get the client to check and download skins
// when that is completed, a begin command will be issued
ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
@ -3197,7 +3204,7 @@ void SV_SayOne_f (void)
if (Cmd_Argc () < 3)
return;
if ((host_client->penalties & BAN_MUTE) && !(host_client->penalties & BAN_DEAF))
if ((host_client->penalties & BAN_MUTE) && !(host_client->penalties & (BAN_DEAF|BAN_STEALTH)))
{
SV_ClientTPrintf(host_client, PRINT_CHAT, "You are muted\n");
return;
@ -3205,7 +3212,7 @@ void SV_SayOne_f (void)
while((to = SV_GetClientForString(Cmd_Argv(1), &clnum)))
{
if ((host_client->penalties & BAN_MUTE))
if ((host_client->penalties & BAN_MUTE) && to != host_client)
continue;
if (host_client->spectator)
{
@ -3348,7 +3355,7 @@ void SV_Say (qboolean team)
else
Q_snprintfz (text, sizeof(text), "%s: ", host_client->name);
if ((host_client->penalties & BAN_MUTE) && !(host_client->penalties & BAN_DEAF))
if ((host_client->penalties & BAN_MUTE) && !(host_client->penalties & (BAN_DEAF|BAN_STEALTH)))
{
SV_ClientTPrintf(host_client, PRINT_CHAT, "You cannot chat while muted\n");
return;
@ -3444,7 +3451,10 @@ void SV_Say (qboolean team)
continue;
}
else if (client->penalties & BAN_DEAF)
continue;
{
if (client != host_client || !(host_client->penalties & BAN_STEALTH))
continue;
}
cls |= 1 << j;
@ -4273,6 +4283,7 @@ void Cmd_Give_f (void)
v = atoi (Cmd_Argv(2));
SV_LogPlayer(host_client, "give cheat");
#ifdef QUAKESTATS
if (strlen(t) == 1 && (Cmd_Argc() == 3 || (*t>='0' && *t <= '9')))
{
switch (t[0])
@ -4307,7 +4318,9 @@ void Cmd_Give_f (void)
SV_TPrintToClient(host_client, PRINT_HIGH, "give: unknown item\n");
}
}
else if (svprogfuncs->EvaluateDebugString)
else
#endif
if (svprogfuncs->EvaluateDebugString)
{
if (developer.value < 2 && host_client->netchan.remote_address.type != NA_LOOPBACK) //we don't want clients doing nasty things... like setting movetype 3123
{

View File

@ -648,7 +648,7 @@ void SVQ2_BuildClientFrame (client_t *client)
clientcluster = CM_LeafCluster (sv.world.worldmodel, leafnum);
// calculate the visible areas
frame->areabytes = CM_WriteAreaBits (sv.world.worldmodel, frame->areabits, clientarea);
frame->areabytes = CM_WriteAreaBits (sv.world.worldmodel, frame->areabits, clientarea, false);
// grab the current player_state_t
frame->ps = clent->client->ps;

View File

@ -2090,7 +2090,6 @@ void SVQ3_WriteSnapshotToClient(client_t *client, sizebuf_t *msg)
static int clientNum;
static int clientarea;
static qbyte *areabits;
static qbyte *bitvector;
static int VARGS SVQ3_QsortEntityStates( const void *arg1, const void *arg2 )
@ -2115,7 +2114,7 @@ static int VARGS SVQ3_QsortEntityStates( const void *arg1, const void *arg2 )
}
static qboolean SVQ3_EntityIsVisible( q3sharedEntity_t *ent )
static qboolean SVQ3_EntityIsVisible(q3client_frame_t *snap, q3sharedEntity_t *ent)
{
q3serverEntity_t *sent;
int i;
@ -2173,11 +2172,11 @@ static qboolean SVQ3_EntityIsVisible( q3sharedEntity_t *ent )
sent = SENTITY_FOR_GENTITY( ent );
// check area
if (sent->areanum < 0 || !(areabits[sent->areanum >> 3] & (1 << (sent->areanum & 7))))
if (sent->areanum < 0 || !(snap->areabits[sent->areanum >> 3] & (1 << (sent->areanum & 7))))
{
// doors can legally straddle two areas, so
// we may need to check another one
if (sent->areanum2 < 0 || !(areabits[sent->areanum2 >> 3] & (1 << (sent->areanum2 & 7))))
if (sent->areanum2 < 0 || !(snap->areabits[sent->areanum2 >> 3] & (1 << (sent->areanum2 & 7))))
{
return false; // blocked by a door
}
@ -2289,6 +2288,7 @@ void SVQ3_BuildClientSnapshot( client_t *client )
q3playerState_t *ps;
int portalarea;
int i;
static qbyte pvsbuffer[(MAX_MAP_LEAFS+7)>>3];
if (!q3_snapshot_entities)
{
@ -2332,7 +2332,7 @@ void SVQ3_BuildClientSnapshot( client_t *client )
org[2] += ps->viewheight;
clientarea = CM_PointLeafnum(sv.world.worldmodel, org);
bitvector = sv.world.worldmodel->funcs.ClusterPVS(sv.world.worldmodel, sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, org), NULL, 0);
bitvector = sv.world.worldmodel->funcs.ClusterPVS(sv.world.worldmodel, CM_LeafCluster(sv.world.worldmodel, clientarea), pvsbuffer, sizeof(pvsbuffer));
clientarea = CM_LeafArea(sv.world.worldmodel, clientarea);
/*
if (client->areanum != clientarea)
@ -2343,11 +2343,10 @@ void SVQ3_BuildClientSnapshot( client_t *client )
*/
// calculate the visible areas
areabits = snap->areabits;
snap->areabytes = CM_WriteAreaBits(sv.world.worldmodel, areabits, clientarea);
snap->areabytes = CM_WriteAreaBits(sv.world.worldmodel, snap->areabits, clientarea, false);
// grab the current playerState_t
memcpy( &snap->ps, ps, sizeof( snap->ps ) );
memcpy(&snap->ps, ps, sizeof(snap->ps));
// build up the list of visible entities
snap->num_entities = 0;
@ -2356,38 +2355,43 @@ void SVQ3_BuildClientSnapshot( client_t *client )
if (svs.gametype == GT_QUAKE3)
{
// check for SVF_PORTAL entities first
for( i=0 ; i<numq3entities ; i++ )
for( i=0 ; i<numq3entities ; i++)
{
ent = GENTITY_FOR_NUM( i );
unsigned int c;
qbyte *merge;
ent = GENTITY_FOR_NUM(i);
if( ent == clent )
if(ent == clent )
continue;
if( !(ent->r.svFlags & SVF_PORTAL) )
if(!(ent->r.svFlags & SVF_PORTAL))
continue;
if( !SVQ3_EntityIsVisible( ent ) )
if(!SVQ3_EntityIsVisible(snap, ent))
continue;
// merge PVS if portal
portalarea = CM_PointLeafnum(sv.world.worldmodel, ent->s.origin2);
//merge pvs bits so we can see other ents through it
merge = sv.world.worldmodel->funcs.ClusterPVS(sv.world.worldmodel, CM_LeafCluster(sv.world.worldmodel, portalarea), NULL, 0);
c = (cl.worldmodel->numclusters+31)/32;
while (c-->0)
((int *)bitvector)[c] |= ((int *)merge)[c];
//and merge areas, so we can see the world too (client will calc its own pvs)
portalarea = CM_LeafArea(sv.world.worldmodel, portalarea);
// CM_MergePVS ( ent->s.origin2 );
// CM_MergeAreaBits( snap->areabits, portalarea );
CM_WriteAreaBits(sv.world.worldmodel, snap->areabits, portalarea, true);
}
// add all visible entities
for( i=0 ; i<numq3entities ; i++ )
for (i=0 ; i<numq3entities ; i++)
{
ent = GENTITY_FOR_NUM( i );
ent = GENTITY_FOR_NUM(i);
if (ent == clent)
if (ent == clent)
continue;
if( !SVQ3_EntityIsVisible( ent ) )
if (!SVQ3_EntityIsVisible(snap, ent))
continue;
if (ent->s.number != i)
{
if (ent->s.number != i)
{
Con_DPrintf( "FIXING ENT->S.NUMBER!!!\n" );
ent->s.number = i;
}

View File

@ -149,7 +149,7 @@ void SWRast_Sync(struct workqueue_s *wq);
qboolean SW_VID_Init(rendererstate_t *info, unsigned char *palette);
void SW_VID_DeInit(void);
qboolean SW_VID_ApplyGammaRamps (unsigned short *ramps);
char *SW_VID_GetRGBInfo(int prepad, int *truevidwidth, int *truevidheight);
char *SW_VID_GetRGBInfo(int *truevidwidth, int *truevidheight, enum uploadfmt *fmt);
void SW_VID_SetWindowCaption(char *msg);
void SW_VID_SwapBuffers(void);
void SW_VID_UpdateViewport(wqcom_t *com);

View File

@ -772,13 +772,13 @@ qboolean SW_VID_ApplyGammaRamps (unsigned short *ramps)
{
return false;
}
char *SW_VID_GetRGBInfo(int prepad, int *truevidwidth, int *truevidheight)
char *SW_VID_GetRGBInfo(int *truevidwidth, int *truevidheight, enum uploadfmt *fmt)
{
char *buf = NULL;
char *src, *dst;
int w, h;
buf = BZ_Malloc(prepad + (vid.pixelwidth * vid.pixelheight * 3));
dst = buf + prepad;
buf = BZ_Malloc((vid.pixelwidth * vid.pixelheight * 3));
dst = buf;
for (h = 0; h < vid.pixelheight; h++)
{
for (w = 0, src = (char*)screenbuffer + (h * vid.pixelwidth*4); w < vid.pixelwidth; w++, dst += 3, src += 4)
@ -790,6 +790,7 @@ char *SW_VID_GetRGBInfo(int prepad, int *truevidwidth, int *truevidheight)
}
*truevidwidth = vid.pixelwidth;
*truevidheight = vid.pixelheight;
*fmt = TF_BGR24;
return buf;
}
void SW_VID_SetWindowCaption(char *msg)