From 8241ed13be7469eefa4761128e771abbaed4f6dd Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 1 Sep 2015 04:45:15 +0000 Subject: [PATCH] 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 --- engine/Makefile | 8 ++ engine/client/cl_cam.c | 8 +- engine/client/cl_ents.c | 11 +- engine/client/cl_input.c | 9 +- engine/client/cl_main.c | 56 ++++++--- engine/client/cl_parse.c | 55 ++++++--- engine/client/cl_plugin.inc | 10 +- engine/client/cl_pred.c | 12 +- engine/client/cl_screen.c | 55 +++++++-- engine/client/cl_ui.c | 2 +- engine/client/client.h | 10 +- engine/client/console.c | 8 ++ engine/client/in_generic.c | 2 + engine/client/keys.c | 1 - engine/client/m_mp3.c | 65 +++++----- engine/client/m_options.c | 2 + engine/client/m_single.c | 2 +- engine/client/p_script.c | 6 + engine/client/pr_clcmd.c | 26 ++++ engine/client/pr_csqc.c | 40 +++++-- engine/client/pr_menu.c | 26 ---- engine/client/r_partset.c | 28 +++++ engine/client/r_surf.c | 2 +- engine/client/renderer.c | 14 ++- engine/client/sbar.c | 48 +++++--- engine/client/sbar.h | 22 +++- engine/client/snd_ov.c | 2 +- engine/client/sys_win.c | 5 +- engine/client/view.c | 35 ++++-- engine/client/zqtp.c | 53 +++++--- engine/common/bothdefs.h | 44 +++++-- engine/common/cmd.c | 1 + engine/common/com_mesh.c | 2 +- engine/common/com_phys_ode.c | 4 + engine/common/common.c | 2 + engine/common/gl_q2bsp.c | 24 ++-- engine/common/net_chan.c | 4 +- engine/common/plugin.c | 7 +- engine/common/pr_bgcmd.c | 33 ++++- engine/common/pr_common.h | 5 + engine/common/protocol.h | 9 +- engine/d3d/d3d_backend.c | 100 +++++++++++----- engine/dotnet2005/ftequake.vcproj | 2 +- engine/gl/gl_backend.c | 36 +++++- engine/gl/gl_model.h | 4 +- engine/gl/gl_rmain.c | 4 +- engine/gl/gl_shader.c | 16 ++- engine/gl/gl_vidnt.c | 20 ++++ engine/gl/shader.h | 6 +- engine/partcfgs/high.cfg | 28 +++++ engine/qclib/execloop.h | 125 ++++++++++++------- engine/qclib/initlib.c | 8 +- engine/qclib/pr_edict.c | 2 +- engine/qclib/pr_exec.c | 2 + engine/qclib/progslib.h | 14 ++- engine/qclib/qcc_pr_comp.c | 38 ++++++ engine/server/net_preparse.c | 71 ++++++----- engine/server/pr_cmds.c | 75 ++++++++---- engine/server/server.h | 9 +- engine/server/sv_ccmds.c | 193 ++++++++++++++---------------- engine/server/sv_ents.c | 7 +- engine/server/sv_init.c | 2 + engine/server/sv_main.c | 14 ++- engine/server/sv_mvd.c | 5 +- engine/server/sv_phys.c | 2 + engine/server/sv_send.c | 7 +- engine/server/sv_user.c | 29 +++-- engine/server/svq2_ents.c | 2 +- engine/server/svq3_game.c | 50 ++++---- engine/sw/sw.h | 2 +- engine/sw/sw_vidwin.c | 7 +- 71 files changed, 1132 insertions(+), 506 deletions(-) diff --git a/engine/Makefile b/engine/Makefile index 7a2f4b7ae..646dff764 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -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) diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index 4facaa541..d0d29992c 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -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(); diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 1ba8b2c43..e1df0aa43 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -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 } //====================================================================== diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index e43d08669..a194cce2e 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -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; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index ae1523664..3e608468e 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -29,7 +29,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include // 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 diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 8c2427c81..93b4e76bc 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -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; diff --git a/engine/client/cl_plugin.inc b/engine/client/cl_plugin.inc index 75885d815..7b2465412 100644 --- a/engine/client/cl_plugin.inc +++ b/engine/client/cl_plugin.inc @@ -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); diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index bf9ea8a6a..8cc055381 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -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) diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 34b689903..a0f37b7b3 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -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) diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index e8053c032..3e4b9df2f 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -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; diff --git a/engine/client/client.h b/engine/client/client.h index 06ac80377..91043cd18 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -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. diff --git a/engine/client/console.c b/engine/client/console.c index 61b11094b..3db6f4e38 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -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<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<completionline->length, (con->completionline->maxlength-con->completionline->length)*sizeof(maskedtext[0]), true); diff --git a/engine/client/in_generic.c b/engine/client/in_generic.c index d177dae8f..a4b4c265e 100644 --- a/engine/client/in_generic.c +++ b/engine/client/in_generic.c @@ -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) { diff --git a/engine/client/keys.c b/engine/client/keys.c index 904f7f2e2..e3651e763 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -2195,7 +2195,6 @@ qboolean Key_MouseShouldBeFree(void) return false; } -int Sbar_TranslateHudClick(void); /* =================== Key_Event diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 2e99ac51d..6872ee33c 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -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 } diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 8ed9e6b5e..73d253301 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -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); diff --git a/engine/client/m_single.c b/engine/client/m_single.c index 333816d92..7fb7cedd1 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -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); diff --git a/engine/client/p_script.c b/engine/client/p_script.c index aa8338016..fdbc5b18c 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -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++) { diff --git a/engine/client/pr_clcmd.c b/engine/client/pr_clcmd.c index 85f31bbd3..54be15159 100644 --- a/engine/client/pr_clcmd.c +++ b/engine/client/pr_clcmd.c @@ -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) { diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 1a182f20c..d9c47efc2 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -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 (); diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index b1ff0960e..0ddf694a9 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -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; diff --git a/engine/client/r_partset.c b/engine/client/r_partset.c index bda80061a..e96a8599b 100644 --- a/engine/client/r_partset.c +++ b/engine/client/r_partset.c @@ -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. diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 99c57681e..624c31d1d 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -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 diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 95eba677a..afb9a7ce2 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -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 ; irbottomcolor; } +#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= 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 diff --git a/engine/client/sbar.h b/engine/client/sbar.h index bc0a08449..75192f18d 100644 --- a/engine/client/sbar.h +++ b/engine/client/sbar.h @@ -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[]; diff --git a/engine/client/snd_ov.c b/engine/client/snd_ov.c index fb034a229..77b6db1e7 100644 --- a/engine/client/snd_ov.c +++ b/engine/client/snd_ov.c @@ -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; } diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 920e49355..ff26c2aee 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -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) diff --git a/engine/client/view.c b/engine/client/view.c index 224201afd..853fc4ee0 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -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 (); diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 81db9962b..fe6d4d97d 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -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 + diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 117cd003a..b2aeaa281 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -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 diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 579f3cd33..4838edd6e 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -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. diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 4b1df1dc1..8e85e9ba5 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -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; diff --git a/engine/common/com_phys_ode.c b/engine/common/com_phys_ode.c index 7c473dd9f..5b66267cb 100644 --- a/engine/common/com_phys_ode.c +++ b/engine/common/com_phys_ode.c @@ -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" diff --git a/engine/common/common.c b/engine/common/common.c index f4b4af7ac..4e9fd67bb 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -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; } diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index db411c15d..507d995de 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -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 ; inumareas ; i++) diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index b0f1878cf..bd51ab8a1 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -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; diff --git a/engine/common/plugin.c b/engine/common/plugin.c index d4544e68b..3e8612dbb 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -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; diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 8fbef4a69..063793bbb 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -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 diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 897670c66..0b6ba2505 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -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 { diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 4643b976a..8b21a452e 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -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 diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index a52974c3f..fca3b06de 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -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); diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index 9df993162..7e22c0dd6 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -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" diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 0b2084ecf..6c5da3b03 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -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); diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index f6658dfde..a359583fe 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -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); diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index c4fdd63ab..b8b435e2d 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -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); diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 9f30e290d..35e555a2b 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -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) diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index 6d113039b..fb84a306a 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -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; diff --git a/engine/gl/shader.h b/engine/gl/shader.h index fc793f7e4..af678ed54 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -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. diff --git a/engine/partcfgs/high.cfg b/engine/partcfgs/high.cfg index 162b5508b..c83516a55 100644 --- a/engine/partcfgs/high.cfg +++ b/engine/partcfgs/high.cfg @@ -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. diff --git a/engine/qclib/execloop.h b/engine/qclib/execloop.h index 74f05f04f..05f666e4c 100644 --- a/engine/qclib/execloop.h +++ b/engine/qclib/execloop.h @@ -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); diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index d3c4dfc01..e27ff2ad1 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -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 ; iinst.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; diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index bf3d8f2b3..2a5574183 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -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 diff --git a/engine/qclib/pr_exec.c b/engine/qclib/pr_exec.c index c5aa4c091..a55117589 100644 --- a/engine/qclib/pr_exec.c +++ b/engine/qclib/pr_exec.c @@ -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; diff --git a/engine/qclib/progslib.h b/engine/qclib/progslib.h index 64a13eae0..ff3a76264 100644 --- a/engine/qclib/progslib.h +++ b/engine/qclib/progslib.h @@ -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) diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index f726841f7..f2945cc4c 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -1,6 +1,7 @@ #if !defined(MINIMAL) && !defined(OMIT_QCC) #include "qcc.h" +#include //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) diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index 590a6f1ba..87da78bbc 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -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: diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 5980e0465..5bca042de 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -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}, diff --git a/engine/server/server.h b/engine/server/server.h index 8f4e908c6..b8cfe1798 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -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 - diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 3fa342943..6c8ce3aa1 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -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< [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<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<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); } diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 0aaf3c4e6..9cd2b2de4 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -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) diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index a35004815..46b60c701 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -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); diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 0b298031c..6b2cf5f0d 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -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"); diff --git a/engine/server/sv_mvd.c b/engine/server/sv_mvd.c index d34afce55..92fbe5bcf 100644 --- a/engine/server/sv_mvd.c +++ b/engine/server/sv_mvd.c @@ -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; diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 079027ace..0ea7b597c 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -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; } diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 73d41eca6..06be4f0bc 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -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); } diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index ebf24cc5f..82552686b 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -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 { diff --git a/engine/server/svq2_ents.c b/engine/server/svq2_ents.c index 99cd488b5..91ea0958c 100644 --- a/engine/server/svq2_ents.c +++ b/engine/server/svq2_ents.c @@ -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; diff --git a/engine/server/svq3_game.c b/engine/server/svq3_game.c index 99d2d133a..ef5e6db8a 100644 --- a/engine/server/svq3_game.c +++ b/engine/server/svq3_game.c @@ -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 ; ir.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 ; is.number != i) - { + if (ent->s.number != i) + { Con_DPrintf( "FIXING ENT->S.NUMBER!!!\n" ); ent->s.number = i; } diff --git a/engine/sw/sw.h b/engine/sw/sw.h index 315863904..cf70e38f7 100644 --- a/engine/sw/sw.h +++ b/engine/sw/sw.h @@ -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); diff --git a/engine/sw/sw_vidwin.c b/engine/sw/sw_vidwin.c index 4c518832d..5fc2e361b 100644 --- a/engine/sw/sw_vidwin.c +++ b/engine/sw/sw_vidwin.c @@ -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)