From b380421e42982650a974638a6f9c973cdcca24f4 Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 8 Sep 2020 05:11:09 +0000 Subject: [PATCH] Lets try using _LARGEFILE64_SOURCE in 32bit linux builds. Not that anyone will notice. Clarify the 'too many alternate clients' messages. Gamepad movement should respond to +speed. favour fte's nq protocols over dp ones when both are supported by the client, to boost compat with qss. try to generate proper utf-8 filenames from player/team names when recording mvds, instead of bad char encodings. Fix loading saved games with splitscreen enabled. pr_dumpplatform can now optionally filter symbols via some specific external files, adding deprecated tags for any symbol not also supported by DP and QSS. Rework CSQC globals to use macros, to ensure completeness and consistency. rework sv_csqcdebug to use special svcs. This should make it more robust. Fix some scary warnings when vid_reloading the vulkan renderer. Fix a possible segfault from opengl+rtlights. Mousewheel will now interact better with engine menus. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5757 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/Makefile | 5 + engine/client/cl_input.c | 12 +- engine/client/cl_main.c | 2 +- engine/client/cl_parse.c | 61 +- engine/client/cl_tent.c | 75 ++- engine/client/client.h | 7 +- engine/client/console.c | 629 ++++++++++----------- engine/client/fragstats.c | 4 +- engine/client/in_generic.c | 13 +- engine/client/keys.c | 13 +- engine/client/m_items.c | 69 ++- engine/client/pr_clcmd.c | 2 +- engine/client/pr_csqc.c | 500 ++++++----------- engine/client/pr_menu.c | 7 - engine/client/pr_skelobj.c | 6 + engine/client/renderer.c | 2 +- engine/client/sys_linux.c | 33 +- engine/common/bspfile.h | 30 +- engine/common/cmd.c | 2 +- engine/common/fs_stdio.c | 49 +- engine/common/log.c | 1 + engine/common/net_ssl_gnutls.c | 50 +- engine/common/pmove.c | 2 +- engine/common/pr_bgcmd.c | 24 +- engine/common/pr_common.h | 174 +++++- engine/common/protocol.h | 4 +- engine/gl/gl_heightmap.c | 7 +- engine/gl/gl_shader.c | 2 +- engine/gl/gl_vidcommon.c | 2 +- engine/gl/gl_vidlinuxglx.c | 19 +- engine/server/net_preparse.c | 133 +++-- engine/server/pr_cmds.c | 989 ++++++++++++++++++++------------- engine/server/progdefs.h | 4 +- engine/server/savegame.c | 23 +- engine/server/server.h | 2 +- engine/server/sv_ccmds.c | 2 +- engine/server/sv_ents.c | 5 +- engine/server/sv_init.c | 7 - engine/server/sv_main.c | 153 +++-- engine/server/sv_mvd.c | 40 +- engine/server/sv_user.c | 21 +- engine/server/world.c | 2 +- engine/vk/vk_init.c | 4 +- 43 files changed, 1913 insertions(+), 1278 deletions(-) diff --git a/engine/Makefile b/engine/Makefile index ed7249e02..443259f9d 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -1474,6 +1474,11 @@ ifneq (,$(findstring linux,$(FTE_TARGET))) CL_CFLAGS=-DMULTITHREAD -DDYNAMIC_SDL $(HAVE_EGL) $(HAVE_WAYLAND) -DX11QUAKE -DAUDIO_PULSE -DAUDIO_ALSA -DAUDIO_OSS -DAUDIO_SDL BASELDFLAGS+=-Wl,--warn-common + ifeq ($(BITS),32) + CL_CFLAGS+=-D_LARGEFILE64_SOURCE + SV_CFLAGS+=-D_LARGEFILE64_SOURCE + endif + QCC_DIR=linqcc$(BITS) NPFTE_OBJS=httpclient.o image.o sys_linux_threads.o sys_npfte.o sys_axfte.o sys_plugfte.o diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index e2de0e55e..61b386ee1 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -35,12 +35,12 @@ static cvar_t cl_movement = CVARD("cl_movement","1", "Specifies whether to send cvar_t cl_nodelta = CVAR("cl_nodelta","0"); cvar_t cl_c2sdupe = CVAR("cl_c2sdupe", "0"); -cvar_t cl_c2spps = CVAR("cl_c2spps", "0"); -cvar_t cl_c2sImpulseBackup = CVAR("cl_c2sImpulseBackup","3"); -cvar_t cl_netfps = CVAR("cl_netfps", "150"); -cvar_t cl_sparemsec = CVARC("cl_sparemsec", "10", CL_SpareMsec_Callback); -cvar_t cl_queueimpulses = CVAR("cl_queueimpulses", "0"); -cvar_t cl_smartjump = CVAR("cl_smartjump", "1"); +cvar_t cl_c2spps = CVARD("cl_c2spps", "0", "Reduces outgoing packet rates by dropping up to a third of outgoing packets."); +cvar_t cl_c2sImpulseBackup = CVARD("cl_c2sImpulseBackup","3", "Prevents the cl_c2spps setting from dropping redundant packets that contain impulses, in an attempt to keep impulses more reliable."); +cvar_t cl_netfps = CVARD("cl_netfps", "150", "Send up to this many packets to the server per second. The rate used is also limited by the server which usually forces a cap to this setting of 77. Low packet rates can result in extra extrapolation to try to hide the resulting latencies."); +cvar_t cl_sparemsec = CVARCD("cl_sparemsec", "10", CL_SpareMsec_Callback, "Allows the 'banking' of a little extra time, so that one slow frame will not delay the timing of the following frame so much."); +cvar_t cl_queueimpulses = CVARD("cl_queueimpulses", "0", "Queues unsent impulses instead of replacing them. This avoids the need for extra wait commands (and the timing issues of such commands), but potentially increases latency and can cause scripts to be desynced with regard to buttons and impulses."); +cvar_t cl_smartjump = CVARD("cl_smartjump", "1", "Makes the jump button act as +moveup when in water. This is typically quieter and faster."); cvar_t cl_iDrive = CVARFD("cl_iDrive", "1", CVAR_SEMICHEAT, "Effectively releases movement keys when the opposing key is pressed. This avoids dead-time when both keys are pressed. This can be emulated with various scripts, but that's messy."); cvar_t cl_run = CVARD("cl_run", "0", "Enables autorun, inverting the state of the +speed key."); cvar_t cl_fastaccel = CVARD("cl_fastaccel", "1", "Begin moving at full speed instantly, instead of waiting a frame or so."); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 10db7882b..a17b218a6 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -5064,7 +5064,7 @@ void CL_Init (void) Cmd_AddCommandD ("fog", CL_Fog_f, "fog "); Cmd_AddCommandD ("waterfog", CL_Fog_f, "waterfog "); - Cmd_AddCommandD ("skyroomfog", CL_Fog_f, "waterfog "); + Cmd_AddCommandD ("skyroomfog", CL_Fog_f, "skyroomfog "); Cmd_AddCommandD ("skygroup", CL_Skygroup_f, "Provides a way to associate a skybox name with a series of maps, so that the requested skybox will override on a per-map basis."); // // Windows commands diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 97e916b5e..88ddc902c 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -165,10 +165,10 @@ static const char *svc_qwstrings[] = "svcfte_updateentities", "svcfte_brushedit", "svcfte_updateseats", - "svcfte_setinfoblob", //89 - "NEW PROTOCOL(90)", - "NEW PROTOCOL(91)", - "NEW PROTOCOL(92)", + "svcfte_setinfoblob", //89 + "svcfte_cgamepacket_sized", //90 + "svcfte_temp_entity_sized", //91 + "svcfte_csqcentities_sized", //92 "NEW PROTOCOL(93)", "NEW PROTOCOL(94)", "NEW PROTOCOL(95)", @@ -287,7 +287,10 @@ static const char *svc_nqstrings[] = "nqsvcfte_updateentities", //86 "NEW PROTOCOL(87)", //87 "NEW PROTOCOL(88)", //88 - "svcfte_setinfoblob"//89 + "svcfte_setinfoblob", //89 + "svcfte_cgamepacket_sized", //90 + "svcfte_temp_entity_sized", //91 + "svcfte_csqcentities_sized", //92 }; #endif @@ -3356,8 +3359,8 @@ static void CLQW_ParseServerData (void) cl.allocated_client_slots = MSG_ReadByte(); if (cl.allocated_client_slots > MAX_CLIENTS) { + Con_Printf(CON_ERROR"Server has too many client slots (%u > %u)\n", cl.allocated_client_slots, MAX_CLIENTS); cl.allocated_client_slots = MAX_CLIENTS; - Host_EndGame("Server sent us too many alternate clients\n"); } /*parsing here is slightly different to allow us 255 max players instead of 127*/ @@ -3368,7 +3371,7 @@ static void CLQW_ParseServerData (void) cl.splitclients &= ~128; } if (cl.splitclients > MAX_SPLITS) - Host_EndGame("Server sent us too many alternate clients\n"); + Host_EndGame("Server sent us too many seats (%u > %u)\n", cl.splitclients, MAX_SPLITS); for (pnum = 0; pnum < cl.splitclients; pnum++) { cl.playerview[pnum].spectator = true; @@ -3387,7 +3390,7 @@ static void CLQW_ParseServerData (void) for (clnum = 0; ; clnum++) { if (clnum == MAX_SPLITS) - Host_EndGame("Server sent us too many alternate clients\n"); + Host_EndGame("Server sent us over %u seats\n", MAX_SPLITS); if (cls.z_ext & Z_EXT_VIEWHEIGHT) cl.playerview[pnum].viewheight = 0; cl.playerview[clnum].playernum = pnum; @@ -6871,7 +6874,7 @@ void CLQW_ParseServerMessage (void) int destsplit; vec3_t ang; float f; - qboolean csqcpacket = false; + qboolean suggestcsqcdebug = false; inframe_t *inf; extern vec3_t demoangles; unsigned int cmdstart; @@ -6971,7 +6974,7 @@ void CLQW_ParseServerMessage (void) { default: CL_DumpPacket(); - Host_EndGame ("CLQW_ParseServerMessage: Illegible server message (%i@%i)%s", cmd, msg_readcount-1, (!cl.csqcdebug && csqcpacket)?"\n'sv_csqcdebug 1' might aid in debugging this.":"" ); + Host_EndGame ("CLQW_ParseServerMessage: Illegible server message (%i@%i)%s", cmd, msg_readcount-1, (!cl.csqcdebug && suggestcsqcdebug)?"\n'sv_csqcdebug 1' might aid in debugging this.":"" ); return; case svc_time: @@ -7210,6 +7213,9 @@ void CLQW_ParseServerMessage (void) CL_ParseTEnt (); #endif break; + case svcfte_temp_entity_sized: + CL_ParseTEnt_Sized(); + break; case svcfte_customtempent: CL_ParseCustomTEnt(); break; @@ -7423,8 +7429,11 @@ void CLQW_ParseServerMessage (void) #ifdef CSQC_DAT case svcfte_csqcentities: - csqcpacket = true; - CSQC_ParseEntities(); + suggestcsqcdebug = true; + CSQC_ParseEntities(cl.csqcdebug); + break; + case svcfte_csqcentities_sized: + CSQC_ParseEntities(true); break; #endif case svcfte_precache: @@ -7441,14 +7450,21 @@ void CLQW_ParseServerMessage (void) CL_ParsePointParticles(true); break; + case svcfte_cgamepacket_sized: +#ifdef CSQC_DAT + if (CSQC_ParseGamePacket(destsplit, true)) + break; +#endif + Con_Printf("Unable to parse gamecode packet\n"); + break; case svcfte_cgamepacket: - csqcpacket = true; + suggestcsqcdebug = true; #ifdef HLCLIENT if (CLHL_ParseGamePacket()) break; #endif #ifdef CSQC_DAT - if (CSQC_ParseGamePacket(destsplit)) + if (CSQC_ParseGamePacket(destsplit, cl.csqcdebug)) break; #endif Con_Printf("Unable to parse gamecode packet\n"); @@ -8089,13 +8105,20 @@ void CLNQ_ParseServerMessage (void) CL_ParseBaselineDelta (); break; + case svcfte_cgamepacket_sized: +#ifdef CSQC_DAT + if (CSQC_ParseGamePacket(destsplit, true)) + break; +#endif + Con_Printf("Unable to parse gamecode packet\n"); + break; case svcfte_cgamepacket: #ifdef HLCLIENT if (CLHL_ParseGamePacket()) break; #endif #ifdef CSQC_DAT - if (CSQC_ParseGamePacket(destsplit)) + if (CSQC_ParseGamePacket(destsplit, cl.csqcdebug)) break; #endif Con_Printf("Unable to parse gamecode packet\n"); @@ -8332,6 +8355,9 @@ void CLNQ_ParseServerMessage (void) case svc_temp_entity: CL_ParseTEnt (true); break; + case svcfte_temp_entity_sized: + CL_ParseTEnt_Sized(); + break; case svc_particle: CLNQ_ParseParticleEffect (); @@ -8445,7 +8471,10 @@ void CLNQ_ParseServerMessage (void) #ifdef CSQC_DAT case svcdp_csqcentities: - CSQC_ParseEntities(); + CSQC_ParseEntities(false); + break; + case svcfte_csqcentities_sized: + CSQC_ParseEntities(true); break; #endif diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index d7dc7f402..dababa11b 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -1131,19 +1131,29 @@ void CL_ParseTEnt (void) if (cl_shownet.ival >= 2) { static char *te_names[] = { - "spike", "superspike", "qwgunshot", "qwexplosion", - "tarexplosion", "lightning1", "lightning2", "wizspike", - "knightspike", "lightning3", "lavasplash", "teleport", - "blood", "lightningblood", "bullet", "superbullet", //bullets deprecated - "neh_explosion3", "railtrail/neh_lightning4", "beam", "explosion2", - "nqexplosion", "nqgunshot", "?", "?", -#ifdef HEXEN2 - "h2lightsml", "h2chain", "h2sunstf1", "h2sunstf2", - "h2light", "h2cb", "h2ic", "h2gaze", - "h2famine", "h2partexp" -#endif + /* 0*/"spike", "superspike", "qwgunshot", "qwexplosion", + /* 4*/"tarexplosion", "lightning1", "lightning2", "wizspike", + /* 8*/"knightspike", "lightning3", "lavasplash", "teleport", + /*12*/"blood", "lightningblood", "bullet", "superbullet", //bullets deprecated + /*16*/"neh_explosion3", "railtrail", "beam", "explosion2", + /*20*/"nqexplosion", "nqgunshot", NULL, NULL, + /*24*/"h2lightsml", "h2chain", "h2sunstf1", "h2sunstf2", + /*28*/"h2light", "h2cb", "h2ic", "h2gaze", + /*32*/"h2famine", "h2partexp",NULL,NULL, + /*36*/NULL,NULL,NULL,NULL, + /*40*/NULL,NULL,NULL,NULL, + /*44*/NULL,NULL,NULL,NULL, + /*48*/NULL,NULL,"dpblood","dpspark" + /*52*/"dpbloodshower","dpexplosionrgb","dpparticlecube","dpparticlerain", + /*56*/"dpparticlesnow","dpgunshotquad","dpspikequad","dpsuperspikequad", + /*60*/NULL,NULL,NULL,NULL, + /*64*/NULL,NULL,NULL,NULL, + /*68*/NULL,NULL,"dpexplosionquad",NULL, + /*72*/"dpsmallflash","dpcustomflash","dpflamejet","dpplasmaburn", + /*76*/"dpteig3","dpsmoke","dpteibigexplosion","dpteiplasmahit", + /*80*/ }; - if (type < countof(te_names)) + if (type < countof(te_names) && te_names[type]) Con_Printf(" te_%s\n", te_names[type]); else Con_Printf(" te_unknown_%i\n", type); @@ -1891,6 +1901,47 @@ void CL_ParseTEnt (void) } } +void CL_ParseTEnt_Sized (void) +{ + unsigned short sz = MSG_ReadShort(); + int start = msg_readcount; + + for(;;) + { +#ifdef NQPROT + if (sz&0x8000) + { + sz&=~0x8000; + CL_ParseTEnt(true); + } + else + CL_ParseTEnt(false); +#else + CL_ParseTEnt(); +#endif + + if (msg_readcount < start + sz) + { //try to be more compatible with xonotic. + int next = MSG_ReadByte(); + if (next == svc_temp_entity) + continue; + msg_readcount--; + + Con_Printf("Sized temp_entity data too large (next byte %i, %i bytes unread)\n", next, (start+sz)-msg_readcount); + msg_readcount = start + sz; + return; + } + break; + } + + + if (msg_readcount != start + sz) + { + Con_Printf("Tempentity size did not match parsed size misread a gamecode packet (%i bytes too much)\n", msg_readcount - (start+sz)); + msg_readcount = start + sz; + } +} + void MSG_ReadPos (vec3_t pos); void MSG_ReadDir (vec3_t dir); typedef struct { diff --git a/engine/client/client.h b/engine/client/client.h index 782f481c0..20b99d658 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -786,7 +786,7 @@ typedef struct int protocol_qw; float gamespeed; - qboolean csqcdebug; + qboolean csqcdebug; //redundant, remove '*csqcdebug' serverinfo key. qboolean allowsendpacket; qboolean stillloading; // set when doing something slow, and the game is still loading. @@ -1216,6 +1216,7 @@ void CL_ParseTEnt (qboolean nqprot); #else void CL_ParseTEnt (void); #endif +void CL_ParseTEnt_Sized (void); void CL_UpdateTEnts (void); enum beamtype_e @@ -1472,7 +1473,7 @@ qboolean CSQC_StuffCmd(int lplayernum, char *cmd, char *cmdend); void CSQC_MapEntityEdited(int modelindex, int idx, const char *newe); //qboolean CSQC_LoadResource(char *resname, char *restype); qboolean CSQC_ParsePrint(char *message, int printlevel); -qboolean CSQC_ParseGamePacket(int seat); +qboolean CSQC_ParseGamePacket(int seat, qboolean sized); qboolean CSQC_CenterPrint(int seat, const char *cmd); void CSQC_ServerInfoChanged(void); void CSQC_PlayerInfoChanged(int player); @@ -1489,7 +1490,7 @@ qboolean CSQC_JoystickAxis(int axis, float value, unsigned int devid); qboolean CSQC_Accelerometer(float x, float y, float z); qboolean CSQC_Gyroscope(float x, float y, float z); int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation, float pitchmod, float timeofs, unsigned int flags); -void CSQC_ParseEntities(void); +void CSQC_ParseEntities(qboolean sized); const char *CSQC_GetExtraFieldInfo(void *went, char *out, size_t outsize); void CSQC_ResetTrails(void); diff --git a/engine/client/console.c b/engine/client/console.c index bc1846cdd..fe171d1bf 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -2636,6 +2636,322 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, float displayscrol void Draw_ExpandedString(float x, float y, conchar_t *str); +static void Con_DrawModelPreview(model_t *model, float x, float y, float w, float h) +{ + playerview_t pv; + entity_t ent; + vec3_t fwd, rgt, up; + vec3_t lightpos = {1, 1, 0}; + float transforms[12]; + float scale; + + if (R2D_Flush) + R2D_Flush(); + + memset(&pv, 0, sizeof(pv)); + + CL_DecayLights (); + CL_ClearEntityLists(); + V_ClearRefdef(&pv); + r_refdef.drawsbar = false; + V_CalcRefdef(&pv); + + r_refdef.grect.width = w; + r_refdef.grect.height = h; + r_refdef.grect.x = x; + r_refdef.grect.y = y; + r_refdef.time = realtime; + + r_refdef.flags = RDF_NOWORLDMODEL; + + r_refdef.afov = 60; + r_refdef.fov_x = 0; + r_refdef.fov_y = 0; + r_refdef.dirty |= RDFD_FOV; + + VectorClear(r_refdef.viewangles); + r_refdef.viewangles[0] = 20; +// r_refdef.viewangles[1] = realtime * 90; + AngleVectors(r_refdef.viewangles, fwd, rgt, up); + VectorScale(fwd, -64, r_refdef.vieworg); + + memset(&ent, 0, sizeof(ent)); + ent.model = model; + ent.scale = 1; + ent.angles[1] = realtime*90;//mods->yaw; +// ent.angles[0] = realtime*23.4;//mods->pitch; + ent.angles[0]*=r_meshpitch.value; + AngleVectors(ent.angles, ent.axis[0], ent.axis[1], ent.axis[2]); + ent.angles[0]*=r_meshpitch.value; + VectorInverse(ent.axis[1]); + + //ent.origin[2] -= (ent.model->maxs[2]-ent.model->mins[2]) * 0.5 + ent.model->mins[2]; + + ent.scale = 1; + scale = max(max(fabs(ent.model->maxs[0]-ent.model->mins[0]), fabs(ent.model->maxs[1]-ent.model->mins[1])), fabs(ent.model->maxs[2]-ent.model->mins[2])); + scale = scale?64.0/scale:1; + ent.origin[2] -= (ent.model->maxs[2]-ent.model->mins[2]) * 0.5 + ent.model->mins[2]; + Vector4Set(ent.shaderRGBAf, 1, 1, 1, 1); + VectorScale(ent.axis[0], scale, ent.axis[0]); + VectorScale(ent.axis[1], scale, ent.axis[1]); + VectorScale(ent.axis[2], scale, ent.axis[2]); + /*if (strstr(model->name, "player")) + { + ent.bottomcolour = genhsv(realtime*0.1 + 0, 1, 1); + ent.topcolour = genhsv(realtime*0.1 + 0.5, 1, 1); + } + else*/ + { + ent.topcolour = TOP_DEFAULT; + ent.bottomcolour = BOTTOM_DEFAULT; + } +// ent.fatness = sin(realtime)*5; + ent.playerindex = -1; + ent.skinnum = 0; + ent.shaderTime = 0;//realtime; + ent.framestate.g[FS_REG].lerpweight[0] = 1; +// ent.framestate.g[FS_REG].frame[0] = animationnum; + ent.framestate.g[FS_REG].frametime[0] = ent.framestate.g[FS_REG].frametime[1] = realtime; + ent.framestate.g[FS_REG].endbone = 0x7fffffff; +// ent.customskin = Mod_RegisterSkinFile(va("%s_0.skin", mods->modelname)); + + Vector4Set(ent.shaderRGBAf, 1,1,1,1); + VectorSet(ent.glowmod, 1,1,1); + ent.light_avg[0] = ent.light_avg[1] = ent.light_avg[2] = 0.66; + ent.light_range[0] = ent.light_range[1] = ent.light_range[2] = 0.33; + + V_ApplyRefdef(); + + if (ent.model->camerabone>0 && Mod_GetTag(ent.model, ent.model->camerabone, &ent.framestate, transforms)) + { + VectorClear(ent.origin); + ent.angles[0]*=r_meshpitch.value; + AngleVectors(ent.angles, ent.axis[0], ent.axis[1], ent.axis[2]); + ent.angles[0]*=r_meshpitch.value; + VectorInverse(ent.axis[1]); + scale = 1; + { + vec3_t fwd, up; + float camera[12], et[12] = { + ent.axis[0][0], ent.axis[1][0], ent.axis[2][0], ent.origin[0], + ent.axis[0][1], ent.axis[1][1], ent.axis[2][1], ent.origin[1], + ent.axis[0][2], ent.axis[1][2], ent.axis[2][2], ent.origin[2], + }; + + R_ConcatTransforms((void*)et, (void*)transforms, (void*)camera); + VectorSet(fwd, camera[2], camera[6], camera[10]); + VectorNegate(fwd, fwd); + VectorSet(up, camera[1], camera[5], camera[9]); + VectorSet(r_refdef.vieworg, camera[3], camera[7], camera[11]); + VectorAngles(fwd, up, r_refdef.viewangles, false); + } + } + else + { + ent.angles[1] = realtime*90;//mods->yaw; + ent.angles[0]*=r_meshpitch.value; + AngleVectors(ent.angles, ent.axis[0], ent.axis[1], ent.axis[2]); + ent.angles[0]*=r_meshpitch.value; + VectorScale(ent.axis[0], scale, ent.axis[0]); + VectorScale(ent.axis[1], -scale, ent.axis[1]); + VectorScale(ent.axis[2], scale, ent.axis[2]); + } + + ent.scale = scale; + + VectorNormalize(lightpos); + ent.light_dir[0] = DotProduct(lightpos, ent.axis[0]); + ent.light_dir[1] = DotProduct(lightpos, ent.axis[1]); + ent.light_dir[2] = DotProduct(lightpos, ent.axis[2]); + + ent.light_known = 2; + + V_AddEntity(&ent); + + R_RenderView(); +} + +static void Con_DrawMouseOver(console_t *mouseconsole) +{ + char *tiptext = NULL; + shader_t *shader = NULL; + model_t *model = NULL; + char *mouseover; + if (!mouseconsole->mouseover || !mouseconsole->mouseover(mouseconsole, &tiptext, &shader)) + { + mouseover = Con_CopyConsole(mouseconsole, false, true, true); + if (mouseover) + { + char *end = strstr(mouseover, "^]"); + char *info = strchr(mouseover, '\\'); + if (!info) + info = ""; + if (end) + *end = 0; +#ifdef PLUGINS + if (!Plug_ConsoleLinkMouseOver(mousecursor_x, mousecursor_y, mouseover+2, info)) +#endif + { + char *key; + key = Info_ValueForKey(info, "tipimg"); + if (*key) + { + char *fl = Info_ValueForKey(info, "tipimgtype"); + if (*fl) + shader = R_RegisterCustom(key, atoi(fl), NULL, NULL); + else + shader = R2D_SafeCachePic(key); + } + else + { + image_t *img = NULL; + key = Info_ValueForKey(info, "tiprawimg"); + if (*key) + { + img = Image_FindTexture(key, NULL, IF_NOREPLACE|IF_PREMULTIPLYALPHA|IF_TEXTYPE_ANY); + if (!img) + img = Image_FindTexture(key, NULL, IF_NOREPLACE|IF_TEXTYPE_ANY); + if (!img) + { + size_t fsize; + char *buf; + img = Image_CreateTexture(key, NULL, IF_NOREPLACE|IF_PREMULTIPLYALPHA|IF_TEXTYPE_ANY); + if ((buf = FS_LoadMallocFile (key, &fsize))) + Image_LoadTextureFromMemory(img, img->flags|IF_NOWORKER, key, key, buf, fsize); + } + } + + key = Info_ValueForKey(info, "tipimgptr"); + if (*key) + img = Image_TextureIsValid(strtoull(key, NULL, 0)); + if (img && img->status == TEX_LOADED) + { + if ((img->flags & IF_TEXTYPEMASK)==IF_TEXTYPE_CUBE) + { + shader = R_RegisterShader("tiprawimgcube", 0, "{\nprogram postproc_equirectangular\n{\nmap \"$cube:$reflectcube\"\n}\n}"); + shader->defaulttextures->reflectcube = img; + } + else if ((img->flags&IF_TEXTYPEMASK) == IF_TEXTYPE_2D) + { + shader = R2D_SafeCachePic("tiprawimg"); + shader->defaulttextures->base = img; + } + + if (shader) + { + shader->width = img->width; + shader->height = img->height; + if (shader->width > 320) + { + shader->height *= 320.0/shader->width; + shader->width = 320; + } + if (shader->height > 240) + { + shader->width *= 240.0/shader->height; + shader->height = 240; + } + } + } + else + shader = NULL; + key = Info_ValueForKey(info, "modelviewer"); + if (*key) + { + model = Mod_ForName(key, MLV_WARN); + if (model->loadstate != MLS_LOADED) + model = NULL; + } + } + tiptext = Info_ValueForKey(info, "tip"); + } + Z_Free(mouseover); + } + } + if ((tiptext && *tiptext) || shader || model) + { + //FIXME: draw a proper background. + //FIXME: support line breaks. + conchar_t buffer[2048], *starts[64], *ends[countof(starts)]; + int lines, i, px, py; + float tw, th; + float ih = 0, iw = 0; + float x = mousecursor_x+8; + float y = mousecursor_y+8; + + Font_BeginString(font_console, x, y, &px, &py); + lines = Font_LineBreaks(buffer, COM_ParseFunString(CON_WHITEMASK, tiptext, buffer, sizeof(buffer), false), (256.0 * vid.pixelwidth) / vid.width, countof(starts), starts, ends); + th = (Font_CharHeight()*lines * vid.height) / vid.pixelheight; + + if (model) + { + iw = 128; + ih = 128; + } + else if (shader) + { + int w, h; + if (R_GetShaderSizes(shader, &w, &h, false) >= 0) + { + iw = w; + ih = h; + } + else + shader = NULL; + } + if (iw > (vid.width/4.0)) + { + ih *= (vid.width/4.0)/iw; + iw *= (vid.width/4.0)/iw; + } + if (ih > (vid.height/4.0)) + { + iw *= (vid.width/4.0)/ih; + ih *= (vid.width/4.0)/ih; + } + + if (x + iw/2 + 8 + 256 > vid.width) + x = vid.width - (iw/2 + 8 + 256); + if (x < iw/2) + x = iw/2; + x += iw/2 + 8; + + if (y+max(th, ih) > vid.height) + y = mousecursor_y - 8 - max(th, ih); + if (y < 0) + y = 0; + + Font_BeginString(font_console, x, y + (max(th, ih) - th)/2, &px, &py); + for (i = 0, tw = 0; i < lines; i++) + { + int lw = Font_LineWidth(starts[i], ends[i]); + if (lw > tw) + tw = lw; + } + tw *= (float)vid.width / vid.pixelwidth; + Font_EndString(font_console); + R2D_ImageColours(0, 0, 0, .75); + R2D_FillBlock(x, y + (max(th, ih) - th)/2, tw, th); + R2D_ImageColours(1, 1, 1, 1); + Font_BeginString(font_console, x, y + (max(th, ih) - th)/2, &px, &py); + for (i = 0; i < lines; i++) + { + Font_LineDraw(px, py, starts[i], ends[i]); + py += Font_CharHeight(); + } + Font_EndString(font_console); + + if (model) + Con_DrawModelPreview(model, x-8-iw, y+((th>ih)?(th-ih)/2:0), iw, ih); + if (shader) + { + if (th > ih) + y += (th-ih)/2; + R2D_Image(x-8-iw, y, iw, ih, 0, 0, 1, 1, shader); + } + } +} + /* ================ Con_DrawConsole @@ -2923,318 +3239,7 @@ void Con_DrawConsole (int lines, qboolean noback) mouseconsole = con_mouseover?con_mouseover:NULL; if (mouseconsole && mouseconsole->selstartline) - { - char *tiptext = NULL; - shader_t *shader = NULL; - model_t *model = NULL; - char *mouseover; - if (!mouseconsole->mouseover || !mouseconsole->mouseover(mouseconsole, &tiptext, &shader)) - { - mouseover = Con_CopyConsole(mouseconsole, false, true, true); - if (mouseover) - { - char *end = strstr(mouseover, "^]"); - char *info = strchr(mouseover, '\\'); - if (!info) - info = ""; - if (end) - *end = 0; - #ifdef PLUGINS - if (!Plug_ConsoleLinkMouseOver(mousecursor_x, mousecursor_y, mouseover+2, info)) - #endif - { - char *key; - key = Info_ValueForKey(info, "tipimg"); - if (*key) - { - char *fl = Info_ValueForKey(info, "tipimgtype"); - if (*fl) - shader = R_RegisterCustom(key, atoi(fl), NULL, NULL); - else - shader = R2D_SafeCachePic(key); - } - else - { - image_t *img = NULL; - key = Info_ValueForKey(info, "tiprawimg"); - if (*key) - { - img = Image_FindTexture(key, NULL, IF_NOREPLACE|IF_PREMULTIPLYALPHA|IF_TEXTYPE_ANY); - if (!img) - img = Image_FindTexture(key, NULL, IF_NOREPLACE|IF_TEXTYPE_ANY); - if (!img) - { - size_t fsize; - char *buf; - img = Image_CreateTexture(key, NULL, IF_NOREPLACE|IF_PREMULTIPLYALPHA|IF_TEXTYPE_ANY); - if ((buf = FS_LoadMallocFile (key, &fsize))) - Image_LoadTextureFromMemory(img, img->flags|IF_NOWORKER, key, key, buf, fsize); - } - } - - key = Info_ValueForKey(info, "tipimgptr"); - if (*key) - img = Image_TextureIsValid(strtoull(key, NULL, 0)); - if (img && img->status == TEX_LOADED) - { - if ((img->flags & IF_TEXTYPEMASK)==IF_TEXTYPE_CUBE) - { - shader = R_RegisterShader("tiprawimgcube", 0, "{\nprogram postproc_equirectangular\n{\nmap \"$cube:$reflectcube\"\n}\n}"); - shader->defaulttextures->reflectcube = img; - } - else if ((img->flags&IF_TEXTYPEMASK) == IF_TEXTYPE_2D) - { - shader = R2D_SafeCachePic("tiprawimg"); - shader->defaulttextures->base = img; - } - - if (shader) - { - shader->width = img->width; - shader->height = img->height; - if (shader->width > 320) - { - shader->height *= 320.0/shader->width; - shader->width = 320; - } - if (shader->height > 240) - { - shader->width *= 240.0/shader->height; - shader->height = 240; - } - } - } - else - shader = NULL; - key = Info_ValueForKey(info, "modelviewer"); - if (*key) - { - model = Mod_ForName(key, MLV_WARN); - if (model->loadstate != MLS_LOADED) - model = NULL; - } - } - tiptext = Info_ValueForKey(info, "tip"); - } - Z_Free(mouseover); - } - } - if ((tiptext && *tiptext) || shader || model) - { - //FIXME: draw a proper background. - //FIXME: support line breaks. - conchar_t buffer[2048], *starts[64], *ends[countof(starts)]; - int lines, i, px, py; - float tw, th; - float ih = 0, iw = 0; - float x = mousecursor_x+8; - float y = mousecursor_y+8; - - Font_BeginString(font_console, x, y, &px, &py); - lines = Font_LineBreaks(buffer, COM_ParseFunString(CON_WHITEMASK, tiptext, buffer, sizeof(buffer), false), (256.0 * vid.pixelwidth) / vid.width, countof(starts), starts, ends); - th = (Font_CharHeight()*lines * vid.height) / vid.pixelheight; - - if (model) - { - iw = 128; - ih = 128; - } - else if (shader) - { - int w, h; - if (R_GetShaderSizes(shader, &w, &h, false) >= 0) - { - iw = w; - ih = h; - } - else - shader = NULL; - } - if (iw > (vid.width/4.0)) - { - ih *= (vid.width/4.0)/iw; - iw *= (vid.width/4.0)/iw; - } - if (ih > (vid.height/4.0)) - { - iw *= (vid.width/4.0)/ih; - ih *= (vid.width/4.0)/ih; - } - - if (x + iw/2 + 8 + 256 > vid.width) - x = vid.width - (iw/2 + 8 + 256); - if (x < iw/2) - x = iw/2; - x += iw/2 + 8; - - if (y+max(th, ih) > vid.height) - y = mousecursor_y - 8 - max(th, ih); - if (y < 0) - y = 0; - - Font_BeginString(font_console, x, y + (max(th, ih) - th)/2, &px, &py); - for (i = 0, tw = 0; i < lines; i++) - { - int lw = Font_LineWidth(starts[i], ends[i]); - if (lw > tw) - tw = lw; - } - tw *= (float)vid.width / vid.pixelwidth; - Font_EndString(font_console); - R2D_ImageColours(0, 0, 0, .75); - R2D_FillBlock(x, y + (max(th, ih) - th)/2, tw, th); - R2D_ImageColours(1, 1, 1, 1); - Font_BeginString(font_console, x, y + (max(th, ih) - th)/2, &px, &py); - for (i = 0; i < lines; i++) - { - Font_LineDraw(px, py, starts[i], ends[i]); - py += Font_CharHeight(); - } - Font_EndString(font_console); - - if (model) - { - playerview_t pv; - entity_t ent; - vec3_t fwd, rgt, up; - vec3_t lightpos = {1, 1, 0}; - float transforms[12]; - float scale; - - if (R2D_Flush) - R2D_Flush(); - - memset(&pv, 0, sizeof(pv)); - - CL_DecayLights (); - CL_ClearEntityLists(); - V_ClearRefdef(&pv); - r_refdef.drawsbar = false; - V_CalcRefdef(&pv); - - r_refdef.grect.width = iw; - r_refdef.grect.height = ih; - r_refdef.grect.x = x-8-iw; - r_refdef.grect.y = y+((th>ih)?(th-ih)/2:0); - r_refdef.time = realtime; - - r_refdef.flags = RDF_NOWORLDMODEL; - - r_refdef.afov = 60; - r_refdef.fov_x = 0; - r_refdef.fov_y = 0; - r_refdef.dirty |= RDFD_FOV; - - VectorClear(r_refdef.viewangles); - r_refdef.viewangles[0] = 20; - // r_refdef.viewangles[1] = realtime * 90; - AngleVectors(r_refdef.viewangles, fwd, rgt, up); - VectorScale(fwd, -64, r_refdef.vieworg); - - memset(&ent, 0, sizeof(ent)); - ent.scale = 1; - ent.angles[1] = realtime*90;//mods->yaw; - // ent.angles[0] = realtime*23.4;//mods->pitch; - ent.angles[0]*=r_meshpitch.value; - AngleVectors(ent.angles, ent.axis[0], ent.axis[1], ent.axis[2]); - ent.angles[0]*=r_meshpitch.value; - VectorInverse(ent.axis[1]); - - ent.model = model; - if (!ent.model) - return; //panic! - //ent.origin[2] -= (ent.model->maxs[2]-ent.model->mins[2]) * 0.5 + ent.model->mins[2]; - - ent.scale = 1; - scale = max(max(fabs(ent.model->maxs[0]-ent.model->mins[0]), fabs(ent.model->maxs[1]-ent.model->mins[1])), fabs(ent.model->maxs[2]-ent.model->mins[2])); - scale = scale?64.0/scale:1; - ent.origin[2] -= (ent.model->maxs[2]-ent.model->mins[2]) * 0.5 + ent.model->mins[2]; - Vector4Set(ent.shaderRGBAf, 1, 1, 1, 1); - VectorScale(ent.axis[0], scale, ent.axis[0]); - VectorScale(ent.axis[1], scale, ent.axis[1]); - VectorScale(ent.axis[2], scale, ent.axis[2]); - /*if (strstr(model->name, "player")) - { - ent.bottomcolour = genhsv(realtime*0.1 + 0, 1, 1); - ent.topcolour = genhsv(realtime*0.1 + 0.5, 1, 1); - } - else*/ - { - ent.topcolour = TOP_DEFAULT; - ent.bottomcolour = BOTTOM_DEFAULT; - } - // ent.fatness = sin(realtime)*5; - ent.playerindex = -1; - ent.skinnum = 0; - ent.shaderTime = 0;//realtime; - ent.framestate.g[FS_REG].lerpweight[0] = 1; -// ent.framestate.g[FS_REG].frame[0] = animationnum; - ent.framestate.g[FS_REG].frametime[0] = ent.framestate.g[FS_REG].frametime[1] = realtime; - ent.framestate.g[FS_REG].endbone = 0x7fffffff; -// ent.customskin = Mod_RegisterSkinFile(va("%s_0.skin", mods->modelname)); - - VectorSet(ent.glowmod, 1,1,1); - ent.light_avg[0] = ent.light_avg[1] = ent.light_avg[2] = 0.66; - ent.light_range[0] = ent.light_range[1] = ent.light_range[2] = 0.33; - - V_ApplyRefdef(); - - if (ent.model->camerabone>0 && Mod_GetTag(ent.model, ent.model->camerabone, &ent.framestate, transforms)) - { - VectorClear(ent.origin); - ent.angles[0]*=r_meshpitch.value; - AngleVectors(ent.angles, ent.axis[0], ent.axis[1], ent.axis[2]); - ent.angles[0]*=r_meshpitch.value; - VectorInverse(ent.axis[1]); - scale = 1; - { - vec3_t fwd, up; - float camera[12], et[12] = { - ent.axis[0][0], ent.axis[1][0], ent.axis[2][0], ent.origin[0], - ent.axis[0][1], ent.axis[1][1], ent.axis[2][1], ent.origin[1], - ent.axis[0][2], ent.axis[1][2], ent.axis[2][2], ent.origin[2], - }; - - R_ConcatTransforms((void*)et, (void*)transforms, (void*)camera); - VectorSet(fwd, camera[2], camera[6], camera[10]); - VectorNegate(fwd, fwd); - VectorSet(up, camera[1], camera[5], camera[9]); - VectorSet(r_refdef.vieworg, camera[3], camera[7], camera[11]); - VectorAngles(fwd, up, r_refdef.viewangles, false); - } - } - else - { - ent.angles[1] = realtime*90;//mods->yaw; - ent.angles[0]*=r_meshpitch.value; - AngleVectors(ent.angles, ent.axis[0], ent.axis[1], ent.axis[2]); - ent.angles[0]*=r_meshpitch.value; - VectorScale(ent.axis[0], scale, ent.axis[0]); - VectorScale(ent.axis[1], -scale, ent.axis[1]); - VectorScale(ent.axis[2], scale, ent.axis[2]); - } - - ent.scale = scale; - - VectorNormalize(lightpos); - ent.light_dir[0] = DotProduct(lightpos, ent.axis[0]); - ent.light_dir[1] = DotProduct(lightpos, ent.axis[1]); - ent.light_dir[2] = DotProduct(lightpos, ent.axis[2]); - - ent.light_known = 2; - - V_AddEntity(&ent); - - R_RenderView(); - } - if (shader) - { - if (th > ih) - y += (th-ih)/2; - R2D_Image(x-8-iw, y, iw, ih, 0, 0, 1, 1, shader); - } - } - } + Con_DrawMouseOver(mouseconsole); } void Con_DrawOneConsole(console_t *con, qboolean focused, struct font_s *font, float fx, float fy, float fsx, float fsy, float lineagelimit) diff --git a/engine/client/fragstats.c b/engine/client/fragstats.c index 7455493df..91b1b7e01 100644 --- a/engine/client/fragstats.c +++ b/engine/client/fragstats.c @@ -630,10 +630,8 @@ static void Stats_LoadFragFile(char *name) Con_DPrintf("Loaded %s\n", filename); oend = 1; - for (;*file;) + for (;oend;) { - if (!oend) - break; for (end = file; *end && *end != '\n'; end++) ; oend = *end; diff --git a/engine/client/in_generic.c b/engine/client/in_generic.c index 6cd947d24..85e5166d2 100644 --- a/engine/client/in_generic.c +++ b/engine/client/in_generic.c @@ -943,14 +943,18 @@ void IN_MoveJoystick(struct joy_s *joy, float *movements, int pnum, float framet mag = pow(mag, joy_exponent.value); jlook[0] *= mag; jlook[1] *= mag; + mag = joydeadzone(fabs(jlook[2]), joy_anglethreshold[2].value); + mag = pow(mag, joy_exponent.value); jlook[2] *= mag; mag = joydeadzone(sqrt(jstrafe[0]*jstrafe[0] + jstrafe[1]*jstrafe[1]), sqrt(joy_movethreshold[0].value*joy_movethreshold[0].value + joy_movethreshold[1].value*joy_movethreshold[1].value)); mag = pow(mag, joy_exponent.value); jstrafe[0] *= mag; jstrafe[1] *= mag; + mag = joydeadzone(fabs(jstrafe[2]), joy_movethreshold[2].value); + mag = pow(mag, joy_exponent.value); jstrafe[2] *= mag; } else @@ -992,9 +996,12 @@ void IN_MoveJoystick(struct joy_s *joy, float *movements, int pnum, float framet V_StopPitchDrift (&cl.playerview[pnum]); //movement - movements[0] += joy_movesens[0].value * cl_forwardspeed.value * jstrafe[0]; - movements[1] += joy_movesens[1].value * cl_sidespeed.value * jstrafe[1]; - movements[2] += joy_movesens[2].value * cl_upspeed.value * jstrafe[2]; + mag = 1; + if ((in_speed.state[pnum] & 1) ^ cl_run.ival) + mag *= cl_movespeedkey.value; + movements[0] += joy_movesens[0].value * mag*cl_forwardspeed.value * jstrafe[0]; + movements[1] += joy_movesens[1].value * mag*cl_sidespeed.value * jstrafe[1]; + movements[2] += joy_movesens[2].value * mag*cl_upspeed.value * jstrafe[2]; } void IN_Move (float *movements, int pnum, float frametime) diff --git a/engine/client/keys.c b/engine/client/keys.c index 69abfd984..b8e1b567e 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -348,7 +348,7 @@ keyname_t keynames[] = #if defined(CSQC_DAT) || defined(MENU_DAT) int MP_TranslateFTEtoQCCodes(int code); -void Key_PrintQCDefines(vfsfile_t *f) +void Key_PrintQCDefines(vfsfile_t *f, qboolean defines) { int i, j; for (i = 0; keynames[i].name; i++) @@ -357,7 +357,12 @@ void Key_PrintQCDefines(vfsfile_t *f) if (keynames[j].keynum == keynames[i].keynum) break; if (j == i) - VFS_PRINTF(f, "#define K_%s\t%i\n", keynames[i].name, MP_TranslateFTEtoQCCodes(keynames[j].keynum)); + { + if (defines) + VFS_PRINTF(f, "#define K_%s\t%i\n", keynames[i].name, MP_TranslateFTEtoQCCodes(keynames[j].keynum)); + else + VFS_PRINTF(f, "const float K_%s = %i;\n", keynames[i].name, MP_TranslateFTEtoQCCodes(keynames[j].keynum)); + } } } #endif @@ -3199,10 +3204,10 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down //these may be redefined later... case K_GP_LEFT_SHOULDER: dc = "impulse 12"; goto defaultedbind; //matches QS's default.cfg case K_GP_RIGHT_SHOULDER: dc = "impulse 10"; goto defaultedbind; //matches QS's default.cfg - case K_GP_LEFT_TRIGGER: dc = "+jump"; goto defaultedbind; //matches QS's default.cfg + case K_GP_LEFT_TRIGGER: dc = "+button3"; goto defaultedbind; //matches QS's default.cfg case K_GP_RIGHT_TRIGGER: dc = "+attack"; goto defaultedbind; //matches QS's default.cfg case K_GP_START: dc = "togglemenu"; goto defaultedbind; - case K_GP_A: dc = "+button3"; goto defaultedbind; + case K_GP_A: dc = "+jump"; goto defaultedbind; case K_GP_B: dc = "+button4"; goto defaultedbind; case K_GP_X: dc = "+button5"; goto defaultedbind; case K_GP_Y: dc = "+button6"; goto defaultedbind; diff --git a/engine/client/m_items.c b/engine/client/m_items.c index 04049c2c7..5868d90be 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -480,6 +480,8 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, emenu_t *men int pw,ph; int framescroll = 0; + menuframe_t *framescroller = NULL; + if (option && option->common.type == mt_box && !option->common.ishidden) { //FIXME: why is this here? why is this special? Draw_ApproxTextBox(xpos+option->common.posx, ypos+option->common.posy, option->box.width, option->box.height); @@ -491,6 +493,22 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, emenu_t *men if (option->common.ishidden) continue; + if (framescroller && option == menu->selecteditem) + { + if (ypos+option->common.posy < framescroller->common.posy) + { + framescroller->frac -= 0.1; + if (framescroller->frac < 0) + framescroller->frac = 0; + } + else if (ypos+option->common.posy+option->common.height > framescroller->common.posy+framescroller->common.height) + { + framescroller->frac += 0.1; + if (framescroller->frac > 1) + framescroller->frac = 1; + } + } + if (&menu->menu == topmenu && menu->mouseitem == option && option->common.type != mt_frameend) { float alphamax = 0.5, alphamin = 0.2; @@ -565,6 +583,8 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, emenu_t *men if (R2D_Flush) R2D_Flush(); BE_Scissor(NULL); + + framescroller = NULL; break; case mt_frameend: { @@ -606,8 +626,9 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, emenu_t *men srect.y = (1-srect.y) - srect.height; BE_Scissor(&srect); - framescroll += option->frame.frac * maxy; - ypos -= option->frame.frac * maxy; + framescroller = &option->frame; + framescroll += framescroller->frac * maxy; + ypos -= framescroller->frac * maxy; } } break; @@ -1995,6 +2016,7 @@ void M_Complex_Key(emenu_t *currentmenu, int key, int unicode) case K_DOWNARROW: case K_KP_DOWNARROW: case K_GP_DPAD_DOWN: + godown: currentmenu->selecteditem = M_NextSelectableItem(currentmenu, currentmenu->selecteditem); if (currentmenu->selecteditem) @@ -2013,6 +2035,7 @@ void M_Complex_Key(emenu_t *currentmenu, int key, int unicode) case K_UPARROW: case K_KP_UPARROW: case K_GP_DPAD_UP: + goup: currentmenu->selecteditem = M_PrevSelectableItem(currentmenu, currentmenu->selecteditem); if (currentmenu->selecteditem) @@ -2029,6 +2052,46 @@ void M_Complex_Key(emenu_t *currentmenu, int key, int unicode) } break; + case K_MWHEELUP: + case K_MWHEELDOWN: + if (currentmenu->mouseitem) + { + qboolean handled = false; + switch(currentmenu->mouseitem->common.type) + { + case mt_combo: + if (mousecursor_x >= currentmenu->xpos + currentmenu->mouseitem->common.posx + currentmenu->mouseitem->combo.captionwidth + 3*8) + { + MC_Combo_Key(¤tmenu->mouseitem->combo, key); + handled = true; + } + break; + case mt_checkbox: + if (mousecursor_x >= currentmenu->xpos + currentmenu->mouseitem->common.posx + currentmenu->mouseitem->check.textwidth + 3*8) + { + MC_CheckBox_Key(¤tmenu->mouseitem->check, currentmenu, key); + handled = true; + } + break; + case mt_custom: + if (currentmenu->mouseitem->custom.key) + handled = currentmenu->mouseitem->custom.key(¤tmenu->mouseitem->custom, currentmenu, key, unicode); + break; + default: + break; + } + + if (handled) + { + currentmenu->selecteditem = currentmenu->mouseitem; + if (currentmenu->cursoritem) + currentmenu->cursoritem->common.posy = currentmenu->selecteditem->common.posy; + break; + } + else if (key == K_MWHEELUP) + goto goup; + else goto godown; + } case K_MOUSE1: case K_MOUSE3: case K_MOUSE4: @@ -2038,8 +2101,6 @@ void M_Complex_Key(emenu_t *currentmenu, int key, int unicode) case K_MOUSE8: case K_MOUSE9: case K_MOUSE10: - case K_MWHEELUP: - case K_MWHEELDOWN: if (!currentmenu->mouseitem) break; if (currentmenu->mouseitem && currentmenu->selecteditem != currentmenu->mouseitem) diff --git a/engine/client/pr_clcmd.c b/engine/client/pr_clcmd.c index e68afa04e..51d630798 100644 --- a/engine/client/pr_clcmd.c +++ b/engine/client/pr_clcmd.c @@ -1171,7 +1171,7 @@ void QCBUILTIN PF_cl_getgamedirinfo(pubprogfuncs_t *prinst, struct globalvars_s RETURN_TSTRING(mod->manifest->defaultexec); break; case GGDI_LOADCOMMAND: //load command - RETURN_TSTRING(va("fs_changegame %u", (unsigned int)diridx+1u)); + RETURN_TSTRING(va("fs_changegame %u\n", (unsigned int)diridx+1u)); break; case GGDI_ICON: //icon { diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 5148a3c88..d24fac2ea 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -101,143 +101,14 @@ extern sfx_t *cl_sfx_ric2; extern sfx_t *cl_sfx_ric3; extern sfx_t *cl_sfx_r_exp3; -#define ENDLIST //clarifies \ in list macros. -#ifndef HAVE_LEGACY -#define legacycsqcglobals -#else -#define legacycsqcglobals \ - globalstring(trace_dphittexturename, "trace_dphittexturename"); /*for dp compat*/ \ - globalfloat(trace_dpstartcontents, "trace_dpstartcontents"); /*for dp compat*/ \ - globalfloat(trace_dphitcontents, "trace_dphitcontents"); /*for dp compat*/ \ - globalfloat(trace_dphitq3surfaceflags, "trace_dphitq3surfaceflags"); /*for dp compat*/ \ - globalfloat(trace_surfaceflagsf, "trace_surfaceflagsf"); /*float written by traceline, for mods that lack ints*/ \ - globalfloat(trace_endcontentsf, "trace_endcontentsf"); /*float written by traceline EXT_CSQC_1, for mods that lack ints*/ \ - ENDLIST -#endif - -//If I do it like this, I'll never forget to register something... -#define csqcglobals \ - globalfunction(init_function, "CSQC_Init"); \ - globalfunction(worldloaded, "CSQC_WorldLoaded"); \ - globalfunction(shutdown_function, "CSQC_Shutdown"); \ - globalfunction(f_updateview, "CSQC_UpdateView"); \ - globalfunction(f_updateviewloading, "CSQC_UpdateViewLoading"); \ - globalfunction(f_drawhud, "CSQC_DrawHud");/*simple csqc*/ \ - globalfunction(f_drawscores, "CSQC_DrawScores");/*simple csqc*/ \ - globalfunction(parse_stuffcmd, "CSQC_Parse_StuffCmd"); \ - globalfunction(parse_centerprint, "CSQC_Parse_CenterPrint"); \ - globalfunction(parse_print, "CSQC_Parse_Print"); \ - globalfunction(parse_event, "CSQC_Parse_Event"); \ - globalfunction(parse_damage, "CSQC_Parse_Damage"); \ - globalfunction(parse_setangles, "CSQC_Parse_SetAngles"); \ - globalfunction(playerinfochanged, "CSQC_PlayerInfoChanged"); \ - globalfunction(serverinfochanged, "CSQC_ServerInfoChanged"); \ - globalfunction(input_event, "CSQC_InputEvent"); \ - globalfunction(input_frame, "CSQC_Input_Frame");/*EXT_CSQC_1*/ \ - globalfunction(rendererrestarted, "CSQC_RendererRestarted"); \ - globalfunction(console_command, "CSQC_ConsoleCommand"); \ - globalfunction(console_link, "CSQC_ConsoleLink"); \ - globalfunction(gamecommand, "GameCommand"); /*DP extension*/\ - \ - globalfunction(ent_spawn, "CSQC_Ent_Spawn"); \ - globalfunction(ent_update, "CSQC_Ent_Update"); \ - globalfunction(ent_remove, "CSQC_Ent_Remove"); \ - \ - globalfunction(event_sound, "CSQC_Event_Sound"); \ - globalfunction(serversound, "CSQC_ServerSound");/*obsolete, use event_sound*/ \ - /*globalfunction(loadresource, "CSQC_LoadResource");*//*EXT_CSQC_1*/ \ - globalfunction(parse_tempentity, "CSQC_Parse_TempEntity");/*EXT_CSQC_ABSOLUTLY_VILE*/ \ - \ - globalfunction(mapentityedited, "CSQC_MapEntityEdited");\ - \ - /*These are pointers to the csqc's globals.*/ \ - globalfloat(simtime, "time"); /*float The simulation(aka: smoothed server) time, speed drifts based upon latency*/ \ - globalfloat(frametime, "frametime"); /*float Client render frame interval*/ \ - globalfloat(gamespeed, "gamespeed"); /*float Multiplier for real time -> simulation time*/ \ - globalfloat(cltime, "cltime"); /*float Clientside map uptime indepent of gamespeed, latency, and the server in general*/ \ - globalfloat(clframetime, "clframetime"); /*float time since last video frame*/ \ - globalfloat(netnewtime, "servertime"); /*float Server time of latest inbound network frame*/ \ - globalfloat(netoldtime, "serverprevtime"); /*float Server time of previous inbound network frame */ \ - globalfloat(netdeltatime, "serverdeltatime"); /*float new-old */ \ - globalfloat(physics_mode, "physics_mode"); /*float Written before entering most qc functions*/ \ - globalentity(self, "self"); /*entity Written before entering most qc functions*/ \ - globalentity(other, "other"); /*entity Written before entering most qc functions*/ \ - \ - globalentity(deathmatch, "deathmatch"); /*for simplecsqc*/ \ - globalentity(coop, "coop"); /*for simplecsqc*/ \ - \ - globalfloat(maxclients, "maxclients"); /*float max number of players allowed*/ \ - globalfloat(numclientseats, "numclientseats"); /*float number of seats/splitscreen clients running on this client*/ \ - \ - globalvector(forward, "v_forward"); /*vector written by anglevectors*/ \ - globalvector(right, "v_right"); /*vector written by anglevectors*/ \ - globalvector(up, "v_up"); /*vector written by anglevectors*/ \ - \ - globalfloat(trace_allsolid, "trace_allsolid"); /*bool written by traceline*/ \ - globalfloat(trace_startsolid, "trace_startsolid"); /*bool written by traceline*/ \ - globalfloat(trace_fraction, "trace_fraction"); /*float written by traceline*/ \ - globalfloat(trace_inwater, "trace_inwater"); /*bool written by traceline*/ \ - globalfloat(trace_inopen, "trace_inopen"); /*bool written by traceline*/ \ - globalvector(trace_endpos, "trace_endpos"); /*vector written by traceline*/ \ - globalvector(trace_plane_normal, "trace_plane_normal"); /*vector written by traceline*/ \ - globalfloat(trace_plane_dist, "trace_plane_dist"); /*float written by traceline*/ \ - globalentity(trace_ent, "trace_ent"); /*entity written by traceline*/ \ - globalint(trace_surfaceflagsi, "trace_surfaceflagsi"); /*int written by traceline*/ \ - globalstring(trace_surfacename, "trace_surfacename"); /*string written by traceline*/ \ - globalint(trace_endcontentsi, "trace_endcontentsi"); /*int written by traceline EXT_CSQC_1*/ \ - globalint(trace_brush_id, "trace_brush_id"); /*int written by traceline*/ \ - globalint(trace_brush_faceid, "trace_brush_faceid"); /*int written by traceline*/ \ - globalint(trace_surface_id, "trace_surface_id"); /*int written by traceline*/ \ - globalint(trace_bone_id, "trace_bone_id"); /*int written by traceline*/ \ - globalint(trace_triangle_id, "trace_triangle_id"); /*int written by traceline*/ \ - globalfloat(trace_networkentity, "trace_networkentity"); /*float written by traceline*/ \ - legacycsqcglobals \ - \ - globalfloat(clientcommandframe, "clientcommandframe"); /*float the next frame that will be sent*/ \ - globalfloat(servercommandframe, "servercommandframe"); /*float the most recent frame received from the server*/ \ - \ - globalfloat(player_localentnum, "player_localentnum"); /*float the entity number the local player is looking out from*/ \ - globalfloat(player_localnum, "player_localnum"); /*float the player number of the local player*/ \ - globalfloat(intermission, "intermission"); /*float set when the client receives svc_intermission*/ \ - globalfloat(intermission_time, "intermission_time"); /*float set when the client receives svc_intermission*/ \ - globalvector(view_angles, "view_angles"); /*float set to the view angles at the start of each new frame (EXT_CSQC_1)*/ \ - \ - globalvector(pmove_org, "pmove_org"); /*deprecated. read/written by runplayerphysics*/ \ - globalvector(pmove_vel, "pmove_vel"); /*deprecated. read/written by runplayerphysics*/ \ - globalvector(pmove_mins, "pmove_mins"); /*deprecated. read/written by runplayerphysics*/ \ - globalvector(pmove_maxs, "pmove_maxs"); /*deprecated. read/written by runplayerphysics*/ \ - globalfloat(pmove_jump_held, "pmove_jump_held"); /*deprecated. read/written by runplayerphysics*/ \ - globalfloat(pmove_waterjumptime, "pmove_waterjumptime"); /*deprecated. read/written by runplayerphysics*/ \ - globalfloat(pmove_onground, "pmove_onground"); /*deprecated. read/written by runplayerphysics*/ \ - \ - globalfloat(input_timelength, "input_timelength"); /*float filled by getinputstate, read by runplayerphysics*/ \ - globalvector(input_angles, "input_angles"); /*vector filled by getinputstate, read by runplayerphysics*/ \ - globalvector(input_movevalues, "input_movevalues"); /*vector filled by getinputstate, read by runplayerphysics*/ \ - globalfloat(input_buttons, "input_buttons"); /*float filled by getinputstate, read by runplayerphysics*/ \ - globalfloat(input_impulse, "input_impulse"); /*float filled by getinputstate, read by runplayerphysics*/ \ - globalfloat(input_lightlevel, "input_lightlevel"); /*unused float filled by getinputstate, read by runplayerphysics*/ \ - globalfloat(input_weapon, "input_weapon"); /*unused float filled by getinputstate, read by runplayerphysics*/ \ - globalfloat(input_servertime, "input_servertime"); /*float filled by getinputstate, read by runplayerphysics*/ \ - globalfloat(input_clienttime, "input_clienttime"); /*float filled by getinputstate, read by runplayerphysics*/ \ - globalvector(input_cursor_screen, "input_cursor_screen"); /*float filled by getinputstate*/ \ - globalvector(input_cursor_start, "input_cursor_trace_start"); /*float filled by getinputstate*/ \ - globalvector(input_cursor_impact, "input_cursor_trace_endpos"); /*float filled by getinputstate*/ \ - globalfloat(input_cursor_entitynumber, "input_cursor_entitynumber"); /*float filled by getinputstate*/ \ - \ - globalvector(global_gravitydir, "global_gravitydir"); /*vector used when .gravitydir is 0 0 0 */ \ - globalfloat(dimension_default, "dimension_default"); /*float default value for dimension_hit+dimension_solid*/ \ - globalfloat(autocvar_vid_conwidth, "autocvar_vid_conwidth"); /*float hackfix for dp mods*/ \ - globalfloat(autocvar_vid_conheight, "autocvar_vid_conheight"); /*float hackfix for dp mods*/ \ - globalfloat(cycle_wrapped, "cycle_wrapped"); \ - ENDLIST - typedef struct { -#define globalfloat(name,qcname) float *name -#define globalint(name,qcname) int *name -#define globalvector(name,qcname) float *name -#define globalentity(name,qcname) int *name -#define globalstring(name,qcname) string_t *name -#define globalfunction(name,qcname) func_t name +#define globalfloatdep(name,dep) globalfloat(name) +#define globalfloat(name) float *name; +#define globalint(name) int *name; +#define globalvector(name) float *name; +#define globalentity(name) int *name; +#define globalstring(name) string_t *name; +#define globalfunction(name,type) func_t name; //These are the functions the engine will call to, found by name. csqcglobals @@ -331,12 +202,12 @@ static void CSQC_FindGlobals(qboolean nofuncs) static float csphysicsmode = 0; static float dimension_default = 255; static vec3_t defaultgravity = {0, 0, -1}; -#define globalfloat(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0, NULL); -#define globalint(name,qcname) csqcg.name = (int*)PR_FindGlobal(csqcprogs, qcname, 0, NULL); -#define globalvector(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0, NULL); -#define globalentity(name,qcname) csqcg.name = (int*)PR_FindGlobal(csqcprogs, qcname, 0, NULL); -#define globalstring(name,qcname) csqcg.name = (string_t*)PR_FindGlobal(csqcprogs, qcname, 0, NULL); -#define globalfunction(name,qcname) csqcg.name = nofuncs?0:PR_FindFunction(csqcprogs,qcname,PR_ANY); +#define globalfloat(name) csqcg.name = (float*)PR_FindGlobal(csqcprogs, #name, 0, NULL); +#define globalint(name) csqcg.name = (int*)PR_FindGlobal(csqcprogs, #name, 0, NULL); +#define globalvector(name) csqcg.name = (float*)PR_FindGlobal(csqcprogs, #name, 0, NULL); +#define globalentity(name) csqcg.name = (int*)PR_FindGlobal(csqcprogs, #name, 0, NULL); +#define globalstring(name) csqcg.name = (string_t*)PR_FindGlobal(csqcprogs, #name, 0, NULL); +#define globalfunction(name,typestr) csqcg.name = nofuncs?0:PR_FindFunction(csqcprogs,#name,PR_ANY); csqcglobals @@ -354,26 +225,26 @@ static void CSQC_FindGlobals(qboolean nofuncs) if (csqc_nogameaccess) { - csqcg.f_updateview = 0; //would fail - csqcg.f_updateviewloading = 0; //would fail - csqcg.parse_stuffcmd = 0; //could block cvar changes, thus allow cheats - csqcg.parse_setangles = 0; //too evil - csqcg.input_frame = 0; //no aimbot writing - csqcg.event_sound = csqcg.serversound = 0; //no sound snooping - csqcg.parse_tempentity = 0; //compat nightmare + csqcg.CSQC_UpdateView = 0; //would fail + csqcg.CSQC_UpdateViewLoading = 0; //would fail + csqcg.CSQC_Parse_StuffCmd = 0; //could block cvar changes, thus allow cheats + csqcg.CSQC_Parse_SetAngles = 0; //too evil + csqcg.CSQC_Input_Frame = 0; //no aimbot writing + csqcg.CSQC_Event_Sound = csqcg.CSQC_ServerSound = 0; //no sound snooping + csqcg.CSQC_Parse_TempEntity = 0; //compat nightmare csqcg.view_angles = NULL; csqcg.physics_mode = NULL; //no thinks stuff csqcg.pmove_org = NULL; //can't make aimbots if you don't know where you're aiming from. csqcg.pmove_vel = NULL; //no dead reckoning please csqcg.pmove_mins = csqcg.pmove_maxs = csqcg.pmove_jump_held = csqcg.pmove_waterjumptime = csqcg.pmove_onground = NULL; //I just want to kill theses csqcg.input_angles = csqcg.input_movevalues = csqcg.input_buttons = csqcg.input_impulse = csqcg.input_lightlevel = csqcg.input_weapon = csqcg.input_servertime = NULL; - csqcg.input_clienttime = csqcg.input_cursor_screen = csqcg.input_cursor_start = csqcg.input_cursor_impact = csqcg.input_cursor_entitynumber = NULL; + csqcg.input_clienttime = csqcg.input_cursor_screen = csqcg.input_cursor_trace_start = csqcg.input_cursor_trace_endpos = csqcg.input_cursor_entitynumber = NULL; } - else if (csqcg.f_updateview || csqcg.f_updateviewloading) + else if (csqcg.CSQC_UpdateView || csqcg.CSQC_UpdateViewLoading) { //full csqc AND simplecsqc's entry points at the same time are a bad idea that just result in confusion. //full csqc mods should just disable engine hud drawing - csqcg.f_drawhud = 0; - csqcg.f_drawscores = 0; + csqcg.CSQC_DrawHud = 0; + csqcg.CSQC_DrawScores = 0; } #ifndef HAVE_LEGACY @@ -426,8 +297,8 @@ static void CSQC_FindGlobals(qboolean nofuncs) ensureentity(trace_ent); - if (csqcg.simtime) - *csqcg.simtime = cl.servertime; + if (csqcg.time) + *csqcg.time = cl.servertime; if (csqcg.cltime) *csqcg.cltime = realtime-csqc_starttime; @@ -442,10 +313,10 @@ static void CSQC_FindGlobals(qboolean nofuncs) csqc_world.g.physics_mode = csqcg.physics_mode; csqc_world.g.frametime = csqcg.frametime; csqc_world.g.newmis = (int*)PR_FindGlobal(csqcprogs, "newmis", 0, NULL); - csqc_world.g.time = csqcg.simtime; - csqc_world.g.v_forward = csqcg.forward; - csqc_world.g.v_right = csqcg.right; - csqc_world.g.v_up = csqcg.up; + csqc_world.g.time = csqcg.time; + csqc_world.g.v_forward = csqcg.v_forward; + csqc_world.g.v_right = csqcg.v_right; + csqc_world.g.v_up = csqcg.v_up; csqc_world.g.defaultgravitydir = csqcg.global_gravitydir; csqc_world.g.drawfont = (float*)PR_FindGlobal(csqcprogs, "drawfont", 0, NULL); csqc_world.g.drawfontscale = (float*)PR_FindGlobal(csqcprogs, "drawfontscale", 0, NULL); @@ -645,8 +516,8 @@ static void cs_getframestate(csqcedict_t *in, unsigned int rflags, framestate_t #endif if (rflags & CSQCRF_FRAMETIMESARESTARTTIMES) { - out->g[FST_BASE].frametime[0] = *csqcg.simtime - in->xv->baseframe1time; - out->g[FST_BASE].frametime[1] = *csqcg.simtime - in->xv->baseframe2time; + out->g[FST_BASE].frametime[0] = *csqcg.time - in->xv->baseframe1time; + out->g[FST_BASE].frametime[1] = *csqcg.time - in->xv->baseframe2time; //out->g[FST_BASE].frametime[2] = *csqcg.simtime - in->xv->baseframe3time; //out->g[FST_BASE].frametime[3] = *csqcg.simtime - in->xv->baseframe4time; } @@ -675,11 +546,11 @@ static void cs_getframestate(csqcedict_t *in, unsigned int rflags, framestate_t #endif if ((rflags & CSQCRF_FRAMETIMESARESTARTTIMES) || csqc_isdarkplaces) { - out->g[FS_REG].frametime[0] = *csqcg.simtime - in->xv->frame1time; - out->g[FS_REG].frametime[1] = *csqcg.simtime - in->xv->frame2time; + out->g[FS_REG].frametime[0] = *csqcg.time - in->xv->frame1time; + out->g[FS_REG].frametime[1] = *csqcg.time - in->xv->frame2time; #if FRAME_BLENDS >= 4 - out->g[FS_REG].frametime[2] = *csqcg.simtime - in->xv->frame3time; - out->g[FS_REG].frametime[3] = *csqcg.simtime - in->xv->frame4time; + out->g[FS_REG].frametime[2] = *csqcg.time - in->xv->frame3time; + out->g[FS_REG].frametime[3] = *csqcg.time - in->xv->frame4time; #endif } else @@ -858,9 +729,9 @@ static void QCBUILTIN PF_cl_cprint (pubprogfuncs_t *prinst, struct globalvars_s static void QCBUILTIN PF_cs_makevectors (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { - if (!csqcg.forward || !csqcg.right || !csqcg.up) + if (!csqcg.v_forward || !csqcg.v_right || !csqcg.v_up) Host_EndGame("PF_makevectors: one of v_forward, v_right or v_up was not defined\n"); - AngleVectors (G_VECTOR(OFS_PARM0), csqcg.forward, csqcg.right, csqcg.up); + AngleVectors (G_VECTOR(OFS_PARM0), csqcg.v_forward, csqcg.v_right, csqcg.v_up); } static int CS_FindModel(const char *name, int *free) @@ -980,8 +851,8 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *fte_restrict in, entity_t *ft out->flags |= RF_NOSHADOW; //CSQCRF_FRAMETIMESARESTARTTIMES is handled by cs_getframestate below - if (rflags & CSQCRF_REMOVED) - Con_Printf("Warning: CSQCRF_NOAUTOADD is no longer supported\n"); +// if (rflags & CSQCRF_REMOVED) +// Con_Printf("Warning: CSQCRF_NOAUTOADD is no longer supported\n"); } effects = in->v->effects; @@ -1008,9 +879,9 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *fte_restrict in, entity_t *ft if (rflags & CSQCRF_USEAXIS) { - VectorCopy(csqcg.forward, out->axis[0]); - VectorNegate(csqcg.right, out->axis[1]); - VectorCopy(csqcg.up, out->axis[2]); + VectorCopy(csqcg.v_forward, out->axis[0]); + VectorNegate(csqcg.v_right, out->axis[1]); + VectorCopy(csqcg.v_up, out->axis[2]); out->scale = 1; } else @@ -1482,9 +1353,9 @@ static void PF_R_DynamicLight_AddInternal(pubprogfuncs_t *prinst, struct globalv if (*dl->cubemapname) { - VectorCopy(csqcg.forward, dl->axis[0]); - VectorCopy(csqcg.right, dl->axis[1]); - VectorCopy(csqcg.up, dl->axis[2]); + VectorCopy(csqcg.v_forward, dl->axis[0]); + VectorCopy(csqcg.v_right, dl->axis[1]); + VectorCopy(csqcg.v_up, dl->axis[2]); } if (pflags & PFLAGS_NOSHADOW) @@ -1631,14 +1502,6 @@ static int csqc_poly_startidx; static int csqc_poly_flags; static int csqc_poly_2d; -#define DRAWFLAG_NORMAL 0 -#define DRAWFLAG_ADD 1 -#define DRAWFLAG_MODULATE 2 -#define DRAWFLAG_MODULATE2 3 -#define DRAWFLAG_2D (1u<<2) -#define DRAWFLAG_TWOSIDED 0x400 -#define DRAWFLAG_LINES 0x800 - static void CSQC_PolyFlush(void) { mesh_t mesh; @@ -1722,6 +1585,8 @@ void QCBUILTIN PF_R_PolygonBegin(pubprogfuncs_t *prinst, struct globalvars_s *pr if ((qcflags & 3) == DRAWFLAG_ADD) beflags = BEF_NOSHADOWS|BEF_FORCEADDITIVE; + else if ((qcflags & 3) == DRAWFLAG_MODULATE) + beflags = BEF_NOSHADOWS|BEF_FORCETRANSPARENT; else beflags = BEF_NOSHADOWS; if (csqc_isdarkplaces || (qcflags & DRAWFLAG_TWOSIDED)) @@ -2879,13 +2744,13 @@ static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars } } -static void QCBUILTIN PF_cs_getstati(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +static void QCBUILTIN PF_cs_getstat_int(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { int stnum = G_FLOAT(OFS_PARM0); if (stnum < 0 || stnum >= MAX_CL_STATS) { G_INT(OFS_RETURN) = 0; - PR_RunWarning(prinst, "PF_cs_getstati: invalid stat index (%i)\n", stnum); + PR_RunWarning(prinst, "PF_cs_getstat_int: invalid stat index (%i)\n", stnum); } else if (stnum >= 128 && csqc_isdarkplaces && cls.protocol != CP_NETQUAKE && !CPNQ_IS_DP) { //dpp7 stats are fucked. @@ -2895,7 +2760,7 @@ static void QCBUILTIN PF_cs_getstati(pubprogfuncs_t *prinst, struct globalvars_s else G_INT(OFS_RETURN) = csqc_playerview->stats[stnum]; } -static void QCBUILTIN PF_cs_getstatbits(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +static void QCBUILTIN PF_cs_getstat_float(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { //read a numeric stat into a qc float. //if bits offsets are specified, reads explicitly the integer version of the stat, allowing high bits to be read for items2/serverflags. the float stat should have the same value, just with lower precision as a float can't hold a 32bit value. maybe we should just use doubles. @@ -2903,10 +2768,10 @@ static void QCBUILTIN PF_cs_getstatbits(pubprogfuncs_t *prinst, struct globalvar if (stnum < 0 || stnum >= MAX_CL_STATS) { G_FLOAT(OFS_RETURN) = 0; - PR_RunWarning(prinst, "PF_cs_getstatbits: invalid stat index (%i)\n", stnum); + PR_RunWarning(prinst, "PF_cs_getstat_float: invalid stat index (%i)\n", stnum); } else if (prinst->callargc > 1) - { + { //like getstati but with partial itof int val = csqc_playerview->stats[stnum]; int first, count; first = G_FLOAT(OFS_PARM1); @@ -2920,12 +2785,12 @@ static void QCBUILTIN PF_cs_getstatbits(pubprogfuncs_t *prinst, struct globalvar { G_FLOAT(OFS_RETURN) = (int)csqc_playerview->statsf[stnum]; //stupid. mods like xonotic end up with an ugly hud if they're actually given any precision if (G_FLOAT(OFS_RETURN) != csqc_playerview->statsf[stnum]) - csqc_deprecated("getstatf stat truncation"); //this is a common call. only get pissy if there's a reason to get pissy. + csqc_deprecated("getstat_float stat truncation"); //this is a common call. only get pissy if there's a reason to get pissy. } else G_FLOAT(OFS_RETURN) = csqc_playerview->statsf[stnum]; } -static void QCBUILTIN PF_cs_getstats(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +static void QCBUILTIN PF_cs_getstat_string(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { int stnum = G_FLOAT(OFS_PARM0); @@ -3878,10 +3743,10 @@ static void cs_set_input_state (usercmd_t *cmd) Vector2Copy(cmd->cursor_screen, csqcg.input_cursor_screen); csqcg.input_cursor_screen[2] = 0; } - if (csqcg.input_cursor_start) - VectorCopy(cmd->cursor_start, csqcg.input_cursor_start); - if (csqcg.input_cursor_impact) - VectorCopy(cmd->cursor_impact, csqcg.input_cursor_impact); + if (csqcg.input_cursor_trace_start) + VectorCopy(cmd->cursor_start, csqcg.input_cursor_trace_start); + if (csqcg.input_cursor_trace_endpos) + VectorCopy(cmd->cursor_impact, csqcg.input_cursor_trace_endpos); if (csqcg.input_cursor_entitynumber) *csqcg.input_cursor_entitynumber = cmd->cursor_entitynumber; } @@ -3916,10 +3781,10 @@ static void cs_get_input_state (usercmd_t *cmd) if (csqcg.input_cursor_screen) Vector2Copy(csqcg.input_cursor_screen, cmd->cursor_screen); - if (csqcg.input_cursor_start) - VectorCopy(csqcg.input_cursor_start, cmd->cursor_start); - if (csqcg.input_cursor_impact) - VectorCopy(csqcg.input_cursor_impact, cmd->cursor_impact); + if (csqcg.input_cursor_trace_start) + VectorCopy(csqcg.input_cursor_trace_start, cmd->cursor_start); + if (csqcg.input_cursor_trace_endpos) + VectorCopy(csqcg.input_cursor_trace_endpos, cmd->cursor_impact); if (csqcg.input_cursor_entitynumber) cmd->cursor_entitynumber = *csqcg.input_cursor_entitynumber; } @@ -4018,7 +3883,7 @@ static void QCBUILTIN PF_cs_getinputstate (pubprogfuncs_t *prinst, struct global static void QCBUILTIN PF_cs_runplayerphysics (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { float msecs; - float oldtime = *csqcg.simtime; + float oldtime = *csqcg.time; csqcedict_t *ent = (void*)G_EDICT(prinst, OFS_PARM0); int mt = ent->v->movetype; @@ -4119,7 +3984,7 @@ static void QCBUILTIN PF_cs_runplayerphysics (pubprogfuncs_t *prinst, struct glo //fixme: touch triggers? World_LinkEdict (&csqc_world, (wedict_t*)ent, true); - *csqcg.simtime = oldtime; + *csqcg.time = oldtime; } static void QCBUILTIN PF_cs_getentitytoken (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -5360,11 +5225,11 @@ static void QCBUILTIN PF_rotatevectorsbytag (pubprogfuncs_t *prinst, struct glob if (Mod_GetTag(mod, tagnum, &fstate, transforms)) { - VectorCopy(csqcg.forward, src+0); + VectorCopy(csqcg.v_forward, src+0); src[3] = 0; - VectorNegate(csqcg.right, src+4); + VectorNegate(csqcg.v_right, src+4); src[7] = 0; - VectorCopy(csqcg.up, src+8); + VectorCopy(csqcg.v_up, src+8); src[11] = 0; if (ent->xv->scale) @@ -5380,9 +5245,9 @@ static void QCBUILTIN PF_rotatevectorsbytag (pubprogfuncs_t *prinst, struct glob R_ConcatRotationsPad((void*)transforms, (void*)src, (void*)dest); - VectorCopy(dest+0, csqcg.forward); - VectorNegate(dest+4, csqcg.right); - VectorCopy(dest+8, csqcg.up); + VectorCopy(dest+0, csqcg.v_forward); + VectorNegate(dest+4, csqcg.v_right); + VectorCopy(dest+8, csqcg.v_up); VectorCopy(srcorg, retorg); for (i = 0 ; i < 3 ; i++) @@ -5697,10 +5562,10 @@ static csqcedict_t *csqcdelta_playerents[MAX_CLIENTS]; static void CSQC_EntRemove(csqcedict_t *ed) { - if (csqcg.ent_remove) + if (csqcg.CSQC_Ent_Remove) { *csqcg.self = EDICT_TO_PROG(csqcprogs, ed); - PR_ExecuteProgram(csqcprogs, csqcg.ent_remove); + PR_ExecuteProgram(csqcprogs, csqcg.CSQC_Ent_Remove); } else { @@ -5964,7 +5829,7 @@ static void QCBUILTIN PF_getentity(pubprogfuncs_t *prinst, struct globalvars_s * break; case GE_ORIGINANDVECTORS: VectorCopy(le->origin, G_VECTOR(OFS_RETURN)); - AngleVectorsIndex(le->angles, ps->modelindex, csqcg.forward, csqcg.right, csqcg.up); + AngleVectorsIndex(le->angles, ps->modelindex, csqcg.v_forward, csqcg.v_right, csqcg.v_up); break; case GE_FORWARD: AngleVectorsIndex(le->angles, ps->modelindex, G_VECTOR(OFS_RETURN), NULL, NULL); @@ -6111,7 +5976,7 @@ static void QCBUILTIN PF_getentity(pubprogfuncs_t *prinst, struct globalvars_s * break; case GE_ORIGINANDVECTORS: VectorCopy(le->origin, G_VECTOR(OFS_RETURN)); - AngleVectorsIndex(le->angles, es->modelindex, csqcg.forward, csqcg.right, csqcg.up); + AngleVectorsIndex(le->angles, es->modelindex, csqcg.v_forward, csqcg.v_right, csqcg.v_up); break; case GE_FORWARD: AngleVectorsIndex(le->angles, es->modelindex, G_VECTOR(OFS_RETURN), NULL, NULL); @@ -7002,9 +6867,9 @@ static struct { #endif //330 - {"getstati", PF_cs_getstati, 330}, // #330 float(float stnum) getstati (EXT_CSQC) - {"getstatf", PF_cs_getstatbits, 331}, // #331 float(float stnum) getstatf (EXT_CSQC) - {"getstats", PF_cs_getstats, 332}, // #332 string(float firststnum) getstats (EXT_CSQC) + {"getstati", PF_cs_getstat_int, 330}, // #330 int(float stnum) getstati (EXT_CSQC) + {"getstatf", PF_cs_getstat_float, 331}, // #331 float(float stnum) getstatf (EXT_CSQC) + {"getstats", PF_cs_getstat_string, 332}, // #332 string(float firststnum) getstats (EXT_CSQC) {"getplayerstat", PF_cs_getplayerstat, 0}, // #0 __variant(float playernum, float statnum, float stattype) getplayerstat {"setmodelindex", PF_cs_SetModelIndex, 333}, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC) {"modelnameforindex", PF_cs_ModelnameForIndex, 334}, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC) @@ -7543,7 +7408,7 @@ static void QDECL CSQC_Event_Touch(world_t *w, wedict_t *s, wedict_t *o, trace_t *csqcg.self = EDICT_TO_PROG(w->progs, (edict_t*)s); *csqcg.other = EDICT_TO_PROG(w->progs, (edict_t*)o); - *csqcg.simtime = w->physicstime; + *csqcg.time = w->physicstime; PR_ExecuteProgram (w->progs, s->v->touch); @@ -7555,7 +7420,7 @@ static void QDECL CSQC_Event_Think(world_t *w, wedict_t *s) { *csqcg.self = EDICT_TO_PROG(w->progs, (edict_t*)s); *csqcg.other = EDICT_TO_PROG(w->progs, (edict_t*)w->edicts); - *csqcg.simtime = w->physicstime; + *csqcg.time = w->physicstime; if (!s->v->think) Con_Printf("CSQC entity \"%s\" has nextthink with no think function\n", PR_GetString(w->progs, s->v->classname)); @@ -7588,7 +7453,7 @@ static qboolean QDECL CSQC_Event_ContentsTransition(world_t *w, wedict_t *ent, i { void *pr_globals = PR_globals(w->progs, PR_CURRENT); *csqcg.self = EDICT_TO_PROG(w->progs, ent); - *csqcg.simtime = w->physicstime; + *csqcg.time = w->physicstime; G_FLOAT(OFS_PARM0) = oldwatertype; G_FLOAT(OFS_PARM1) = newwatertype; PR_ExecuteProgram (w->progs, ent->xv->contentstransition); @@ -7622,8 +7487,8 @@ void CSQC_Shutdown(void) int i; if (csqcprogs) { - if (csqcg.shutdown_function) - PR_ExecuteProgram(csqcprogs, csqcg.shutdown_function); + if (csqcg.CSQC_Shutdown) + PR_ExecuteProgram(csqcprogs, csqcg.CSQC_Shutdown); key_dest_absolutemouse &= ~kdm_game; CSQC_ForgetThreads(); @@ -8213,13 +8078,13 @@ qboolean CSQC_Init (qboolean anycsqc, const char *csprogsname, unsigned int chec if (csqcg.coop) *csqcg.coop = !cl.deathmatch && cl.allocated_client_slots > 1; - if (csqcg.init_function) + if (csqcg.CSQC_Init) { void *pr_globals = PR_globals(csqcprogs, PR_CURRENT); G_FLOAT(OFS_PARM0) = CSQC_API_VERSION; //api version (((string_t *)pr_globals)[OFS_PARM1] = PR_TempString(csqcprogs, FULLENGINENAME)); G_FLOAT(OFS_PARM2) = version_number(); - PR_ExecuteProgram(csqcprogs, csqcg.init_function); + PR_ExecuteProgram(csqcprogs, csqcg.CSQC_Init); } /* { @@ -8261,11 +8126,11 @@ void CSQC_RendererRestarted(void) //FIXME: registered shaders //let the csqc know that its rendertargets got purged - if (csqcg.rendererrestarted) + if (csqcg.CSQC_RendererRestarted) { void *pr_globals = PR_globals(csqcprogs, PR_CURRENT); (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, rf->description)); - PR_ExecuteProgram(csqcprogs, csqcg.rendererrestarted); + PR_ExecuteProgram(csqcprogs, csqcg.CSQC_RendererRestarted); } //in case it drew to any render targets. if (R2D_Flush) @@ -8311,18 +8176,18 @@ void CSQC_WorldLoaded(void) if (csqc_isdarkplaces) { - if (csqcg.init_function) + if (csqcg.CSQC_Init) { void *pr_globals = PR_globals(csqcprogs, PR_CURRENT); G_FLOAT(OFS_PARM0) = CSQC_API_VERSION; //api version (((string_t *)pr_globals)[OFS_PARM1] = PR_TempString(csqcprogs, FULLENGINENAME)); G_FLOAT(OFS_PARM2) = version_number(); - PR_ExecuteProgram(csqcprogs, csqcg.init_function); + PR_ExecuteProgram(csqcprogs, csqcg.CSQC_Init); } } - if (csqcg.worldloaded) - PR_ExecuteProgram(csqcprogs, csqcg.worldloaded); + if (csqcg.CSQC_WorldLoaded) + PR_ExecuteProgram(csqcprogs, csqcg.CSQC_WorldLoaded); csqcmapentitydata = NULL; worldent->readonly = true; @@ -8547,7 +8412,7 @@ void CSQC_CvarChanged(cvar_t *var) qboolean CSQC_UseGamecodeLoadingScreen(void) { - return csqcprogs && csqcg.f_updateviewloading; + return csqcprogs && csqcg.CSQC_UpdateViewLoading; } //evil evil function. calling qc from inside the renderer is BAD. @@ -8569,16 +8434,16 @@ qboolean CSQC_SetupToRenderPortal(int entkeynum) *csqcg.self = EDICT_TO_PROG(csqcprogs, e); VectorCopy(r_refdef.vieworg, G_VECTOR(OFS_PARM0)); VectorAngles(vpn, vup, G_VECTOR(OFS_PARM1), true/*FIXME*/); - VectorCopy(vpn, csqcg.forward); - VectorCopy(vright, csqcg.right); - VectorCopy(vup, csqcg.up); + VectorCopy(vpn, csqcg.v_forward); + VectorCopy(vright, csqcg.v_right); + VectorCopy(vup, csqcg.v_up); VectorCopy(r_refdef.vieworg/*r_refdef.pvsorigin*/, csqcg.trace_endpos); PR_ExecuteProgram (csqcprogs, e->xv->camera_transform); - VectorCopy(csqcg.forward, vpn); - VectorCopy(csqcg.right, vright); - VectorCopy(csqcg.up, vup); + VectorCopy(csqcg.v_forward, vpn); + VectorCopy(csqcg.v_right, vright); + VectorCopy(csqcg.v_up, vup); VectorCopy(G_VECTOR(OFS_RETURN), r_refdef.vieworg); VectorCopy(csqcg.trace_endpos, r_refdef.pvsorigin); @@ -8600,7 +8465,7 @@ qboolean CSQC_DrawView(void) csqc_resortfrags = true; csqctime = Sys_DoubleTime(); - if (!csqcg.f_updateview || !csqcprogs) + if (!csqcg.CSQC_UpdateView || !csqcprogs) return false; if (cls.state < ca_active && !CSQC_UnconnectedOkay(false)) @@ -8689,8 +8554,8 @@ qboolean CSQC_DrawView(void) if (csqcg.cltime) *csqcg.cltime = realtime-csqc_starttime; - if (csqcg.simtime) - *csqcg.simtime = cl.servertime; + if (csqcg.time) + *csqcg.time = cl.servertime; if (csqcg.clientcommandframe) *csqcg.clientcommandframe = cl.movesequence; if (csqcg.servercommandframe) @@ -8704,12 +8569,12 @@ qboolean CSQC_DrawView(void) } if (cl.currentpackentities && cl.previouspackentities) { - if (csqcg.netnewtime) - *csqcg.netnewtime = cl.currentpackentities->servertime; - if (csqcg.netoldtime) - *csqcg.netoldtime = cl.previouspackentities->servertime; - if (csqcg.netdeltatime) - *csqcg.netdeltatime = cl.currentpackentities->servertime - cl.previouspackentities->servertime; + if (csqcg.servertime) + *csqcg.servertime = cl.currentpackentities->servertime; + if (csqcg.serverprevtime) + *csqcg.serverprevtime = cl.previouspackentities->servertime; + if (csqcg.serverdeltatime) + *csqcg.serverdeltatime = cl.currentpackentities->servertime - cl.previouspackentities->servertime; } //always revert to a usable default. @@ -8741,10 +8606,10 @@ qboolean CSQC_DrawView(void) } G_FLOAT(OFS_PARM2) = !Key_Dest_Has(kdm_menu|kdm_cwindows) && !r_refdef.eyeoffset[0] && !r_refdef.eyeoffset[1]; - if (csqcg.f_updateviewloading && cls.state && cls.state < ca_active) - PR_ExecuteProgram(csqcprogs, csqcg.f_updateviewloading); + if (csqcg.CSQC_UpdateViewLoading && cls.state && cls.state < ca_active) + PR_ExecuteProgram(csqcprogs, csqcg.CSQC_UpdateViewLoading); else - PR_ExecuteProgram(csqcprogs, csqcg.f_updateview); + PR_ExecuteProgram(csqcprogs, csqcg.CSQC_UpdateView); } if (*r_refdef.rt_destcolour[0].texname) @@ -8763,7 +8628,7 @@ qboolean CSQC_DrawView(void) qboolean CSQC_DrawHud(playerview_t *pv) { - if (csqcg.f_drawhud && (pv==cl.playerview/* || csqcg.numclientseats*/)) + if (csqcg.CSQC_DrawHud && (pv==cl.playerview/* || csqcg.numclientseats*/)) { RSpeedMark(); void *pr_globals = PR_globals(csqcprogs, PR_CURRENT); @@ -8772,8 +8637,8 @@ qboolean CSQC_DrawHud(playerview_t *pv) CSQC_ChangeLocalPlayer(pv-cl.playerview); if (csqcg.numclientseats) *csqcg.numclientseats = cl.splitclients; - if (csqcg.simtime) - *csqcg.simtime = cl.time; + if (csqcg.time) + *csqcg.time = cl.time; if (csqcg.frametime) *csqcg.frametime = host_frametime; if (csqcg.cltime) @@ -8790,7 +8655,7 @@ qboolean CSQC_DrawHud(playerview_t *pv) G_FLOAT(OFS_PARM2+0) = 0;//r_refdef.grect.x; G_FLOAT(OFS_PARM2+1) = 0;//r_refdef.grect.y; G_FLOAT(OFS_PARM2+2) = 0;//pv-cl.playerview; - PR_ExecuteProgram(csqcprogs, csqcg.f_drawhud); + PR_ExecuteProgram(csqcprogs, csqcg.CSQC_DrawHud); if (*r_refdef.rt_destcolour[0].texname) { @@ -8807,7 +8672,7 @@ qboolean CSQC_DrawHud(playerview_t *pv) } qboolean CSQC_DrawScores(playerview_t *pv) { - if (csqcg.f_drawscores && (pv==cl.playerview/* || csqcg.numclientseats*/)) + if (csqcg.CSQC_DrawScores && (pv==cl.playerview/* || csqcg.numclientseats*/)) { RSpeedMark(); void *pr_globals = PR_globals(csqcprogs, PR_CURRENT); @@ -8816,8 +8681,8 @@ qboolean CSQC_DrawScores(playerview_t *pv) CSQC_ChangeLocalPlayer(pv-cl.playerview); if (csqcg.numclientseats) *csqcg.numclientseats = cl.splitclients; - if (csqcg.simtime) - *csqcg.simtime = cl.time; + if (csqcg.time) + *csqcg.time = cl.time; if (csqcg.frametime) *csqcg.frametime = host_frametime; if (csqcg.cltime) @@ -8834,7 +8699,7 @@ qboolean CSQC_DrawScores(playerview_t *pv) G_FLOAT(OFS_PARM2+0) = 0;//r_refdef.grect.x; G_FLOAT(OFS_PARM2+1) = 0;//r_refdef.grect.y; G_FLOAT(OFS_PARM2+2) = 0;//pv-cl.playerview; - PR_ExecuteProgram(csqcprogs, csqcg.f_drawscores); + PR_ExecuteProgram(csqcprogs, csqcg.CSQC_DrawScores); if (*r_refdef.rt_destcolour[0].texname) { @@ -8856,7 +8721,7 @@ qboolean CSQC_KeyPress(int key, int unicode, qboolean down, unsigned int devid) void *pr_globals; int ie = down?CSIE_KEYDOWN:CSIE_KEYUP; - if (!csqcprogs || !csqcg.input_event || ie >= dpcompat_csqcinputeventtypes.ival) + if (!csqcprogs || !csqcg.CSQC_InputEvent || ie >= dpcompat_csqcinputeventtypes.ival) return false; #ifdef TEXTEDITOR if (editormodal) @@ -8888,7 +8753,7 @@ qboolean CSQC_KeyPress(int key, int unicode, qboolean down, unsigned int devid) return false; //prevent up events being able to leak csqckeysdown[key] &= ~(1u<= dpcompat_csqcinputeventtypes.ival) + if (!csqcprogs || !csqcg.CSQC_InputEvent || CSIE_MOUSEABS >= dpcompat_csqcinputeventtypes.ival) return false; pr_globals = PR_globals(csqcprogs, PR_CURRENT); @@ -8907,7 +8772,7 @@ qboolean CSQC_MousePosition(float xabs, float yabs, unsigned int devid) G_FLOAT(OFS_PARM2) = (yabs * vid.height) / vid.pixelheight; G_FLOAT(OFS_PARM3) = devid; - PR_ExecuteProgram (csqcprogs, csqcg.input_event); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_InputEvent); return G_FLOAT(OFS_RETURN); } @@ -8915,7 +8780,7 @@ qboolean CSQC_MouseMove(float xdelta, float ydelta, unsigned int devid) { void *pr_globals; - if (!csqcprogs || !csqcg.input_event || CSIE_MOUSEDELTA >= dpcompat_csqcinputeventtypes.ival) + if (!csqcprogs || !csqcg.CSQC_InputEvent || CSIE_MOUSEDELTA >= dpcompat_csqcinputeventtypes.ival) return false; pr_globals = PR_globals(csqcprogs, PR_CURRENT); @@ -8924,7 +8789,7 @@ qboolean CSQC_MouseMove(float xdelta, float ydelta, unsigned int devid) G_FLOAT(OFS_PARM2) = (ydelta * vid.height) / vid.pixelheight; G_FLOAT(OFS_PARM3) = devid; - PR_ExecuteProgram (csqcprogs, csqcg.input_event); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_InputEvent); return G_FLOAT(OFS_RETURN); } @@ -8932,7 +8797,7 @@ qboolean CSQC_MouseMove(float xdelta, float ydelta, unsigned int devid) qboolean CSQC_JoystickAxis(int axis, float value, unsigned int devid) { void *pr_globals; - if (!csqcprogs || !csqcg.input_event || CSIE_JOYAXIS >= dpcompat_csqcinputeventtypes.ival) + if (!csqcprogs || !csqcg.CSQC_InputEvent || CSIE_JOYAXIS >= dpcompat_csqcinputeventtypes.ival) return false; pr_globals = PR_globals(csqcprogs, PR_CURRENT); @@ -8940,14 +8805,14 @@ qboolean CSQC_JoystickAxis(int axis, float value, unsigned int devid) G_FLOAT(OFS_PARM1) = axis; G_FLOAT(OFS_PARM2) = value; G_FLOAT(OFS_PARM3) = devid; - PR_ExecuteProgram (csqcprogs, csqcg.input_event); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_InputEvent); return G_FLOAT(OFS_RETURN); } qboolean CSQC_Accelerometer(float x, float y, float z) { void *pr_globals; - if (!csqcprogs || !csqcg.input_event || CSIE_ACCELEROMETER >= dpcompat_csqcinputeventtypes.ival) + if (!csqcprogs || !csqcg.CSQC_InputEvent || CSIE_ACCELEROMETER >= dpcompat_csqcinputeventtypes.ival) return false; pr_globals = PR_globals(csqcprogs, PR_CURRENT); @@ -8955,13 +8820,13 @@ qboolean CSQC_Accelerometer(float x, float y, float z) G_FLOAT(OFS_PARM1) = x; G_FLOAT(OFS_PARM2) = y; G_FLOAT(OFS_PARM3) = z; - PR_ExecuteProgram (csqcprogs, csqcg.input_event); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_InputEvent); return G_FLOAT(OFS_RETURN); } qboolean CSQC_Gyroscope(float x, float y, float z) { void *pr_globals; - if (!csqcprogs || !csqcg.input_event || CSIE_GYROSCOPE >= dpcompat_csqcinputeventtypes.ival) + if (!csqcprogs || !csqcg.CSQC_InputEvent || CSIE_GYROSCOPE >= dpcompat_csqcinputeventtypes.ival) return false; pr_globals = PR_globals(csqcprogs, PR_CURRENT); @@ -8969,14 +8834,14 @@ qboolean CSQC_Gyroscope(float x, float y, float z) G_FLOAT(OFS_PARM1) = x; G_FLOAT(OFS_PARM2) = y; G_FLOAT(OFS_PARM3) = z; - PR_ExecuteProgram (csqcprogs, csqcg.input_event); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_InputEvent); return G_FLOAT(OFS_RETURN); } qboolean CSQC_ConsoleLink(char *text, char *info) { void *pr_globals; - if (!csqcprogs || !csqcg.console_link) + if (!csqcprogs || !csqcg.CSQC_ConsoleLink) return false; pr_globals = PR_globals(csqcprogs, PR_CURRENT); @@ -8984,14 +8849,14 @@ qboolean CSQC_ConsoleLink(char *text, char *info) *info = 0; (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, text)); *info = '\\'; - PR_ExecuteProgram (csqcprogs, csqcg.console_link); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_ConsoleLink); return G_FLOAT(OFS_RETURN); } qboolean CSQC_ConsoleCommand(int seat, const char *cmd) { void *pr_globals; - if (!csqcprogs || !csqcg.console_command) + if (!csqcprogs || !csqcg.CSQC_ConsoleCommand) return false; #ifdef TEXTEDITOR if (editormodal) @@ -9005,54 +8870,54 @@ qboolean CSQC_ConsoleCommand(int seat, const char *cmd) pr_globals = PR_globals(csqcprogs, PR_CURRENT); (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, cmd)); - PR_ExecuteProgram (csqcprogs, csqcg.console_command); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_ConsoleCommand); return G_FLOAT(OFS_RETURN); } static void CSQC_GameCommand_f(void) { void *pr_globals; - if (!csqcprogs || !csqcg.gamecommand) + if (!csqcprogs || !csqcg.GameCommand) return; pr_globals = PR_globals(csqcprogs, PR_CURRENT); (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, Cmd_Args())); - PR_ExecuteProgram (csqcprogs, csqcg.gamecommand); + PR_ExecuteProgram (csqcprogs, csqcg.GameCommand); } void CSQC_PlayerInfoChanged(int player) { void *pr_globals; - if (!csqcprogs || !csqcg.playerinfochanged) + if (!csqcprogs || !csqcg.CSQC_PlayerInfoChanged) return; pr_globals = PR_globals(csqcprogs, PR_CURRENT); G_FLOAT(OFS_PARM0) = player; // (((string_t *)pr_globals)[OFS_PARM1] = PR_TempString(csqcprogs, keyname)); - PR_ExecuteProgram (csqcprogs, csqcg.playerinfochanged); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_PlayerInfoChanged); } void CSQC_ServerInfoChanged(void) { // void *pr_globals; - if (!csqcprogs || !csqcg.serverinfochanged) + if (!csqcprogs || !csqcg.CSQC_ServerInfoChanged) return; // pr_globals = PR_globals(csqcprogs, PR_CURRENT); // (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, keyname)); - PR_ExecuteProgram (csqcprogs, csqcg.serverinfochanged); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_ServerInfoChanged); } qboolean CSQC_ParseTempEntity(void) { int orc; void *pr_globals; - if (!csqcprogs || !csqcg.parse_tempentity) + if (!csqcprogs || !csqcg.CSQC_Parse_TempEntity) return false; pr_globals = PR_globals(csqcprogs, PR_CURRENT); csqc_mayread = true; orc = msg_readcount; - PR_ExecuteProgram (csqcprogs, csqcg.parse_tempentity); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_Parse_TempEntity); csqc_mayread = false; if (G_FLOAT(OFS_RETURN)) return true; @@ -9062,11 +8927,11 @@ qboolean CSQC_ParseTempEntity(void) return false; } -qboolean CSQC_ParseGamePacket(int seat) +qboolean CSQC_ParseGamePacket(int seat, qboolean sized) { - int parsefnc = csqcg.parse_event?csqcg.parse_event:csqcg.parse_tempentity; + int parsefnc = csqcg.CSQC_Parse_Event?csqcg.CSQC_Parse_Event:csqcg.CSQC_Parse_TempEntity; - if (cl.csqcdebug) + if (sized) { int len = (unsigned short)MSG_ReadShort(); int start = msg_readcount; @@ -9091,7 +8956,8 @@ qboolean CSQC_ParseGamePacket(int seat) { if (!csqcprogs || !parsefnc) { - Host_EndGame("CSQC not running or is unable to parse events.\n"); + int next = MSG_ReadByte(); + Host_EndGame("CSQC not running or is unable to parse events (lead byte %i).\n", next); return false; } csqc_mayread = true; @@ -9105,7 +8971,7 @@ qboolean CSQC_ParseGamePacket(int seat) void CSQC_MapEntityEdited(int modelindex, int idx, const char *newe) { void *pr_globals; - if (!csqcprogs || !csqcg.mapentityedited) + if (!csqcprogs || !csqcg.CSQC_MapEntityEdited) return; if (modelindex != 1) @@ -9114,7 +8980,7 @@ void CSQC_MapEntityEdited(int modelindex, int idx, const char *newe) pr_globals = PR_globals(csqcprogs, PR_CURRENT); G_INT(OFS_PARM0) = idx; (((string_t *)pr_globals)[OFS_PARM1] = PR_TempString(csqcprogs, newe)); - PR_ExecuteProgram (csqcprogs, csqcg.mapentityedited); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_MapEntityEdited); } /*qboolean CSQC_LoadResource(char *resname, char *restype) @@ -9135,7 +9001,7 @@ void CSQC_MapEntityEdited(int modelindex, int idx, const char *newe) qboolean CSQC_Parse_Damage(int seat, float save, float take, vec3_t source) { void *pr_globals; - if (!csqcprogs || !csqcg.parse_damage) + if (!csqcprogs || !csqcg.CSQC_Parse_Damage) return false; CSQC_ChangeLocalPlayer(seat); @@ -9146,7 +9012,7 @@ qboolean CSQC_Parse_Damage(int seat, float save, float take, vec3_t source) ((float *)pr_globals)[OFS_PARM2+0] = source[0]; ((float *)pr_globals)[OFS_PARM2+1] = source[1]; ((float *)pr_globals)[OFS_PARM2+2] = source[2]; - PR_ExecuteProgram (csqcprogs, csqcg.parse_damage); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_Parse_Damage); return G_FLOAT(OFS_RETURN); } @@ -9157,7 +9023,7 @@ qboolean CSQC_ParsePrint(char *message, int printlevel) int bufferpos; char *nextline; qboolean doflush; - if (!csqcprogs || !csqcg.parse_print) + if (!csqcprogs || !csqcg.CSQC_Parse_Print) { return false; } @@ -9200,7 +9066,7 @@ qboolean CSQC_ParsePrint(char *message, int printlevel) pr_globals = PR_globals(csqcprogs, PR_CURRENT); (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, csqc_printbuffer)); G_FLOAT(OFS_PARM1) = printlevel; - PR_ExecuteProgram (csqcprogs, csqcg.parse_print); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_Parse_Print); bufferpos = 0; csqc_printbuffer[bufferpos] = 0; @@ -9213,7 +9079,7 @@ qboolean CSQC_StuffCmd(int lplayernum, char *cmd, char *cmdend) { void *pr_globals; char tmp[2]; - if (!csqcprogs || !csqcg.parse_stuffcmd) + if (!csqcprogs || !csqcg.CSQC_Parse_StuffCmd) return false; CSQC_ChangeLocalPlayer(lplayernum); @@ -9227,13 +9093,13 @@ qboolean CSQC_StuffCmd(int lplayernum, char *cmd, char *cmdend) cmdend[0] = tmp[0]; cmdend[1] = tmp[1]; - PR_ExecuteProgram (csqcprogs, csqcg.parse_stuffcmd); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_Parse_StuffCmd); return true; } qboolean CSQC_CenterPrint(int seat, const char *cmd) { void *pr_globals; - if (!csqcprogs || !csqcg.parse_centerprint) + if (!csqcprogs || !csqcg.CSQC_Parse_CenterPrint) return false; CSQC_ChangeLocalPlayer(seat); @@ -9241,14 +9107,14 @@ qboolean CSQC_CenterPrint(int seat, const char *cmd) pr_globals = PR_globals(csqcprogs, PR_CURRENT); (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, cmd)); - PR_ExecuteProgram (csqcprogs, csqcg.parse_centerprint); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_Parse_CenterPrint); return G_FLOAT(OFS_RETURN) || csqc_isdarkplaces; } qboolean CSQC_Parse_SetAngles(int seat, vec3_t newangles, qboolean wasdelta) { void *pr_globals; - if (!csqcprogs || !csqcg.parse_setangles) + if (!csqcprogs || !csqcg.CSQC_Parse_SetAngles) return false; CSQC_ChangeLocalPlayer(seat); @@ -9259,19 +9125,19 @@ qboolean CSQC_Parse_SetAngles(int seat, vec3_t newangles, qboolean wasdelta) ((float *)pr_globals)[OFS_PARM0+2] = newangles[2]; ((float *)pr_globals)[OFS_PARM1] = wasdelta; - PR_ExecuteProgram (csqcprogs, csqcg.parse_setangles); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_Parse_SetAngles); return G_FLOAT(OFS_RETURN); } void CSQC_Input_Frame(int seat, usercmd_t *cmd) { - if (!csqcprogs || !csqcg.input_frame) + if (!csqcprogs || !csqcg.CSQC_Input_Frame) return; CSQC_ChangeLocalPlayer(seat); - if (csqcg.simtime) - *csqcg.simtime = cl.servertime; + if (csqcg.time) + *csqcg.time = cl.servertime; if (csqcg.cltime) *csqcg.cltime = realtime-csqc_starttime; @@ -9279,7 +9145,7 @@ void CSQC_Input_Frame(int seat, usercmd_t *cmd) *csqcg.clientcommandframe = cl.movesequence; cs_set_input_state(cmd); - PR_ExecuteProgram (csqcprogs, csqcg.input_frame); + PR_ExecuteProgram (csqcprogs, csqcg.CSQC_Input_Frame); cs_get_input_state(cmd); } @@ -9305,7 +9171,7 @@ int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float if (!csqcprogs) return false; - if (csqcg.event_sound) + if (csqcg.CSQC_Event_Sound) { pr_globals = PR_globals(csqcprogs, PR_CURRENT); @@ -9326,11 +9192,11 @@ int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float G_FLOAT(OFS_PARM7) = flags; // G_FLOAT(OFS_PARM8) = timeofs; - PR_ExecuteProgram(csqcprogs, csqcg.event_sound); + PR_ExecuteProgram(csqcprogs, csqcg.CSQC_Event_Sound); return G_FLOAT(OFS_RETURN); } - else if (csqcg.serversound) + else if (csqcg.CSQC_ServerSound) { CSQC_EntityCheck(entnum); ent = csqcent[entnum]; @@ -9348,7 +9214,7 @@ int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float G_FLOAT(OFS_PARM5) = flags; G_FLOAT(OFS_PARM6) = timeofs; - PR_ExecuteProgram(csqcprogs, csqcg.serversound); + PR_ExecuteProgram(csqcprogs, csqcg.CSQC_ServerSound); return G_FLOAT(OFS_RETURN); } @@ -9364,7 +9230,7 @@ void CSQC_GetEntityOrigin(unsigned int csqcent, float *out) VectorCopy(ent->v->origin, out); } -void CSQC_ParseEntities(void) +void CSQC_ParseEntities(qboolean sized) { csqcedict_t *ent; unsigned int entnum; @@ -9376,7 +9242,7 @@ void CSQC_ParseEntities(void) if (!csqcprogs) Host_EndGame("CSQC needs to be initialized for this server.\n"); - if (!csqcg.ent_update || !csqcg.self) + if (!csqcg.CSQC_Ent_Update || !csqcg.self) Host_EndGame("CSQC has no CSQC_Ent_Update function\n"); if (!csqc_world.worldmodel || csqc_world.worldmodel->loadstate != MLS_LOADED) Host_EndGame("world is not yet initialised\n"); @@ -9384,17 +9250,17 @@ void CSQC_ParseEntities(void) pr_globals = PR_globals(csqcprogs, PR_CURRENT); CL_CalcClientTime(); - if (csqcg.simtime) //estimated server time - *csqcg.simtime = cl.servertime; + if (csqcg.time) //estimated server time + *csqcg.time = cl.servertime; if (csqcg.cltime) //smooth client time. *csqcg.cltime = realtime-csqc_starttime; - if (csqcg.netnewtime) - *csqcg.netnewtime = cl.gametime; - if (csqcg.netoldtime) - *csqcg.netoldtime = cl.oldgametime; - if (csqcg.netdeltatime) - *csqcg.netdeltatime = cl.gametime - cl.oldgametime; + if (csqcg.servertime) + *csqcg.servertime = cl.gametime; + if (csqcg.serverprevtime) + *csqcg.serverprevtime = cl.oldgametime; + if (csqcg.serverdeltatime) + *csqcg.serverdeltatime = cl.gametime - cl.oldgametime; if (!csqc_isdarkplaces) { @@ -9449,7 +9315,7 @@ void CSQC_ParseEntities(void) { CSQC_EntityCheck(entnum); - if (cl.csqcdebug) + if (sized) { packetsize = MSG_ReadShort(); packetstart = msg_readcount; @@ -9463,11 +9329,11 @@ void CSQC_ParseEntities(void) ent = csqcent[entnum]; if (!ent) { - if (csqcg.ent_spawn) + if (csqcg.CSQC_Ent_Spawn) { *csqcg.self = 0; G_FLOAT(OFS_PARM0) = entnum; - PR_ExecuteProgram(csqcprogs, csqcg.ent_spawn); + PR_ExecuteProgram(csqcprogs, csqcg.CSQC_Ent_Spawn); ent = csqcent[entnum] = (csqcedict_t*)PROG_TO_WEDICT(csqcprogs, *csqcg.self); //allow the mod to change the ent. } else @@ -9491,12 +9357,12 @@ void CSQC_ParseEntities(void) *csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)ent); csqc_mayread = true; - PR_ExecuteProgram(csqcprogs, csqcg.ent_update); + PR_ExecuteProgram(csqcprogs, csqcg.CSQC_Ent_Update); csqc_mayread = false; - if (csqcg.ent_spawn) + if (csqcg.CSQC_Ent_Spawn) csqcent[entnum] = (csqcedict_t*)PROG_TO_WEDICT(csqcprogs, *csqcg.self); //allow the mod to change the ent. - if (cl.csqcdebug) + if (sized) { if (msg_readcount != packetstart+packetsize) { diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index 2290cfd9b..5990a1075 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -19,13 +19,6 @@ void M_Init_Internal (void); void M_DeInit_Internal (void); extern unsigned int r2d_be_flags; -#define DRAWFLAG_NORMAL 0 -#define DRAWFLAG_ADD 1 -#define DRAWFLAG_MODULATE 2 -#define DRAWFLAG_MODULATE2 3 -#define DRAWFLAG_2D (1u<<2) -#define DRAWFLAG_TWOSIDED 0x400 -#define DRAWFLAG_LINES 0x800 static unsigned int PF_SelectDPDrawFlag(pubprogfuncs_t *prinst, int flag) { if (r_refdef.warndraw) diff --git a/engine/client/pr_skelobj.c b/engine/client/pr_skelobj.c index 17da787fc..e4b4c2a0a 100644 --- a/engine/client/pr_skelobj.c +++ b/engine/client/pr_skelobj.c @@ -2607,6 +2607,12 @@ void QCBUILTIN PF_gettaginfo (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl } bonemat_toqcvectors(result, w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN)); + +/* //extra info for dp compat. + gettaginfo_parent = parentofbone(tagnum); + gettaginfo_name = nameofbone(tagnum); + bonemat_toqcvectors(relbonetransform(fstate, tagnum), gettaginfo_forward, gettaginfo_right, gettaginfo_up, gettaginfo_offset); +*/ } //writes to axis+origin. returns root entity. diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 8603466b1..2cb036809 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -291,7 +291,7 @@ cvar_t scr_fov_viewmodel = CVARFD("r_viewmodel_fov", "", CVAR_ARCHIVE, "field of vision, 1-170 degrees, standard fov is 90, nquake defaults to 108."); cvar_t scr_printspeed = CVAR ("scr_printspeed", "16"); cvar_t scr_showpause = CVAR ("showpause", "1"); -cvar_t scr_showturtle = CVAR ("showturtle", "0"); +cvar_t scr_showturtle = CVARD ("showturtle", "0", "Enables a low-framerate indicator."); cvar_t scr_turtlefps = CVAR ("scr_turtlefps", "10"); cvar_t scr_sshot_compression = CVAR ("scr_sshot_compression", "75"); cvar_t scr_sshot_type = CVARD ("scr_sshot_type", "png", "This specifies the default extension(and thus file format) for screenshots.\nKnown extensions are: png, jpg/jpeg, bmp, pcx, tga, ktx, dds."); diff --git a/engine/client/sys_linux.c b/engine/client/sys_linux.c index 51d6c3f6b..44c9e4ef8 100644 --- a/engine/client/sys_linux.c +++ b/engine/client/sys_linux.c @@ -1103,7 +1103,6 @@ int main (int c, const char **v) quakeparms_t parms; int i; -// char cwd[1024]; char bindir[1024]; signal(SIGFPE, SIG_IGN); @@ -1167,7 +1166,33 @@ int main (int c, const char **v) } } - parms.basedir = realpath(".", NULL); +#if _POSIX_C_SOURCE >= 200809L + { + char *path = realpath(".", NULL); + if (path) + { + size_t l = strlen(path)+2; + char *npath = malloc(strlen(path)+2); + Q_snprintfz(npath, l, "%s/", path); + parms.basedir = npath; + free(path); + } + } +#elif _POSIX_C_SOURCE >= 200112L && defined(PATH_MAX) + { + char path[PATH_MAX]; + if (realpath(".", path)) + { + size_t l = strlen(path)+2; + char *npath = malloc(strlen(path)+2); + Q_snprintfz(npath, l, "%s/", path); + parms.basedir = npath; + } + } +#else + parms.basedir = ""; //play it safe when realpath is too awkward to use. don't depend upon "./" working, and hope that the user uses -basedir or simply doesn't care about path prints (hopefully its only windows libraries that change the working dir without the program's permission). +#endif + memset(bindir, 0, sizeof(bindir)); //readlink does NOT null terminate, apparently. #ifdef __linux__ //attempt to figure out where the exe is located @@ -1233,7 +1258,7 @@ int main (int c, const char **v) #endif if (parms.binarydir) - Sys_Printf("Binary is located at \"%s\"\n", bindir); + Sys_Printf("Binary is located at \"%s\"\n", parms.binarydir); #ifndef CLIENTONLY if (isDedicated) //compleate denial to switch to anything else - many of the client structures are not initialized. @@ -1369,7 +1394,7 @@ qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refres #define SYS_CLIPBOARD_SIZE 256 static char clipboard_buffer[SYS_CLIPBOARD_SIZE] = {0}; -void Sys_Clipboard_PasteText(clipboardtype_t cbt, void (*callback)(void *cb, char *utf8), void *ctx) +void Sys_Clipboard_PasteText(clipboardtype_t cbt, void (*callback)(void *cb, const char *utf8), void *ctx) { callback(ctx, clipboard_buffer); } diff --git a/engine/common/bspfile.h b/engine/common/bspfile.h index 5bd409d18..51133e78f 100644 --- a/engine/common/bspfile.h +++ b/engine/common/bspfile.h @@ -619,17 +619,35 @@ typedef struct #define TI_SLICK 0x2 // effects game physics -#define TI_SKY 0x4 // don't draw, but add to skybox -#define TI_WARP 0x8 // turbulent water warp -#define TI_TRANS33 0x10 -#define TI_TRANS66 0x20 -#define TI_FLOWING 0x40 // scroll towards angle +#define TI_SKY 0x4 // don't draw, but add to skybox +#define TI_WARP 0x8 // turbulent water warp +#define TI_TRANS33 0x10 +#define TI_TRANS66 0x20 +#define TI_FLOWING 0x40 // scroll towards angle #define TI_NODRAW 0x80 // don't bother referencing the texture #define TI_ALPHATEST 0x100 //Surface flags -#define Q3SURF_LADDER 0x8 //wee +//#define Q3SURFACEFLAG_NODAMAGE 0x1 // never give falling damage +//#define Q3SURFACEFLAG_SLICK 0x2 // effects game physics +//#define Q3SURFACEFLAG_SKY 0x4 // lighting from environment map +#define Q3SURFACEFLAG_LADDER 0x8 +//#define Q3SURFACEFLAG_NOIMPACT 0x10 // don't make missile explosions +//#define Q3SURFACEFLAG_NOMARKS 0x20 // don't leave missile marks +//#define Q3SURFACEFLAG_FLESH 0x40 // make flesh sounds and effects +//#define Q3SURFACEFLAG_NODRAW 0x80 // don't generate a drawsurface at all +//#define Q3SURFACEFLAG_HINT 0x100 // make a primary bsp splitter +//#define Q3SURFACEFLAG_SKIP 0x200 // completely ignore, allowing non-closed brushes +//#define Q3SURFACEFLAG_NOLIGHTMAP 0x400 // surface doesn't need a lightmap +//#define Q3SURFACEFLAG_POINTLIGHT 0x800 // generate lighting info at vertexes +//#define Q3SURFACEFLAG_METALSTEPS 0x1000 // clanking footsteps +//#define Q3SURFACEFLAG_NOSTEPS 0x2000 // no footstep sounds +//#define Q3SURFACEFLAG_NONSOLID 0x4000 // don't collide against curves with this set +//#define Q3SURFACEFLAG_LIGHTFILTER 0x8000 // act as a light filter during q3map -light +//#define Q3SURFACEFLAG_ALPHASHADOW 0x10000 // do per-pixel light shadow casting in q3map +//#define Q3SURFACEFLAG_NODLIGHT 0x20000 // don't dlight even if solid (solid lava, skies) +//#define Q3SURFACEFLAG_DUST 0x40000 // leave a dust trail when walking on this surface // content masks. Allow q2contents_window in here //#define MASK_ALL (-1) diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 5e6c80474..c1ea4a8f5 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -4277,7 +4277,6 @@ void Cmd_Init (void) Cmd_AddCommandAD ("seta_calc", Cmd_set_f, Cmd_Set_c, "Sets the named cvar to the result of a (complex) expression. Also forces the archive flag so that the cvar will always be written into any saved configs."); Cmd_AddCommandD ("vstr", Cmd_Vstr_f, "Executes the string value of the cvar, much like if it were an alias. For compatibility with q3."); Cmd_AddCommandAD ("inc", Cvar_Inc_f, Cmd_Set_c, "Adds a value to the named cvar. Use a negative value if you wish to decrease the cvar's value."); - //FIXME: Add seta some time. Cmd_AddCommand ("if", Cmd_if_f); Cmd_AddCommand ("cmdlist", Cmd_List_f); @@ -4312,6 +4311,7 @@ void Cmd_Init (void) Cmd_AddCommandD ("in", Cmd_In_f, "Issues the given command after a time delay. Disabled if ruleset_allow_in is 0."); #ifdef HAVE_LEGACY + Cmd_AddCommandD ("defer", Cmd_In_f, "Issues the given command after a time delay. Disabled if ruleset_allow_in is 0."); Cvar_Register(&dpcompat_set, "Darkplaces compatibility"); Cvar_Register(&dpcompat_console, "Darkplaces compatibility"); #endif diff --git a/engine/common/fs_stdio.c b/engine/common/fs_stdio.c index f5fc3fc7d..7b6f21cec 100644 --- a/engine/common/fs_stdio.c +++ b/engine/common/fs_stdio.c @@ -37,7 +37,9 @@ static int QDECL VFSSTDIO_WriteBytes (struct vfsfile_s *file, const void *buffer static qboolean QDECL VFSSTDIO_Seek (struct vfsfile_s *file, qofs_t pos) { vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; -#if _POSIX_C_SOURCE >= 200112L +#ifdef __USE_LARGEFILE64 + return fseeko64(intfile->handle, (off64_t)pos, SEEK_SET) == 0; +#elif _POSIX_C_SOURCE >= 200112L return fseeko(intfile->handle, (off_t)pos, SEEK_SET) == 0; #else return fseek(intfile->handle, pos, SEEK_SET) == 0; @@ -46,7 +48,9 @@ static qboolean QDECL VFSSTDIO_Seek (struct vfsfile_s *file, qofs_t pos) static qofs_t QDECL VFSSTDIO_Tell (struct vfsfile_s *file) { vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; -#if _POSIX_C_SOURCE >= 200112L +#ifdef __USE_LARGEFILE64 + idhgr sdrg ser gser greturn (qofs_t)ftello64(intfile->handle); +#elif _POSIX_C_SOURCE >= 200112L return (qofs_t)ftello(intfile->handle); #else return ftell(intfile->handle); @@ -61,7 +65,14 @@ static qofs_t QDECL VFSSTDIO_GetSize (struct vfsfile_s *file) { vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; -#if _POSIX_C_SOURCE >= 200112L +#ifdef __USE_LARGEFILE64 + off64_t curpos; + qofs_t maxlen; + curpos = ftello64(intfile->handle); + fseeko64(intfile->handle, 0, SEEK_END); + maxlen = (qofs_t)ftello64(intfile->handle); + fseeko64(intfile->handle, curpos, SEEK_SET); +#elif _POSIX_C_SOURCE >= 200112L off_t curpos; qofs_t maxlen; curpos = ftello(intfile->handle); @@ -122,8 +133,12 @@ vfsfile_t *FSSTDIO_OpenTemp(void) file->funcs.Close = VFSSTDIO_CloseTemp; strcpy((char*)(file+1), fname); free(fname); +#else +#ifdef __USE_LARGEFILE64 + f = tmpfile64(); #else f = tmpfile(); +#endif if (!f) return NULL; @@ -189,7 +204,11 @@ vfsfile_t *VFSSTDIO_Open(const char *osname, const char *mode, qboolean *needsfl #endif newmode[modec++] = '\0'; +#ifdef __USE_LARGEFILE64 + f = fopen64(osname, newmode); +#else f = fopen(osname, newmode); +#endif if (!f) return NULL; @@ -298,7 +317,7 @@ static unsigned int QDECL FSSTDIO_CreateLoc(searchpathfuncs_t *handle, flocation static unsigned int QDECL FSSTDIO_FLocate(searchpathfuncs_t *handle, flocation_t *loc, const char *filename, void *hashedresult) { stdiopath_t *sp = (void*)handle; - int len; + qofs_t len; char netpath[MAX_OSPATH]; if (hashedresult && (void *)hashedresult != handle) @@ -326,12 +345,24 @@ static unsigned int QDECL FSSTDIO_FLocate(searchpathfuncs_t *handle, flocation_t } #else { +#ifdef __USE_LARGEFILE64 + FILE *f = fopen64(netpath, "rb"); +#else FILE *f = fopen(netpath, "rb"); +#endif if (!f) return FF_NOTFOUND; +#ifdef __USE_LARGEFILE64 + fseeko64(f, 0, SEEK_END); + len = ftello64(f); +#elif _POSIX_C_SOURCE >= 200112L + fseeko(f, 0, SEEK_END); + len = ftello(f); +#else fseek(f, 0, SEEK_END); len = ftell(f); +#endif fclose(f); } #endif @@ -349,10 +380,20 @@ static void QDECL FSSTDIO_ReadFile(searchpathfuncs_t *handle, flocation_t *loc, FILE *f; size_t result; +#ifdef __USE_LARGEFILE64 + f = fopen64(loc->rawname, "rb"); +#else f = fopen(loc->rawname, "rb"); +#endif if (!f) //err... return; +#ifdef __USE_LARGEFILE64 + fseeko64(f, loc->offset, SEEK_SET); +#elif _POSIX_C_SOURCE >= 200112L + fseeko(f, loc->offset, SEEK_SET); +#else fseek(f, loc->offset, SEEK_SET); +#endif result = fread(buffer, 1, loc->len, f); // do soemthing with result if (result != loc->len) diff --git a/engine/common/log.c b/engine/common/log.c index 8e92dc17a..32be33233 100644 --- a/engine/common/log.c +++ b/engine/common/log.c @@ -791,6 +791,7 @@ qboolean CertLog_ConnectOkay(const char *hostname, void *cert, size_t certsize, if (certlog_curprompt) return false; + COM_AssertMainThread("CertLog_ConnectOkay"); if (!certlog_inited) CertLog_Import(NULL); diff --git a/engine/common/net_ssl_gnutls.c b/engine/common/net_ssl_gnutls.c index b1d54a710..49e6b1672 100644 --- a/engine/common/net_ssl_gnutls.c +++ b/engine/common/net_ssl_gnutls.c @@ -517,7 +517,6 @@ static int QDECL SSL_CheckCert(gnutls_session_t session) gnutlsfile_t *file = qgnutls_session_get_ptr (session); unsigned int certstatus; qboolean preverified = false; - int errcode = GNUTLS_E_CERTIFICATE_ERROR; size_t knownsize; qbyte *knowndata = TLS_GetKnownCertificate(file->certname, &knownsize); @@ -576,23 +575,31 @@ static int QDECL SSL_CheckCert(gnutls_session_t session) #ifdef GNUTLS_HAVE_VERIFY3 if (qgnutls_certificate_verify_peers3(session, file->certname, &certstatus) >= 0) { + gnutls_datum_t out = {NULL,0}; + gnutls_certificate_type_t type; + int ret; + + if (preverified && (certstatus&~GNUTLS_CERT_EXPIRED) == (GNUTLS_CERT_INVALID|GNUTLS_CERT_SIGNER_NOT_FOUND)) + return 0; + ret = SSL_CheckUserTrust(session, file, certstatus); + if (!ret) + return ret; + + type = qgnutls_certificate_type_get (session); + if (qgnutls_certificate_verification_status_print(certstatus, type, &out, 0) >= 0) { - gnutls_datum_t out; - gnutls_certificate_type_t type; - int ret; - - if (preverified && (certstatus&~GNUTLS_CERT_EXPIRED) == (GNUTLS_CERT_INVALID|GNUTLS_CERT_SIGNER_NOT_FOUND)) - return 0; - ret = SSL_CheckUserTrust(session, file, certstatus); - if (!ret) - return ret; - - type = qgnutls_certificate_type_get (session); - if (qgnutls_certificate_verification_status_print(certstatus, type, &out, 0) >= 0) - { - Con_Printf(CON_ERROR "%s: %s (%x)\n", file->certname, out.data, certstatus); -//looks like its static anyway. qgnutls_free(out.data); + Con_Printf(CON_ERROR "%s: %s (%x)\n", file->certname, out.data, certstatus); + (*qgnutls_free)(out.data); + } + else + Con_Printf(CON_ERROR "%s: UNKNOWN STATUS (%x)\n", file->certname, certstatus); + if (tls_ignorecertificateerrors.ival) + { + Con_Printf(CON_ERROR "%s: Ignoring certificate errors (tls_ignorecertificateerrors is %i)\n", file->certname, tls_ignorecertificateerrors.ival); + return 0; + } + } #else if (qgnutls_certificate_verify_peers2(session, &certstatus) >= 0) { @@ -625,7 +632,6 @@ static int QDECL SSL_CheckCert(gnutls_session_t session) Con_Printf(CON_ERROR "%s: Certificate signature failure\n", file->certname); else Con_Printf(CON_ERROR "%s: Certificate error\n", file->certname); -#endif if (tls_ignorecertificateerrors.ival) { Con_Printf(CON_ERROR "%s: Ignoring certificate errors (tls_ignorecertificateerrors is %i)\n", file->certname, tls_ignorecertificateerrors.ival); @@ -636,9 +642,10 @@ static int QDECL SSL_CheckCert(gnutls_session_t session) Con_DPrintf(CON_ERROR "%s: certificate is for a different domain\n", file->certname); } } +#endif Con_DPrintf(CON_ERROR "%s: rejecting certificate\n", file->certname); - return errcode; + return GNUTLS_E_CERTIFICATE_ERROR; } //return 1 to read data. @@ -1052,6 +1059,7 @@ static qboolean SSL_LoadPrivateCert(gnutls_certificate_credentials_t cred) qboolean SSL_InitGlobal(qboolean isserver) { + int err; static int initstatus[2]; isserver = !!isserver; if (COM_CheckParm("-notls")) @@ -1087,7 +1095,9 @@ qboolean SSL_InitGlobal(qboolean isserver) qgnutls_certificate_allocate_credentials (&xcred[isserver]); #ifdef GNUTLS_HAVE_SYSTEMTRUST - qgnutls_certificate_set_x509_system_trust (xcred[isserver]); + err = qgnutls_certificate_set_x509_system_trust (xcred[isserver]); + if (err <= 0) + Con_Printf("gnutls_certificate_set_x509_system_trust: error %i.\n", err); #else qgnutls_certificate_set_x509_trust_file (xcred[isserver], CAFILE, GNUTLS_X509_FMT_PEM); #endif @@ -1227,7 +1237,7 @@ int GNUTLS_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize) gnutls_datum_t cb; gnutlsfile_t *f = (gnutlsfile_t*)vf; if (vf->Close != SSL_CloseFile) - return -1; //err, not a tls connection. + return -1; //err, not a gnutls connection. if (qgnutls_session_channel_binding(f->session, GNUTLS_CB_TLS_UNIQUE, &cb)) { //error of some kind diff --git a/engine/common/pmove.c b/engine/common/pmove.c index d9f1d5219..688112d2d 100644 --- a/engine/common/pmove.c +++ b/engine/common/pmove.c @@ -1022,7 +1022,7 @@ void PM_CategorizePosition (void) VectorMA (pmove.origin, 24, flatforward, fwd1); pmove.physents[0].model->funcs.NativeTrace(pmove.physents[0].model, 0, PE_FRAMESTATE, NULL, pmove.origin, fwd1, pmove.player_mins, pmove.player_maxs, pmove.capsule, MASK_PLAYERSOLID, &t); - if (t.surface && t.surface->flags & Q3SURF_LADDER) + if (t.surface && t.surface->flags & Q3SURFACEFLAG_LADDER) { pmove.onladder = true; pmove.onground = false; // too steep diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 5ace1bc84..688a98940 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -1590,17 +1590,17 @@ void QCBUILTIN PF_cvar_type (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo cvar_t *v = Cvar_FindVar(str); //this builtin MUST NOT create cvars implicitly, otherwise there would be no way to test if it exists. if (v) { - ret |= 1; // CVAR_EXISTS + ret |= CVAR_TYPEFLAG_EXISTS; if(v->flags & CVAR_ARCHIVE) - ret |= 2; // CVAR_TYPE_SAVED + ret |= CVAR_TYPEFLAG_SAVED; if(v->flags & (CVAR_NOTFROMSERVER|CVAR_NOUNSAFEEXPAND)) - ret |= 4; // CVAR_TYPE_PRIVATE + ret |= CVAR_TYPEFLAG_PRIVATE; if(!(v->flags & CVAR_USERCREATED)) - ret |= 8; // CVAR_TYPE_ENGINE + ret |= CVAR_TYPEFLAG_ENGINE; if (v->description) - ret |= 16; // CVAR_TYPE_HASDESCRIPTION + ret |= CVAR_TYPEFLAG_HASDESCRIPTION; if (v->flags & CVAR_NOSET) - ret |= 32; // CVAR_TYPE_READONLY + ret |= CVAR_TYPEFLAG_READONLY; } G_FLOAT(OFS_RETURN) = ret; } @@ -4114,7 +4114,15 @@ void QCBUILTIN PF_ftoi (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) } void QCBUILTIN PF_itof (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { - G_FLOAT(OFS_RETURN) = G_INT(OFS_PARM0); + if (prinst->callargc > 1) + { + unsigned int value = G_INT(OFS_PARM0); + unsigned int shift = G_FLOAT(OFS_PARM1); + unsigned int count = G_FLOAT(OFS_PARM2); + G_FLOAT(OFS_RETURN) = (value >> shift) & ((1u< simulation time*/ \ + globalfloat (cltime) /*float Clientside map uptime indepent of gamespeed, latency, and the server in general*/ \ + globalfloat (clframetime) /*float time since last video frame*/ \ + globalfloat (servertime) /*float Server time of latest inbound network frame*/ \ + globalfloat (serverprevtime) /*float Server time of previous inbound network frame */ \ + globalfloat (serverdeltatime) /*float new-old */ \ + globalfloat (physics_mode) /*float Written before entering most qc functions*/ \ + globalentity(self) /*entity Written before entering most qc functions*/ \ + globalentity(other) /*entity Written before entering most qc functions*/ \ + \ + globalfloat (deathmatch) /*for simplecsqc*/ \ + globalfloat (coop) /*for simplecsqc*/ \ + \ + globalfloat (maxclients) /*float max number of players allowed*/ \ + globalfloat (numclientseats) /*float number of seats/splitscreen clients running on this client*/ \ + \ + globalvector(v_forward) /*vector written by anglevectors*/ \ + globalvector(v_right) /*vector written by anglevectors*/ \ + globalvector(v_up) /*vector written by anglevectors*/ \ + \ + globalfloat (trace_allsolid) /*bool written by traceline*/ \ + globalfloat (trace_startsolid) /*bool written by traceline*/ \ + globalfloat (trace_fraction) /*float written by traceline*/ \ + globalfloat (trace_inwater) /*bool written by traceline*/ \ + globalfloat (trace_inopen) /*bool written by traceline*/ \ + globalvector(trace_endpos) /*vector written by traceline*/ \ + globalvector(trace_plane_normal) /*vector written by traceline*/ \ + globalfloat (trace_plane_dist) /*float written by traceline*/ \ + globalentity(trace_ent) /*entity written by traceline*/ \ + globalint (trace_surfaceflagsi) /*int written by traceline*/ \ + globalstring(trace_surfacename) /*string written by traceline*/ \ + globalint (trace_endcontentsi) /*int written by traceline EXT_CSQC_1*/ \ + globalint (trace_brush_id) /*int written by traceline*/ \ + globalint (trace_brush_faceid) /*int written by traceline*/ \ + globalint (trace_surface_id) /*int written by traceline*/ \ + globalint (trace_bone_id) /*int written by traceline*/ \ + globalint (trace_triangle_id) /*int written by traceline*/ \ + globalfloat (trace_networkentity) /*float written by traceline*/ \ + legacycsqcglobals \ + \ + globalfloat(clientcommandframe) /*float the next frame that will be sent*/ \ + globalfloat(servercommandframe) /*float the most recent frame received from the server*/ \ + \ + globalfloat(player_localentnum) /*float the entity number the local player is looking out from*/ \ + globalfloat(player_localnum) /*float the player number of the local player*/ \ + globalfloat(intermission) /*float set when the client receives svc_intermission*/ \ + globalfloat(intermission_time) /*float set when the client receives svc_intermission*/ \ + globalvector(view_angles) /*float set to the view angles at the start of each new frame (EXT_CSQC_1)*/ \ + \ + globalvector(pmove_org) /*deprecated. read/written by runplayerphysics*/ \ + globalvector(pmove_vel) /*deprecated. read/written by runplayerphysics*/ \ + globalvector(pmove_mins) /*deprecated. read/written by runplayerphysics*/ \ + globalvector(pmove_maxs) /*deprecated. read/written by runplayerphysics*/ \ + globalfloat (pmove_jump_held) /*deprecated. read/written by runplayerphysics*/ \ + globalfloat (pmove_waterjumptime) /*deprecated. read/written by runplayerphysics*/ \ + globalfloat (pmove_onground) /*deprecated. read/written by runplayerphysics*/ \ + \ + globalfloat (input_timelength) /*float filled by getinputstate, read by runplayerphysics*/ \ + globalvector(input_angles) /*vector filled by getinputstate, read by runplayerphysics*/ \ + globalvector(input_movevalues) /*vector filled by getinputstate, read by runplayerphysics*/ \ + globalfloat (input_buttons) /*float filled by getinputstate, read by runplayerphysics*/ \ + globalfloat (input_impulse) /*float filled by getinputstate, read by runplayerphysics*/ \ + globalfloat (input_lightlevel) /*unused float filled by getinputstate, read by runplayerphysics*/ \ + globalfloat (input_weapon) /*unused float filled by getinputstate, read by runplayerphysics*/ \ + globalfloat (input_servertime) /*float filled by getinputstate, read by runplayerphysics*/ \ + globalfloat (input_clienttime) /*float filled by getinputstate, read by runplayerphysics*/ \ + globalvector(input_cursor_screen) /*float filled by getinputstate*/ \ + globalvector(input_cursor_trace_start) /*float filled by getinputstate*/ \ + globalvector(input_cursor_trace_endpos) /*float filled by getinputstate*/ \ + globalfloat (input_cursor_entitynumber) /*float filled by getinputstate*/ \ + \ + globalvector(global_gravitydir) /*vector used when .gravitydir is 0 0 0 */ \ + globalfloat (dimension_default) /*float default value for dimension_hit+dimension_solid*/ \ + globalfloat (autocvar_vid_conwidth) /*float hackfix for dp mods*/ \ + globalfloat (autocvar_vid_conheight) /*float hackfix for dp mods*/ \ + globalfloat (cycle_wrapped) \ + ENDLIST + + #ifdef __cplusplus }; #endif diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 402ffc06a..207b859e7 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -326,7 +326,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svcfte_brushedit 87 // networked brush editing, paired with clcfte_brushedit. #define svcfte_updateseats 88 // byte count, byte playernum[count] #define svcfte_setinfoblob 89 // [8] 1-based index [string] key [32] isfinal<<31|offset [16] chunksize [chunksize] data - +#define svcfte_cgamepacket_sized 90 //svcfte_cgamepacket with an extra short size right after the svc. +#define svcfte_temp_entity_sized 91 //svc_temp_entity with an extra short size right after the svc (high bit means nq, unset means qw). +#define svcfte_csqcentities_sized 92 //entity lump for csqc (with size info) //fitz svcs #define svcfitz_skybox 37 diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index c104a5635..bf2d52d40 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -4917,11 +4917,8 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g if (!mod) return; - if (!mod->terrain) - { - if (mod->loadstate == MLS_LOADING) - COM_WorkerPartialSync(mod, &mod->loadstate, MLS_LOADING); - } + if (mod->loadstate == MLS_LOADING) + COM_WorkerPartialSync(mod, &mod->loadstate, MLS_LOADING); if (mod->loadstate != MLS_LOADED) return; diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 7a041d024..48ec3babc 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -7318,7 +7318,7 @@ void R_UnloadShader(shader_t *shader) return; if (shader->uses <= 0) { - Con_Printf("Shader double free (%s %i)\n", shader->name, shader->usageflags); + Con_Printf("Shader double free (%p %s %i)\n", shader, shader->name, shader->usageflags); return; } if (--shader->uses == 0) diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 19309996d..262607bec 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -2319,7 +2319,7 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int ); } - if (!prog || !prog->explicitsyms) + if (prog && !prog->explicitsyms) { //for compat with our vulkan processor, which injects samplers in order to control layouts. const char *defaultsamplernames[] = { diff --git a/engine/gl/gl_vidlinuxglx.c b/engine/gl/gl_vidlinuxglx.c index 2e0271158..e0a929ff5 100644 --- a/engine/gl/gl_vidlinuxglx.c +++ b/engine/gl/gl_vidlinuxglx.c @@ -56,7 +56,11 @@ none of these issues will be fixed by a compositing window manager, because ther #include "quakedef.h" -#ifndef NO_X11 +#ifdef NO_X11 + #ifdef VKQUAKE + rendererinfo_t vkrendererinfo; + #endif +#else #include #include @@ -208,6 +212,7 @@ static struct qXErrorHandler (*pXSetErrorHandler)(XErrorHandler); + int (*pXGetErrorText)(Display *display, int code, char *buffer_return, int length); int (*pXGrabServer)(Display *display); int (*pXUngrabServer)(Display *display); @@ -245,8 +250,8 @@ static struct static int X11_ErrorHandler(Display *dpy, XErrorEvent *e) { char msg[80]; -// XGetErrorText(dpy, e->error_code, msg, sizeof(msg)); *msg = 0; + x11.pXGetErrorText(dpy, e->error_code, msg, sizeof(msg)); Con_Printf(CON_ERROR "XLib Error %d (%s): request %d.%d\n", e->error_code, msg, e->request_code, e->minor_code); return 0; //ignored. } @@ -329,8 +334,9 @@ static qboolean x11_initlib(void) if (x11.lib) { x11.pXSetErrorHandler = Sys_GetAddressForName(x11.lib, "XSetErrorHandler"); + x11.pXGetErrorText = Sys_GetAddressForName(x11.lib, "XGetErrorText"); - if (x11.pXSetErrorHandler) + if (x11.pXSetErrorHandler && x11.pXGetErrorText) x11.pXSetErrorHandler(X11_ErrorHandler); //raw input (yay mouse deltas) @@ -872,7 +878,7 @@ static void XRandR_RevertMode(void) { x11.pXGrabServer(vid_dpy); if (xrandr.nvidiabug == 1) - { + { //attempt to undo at least part of the damage we inflicted to work around nvidia's defects. if (Success == xrandr.pSetCrtcConfig(vid_dpy, xrandr.res, xrandr.crtc, CurrentTime, c->x, c->y, None, c->rotation, NULL, 0)) xrandr.pSetScreenSize(vid_dpy, DefaultRootWindow(vid_dpy), xrandr.origscreenwidth, xrandr.origscreenheight, xrandr.origscreenwidthmm, xrandr.origscreenheightmm); } @@ -1137,13 +1143,13 @@ static void XRandR_SelectMode(const char *devicename, int *x, int *y, int *width if (xrandr.nvidiabug && (c->x != 0 || c->y != 0 || c->noutput>1)) { - Con_Printf("Nvidia and multimonitor detected. XRandR cannot be used safely under in this situation.\n"); + Con_Printf("Nvidia and multimonitor detected. XRandR cannot be used safely in this situation.\n"); xrandr.crtcmode = NULL; } else { if (xrandr.nvidiabug) - Con_Printf(CON_ERROR "Attempting NVIDIA panning workaround. Try 'xrandr --output foo --auto' to fix if this goes south..\n"); + Con_Printf(CON_ERROR "Attempting NVIDIA panning workaround. Try 'xrandr --output foo --auto' to fix if this breaks things.\n"); fullscreenflags |= FULLSCREEN_XRANDR; if (XRandR_ApplyMode()) @@ -3639,6 +3645,7 @@ static qboolean XCursor_Init(void) #else static qboolean XCursor_Init(void) { + return false; } #endif diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index bec318496..1618880c4 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -835,45 +835,60 @@ void NPP_NQFlush(void) break; case svcfte_cgamepacket: - if (writedest != &sv.multicast) + if (sv_csqcdebug.ival || writedest != &sv.multicast) { - Con_Printf(CON_WARNING"Warning: svc_cgamepacket used outside of a multicast\n"); - if (sv.csqcdebug) - { - /*shift the data up by two bytes*/ - memmove(buffer+3, buffer+1, bufferlen-1); + if (writedest != &sv.multicast) + Con_Printf(CON_WARNING"Warning: svc_cgamepacket used outside of a multicast\n"); + /*shift the data up by two bytes*/ + memmove(buffer+3, buffer+1, bufferlen-1); - /*add a length in the 2nd/3rd bytes*/ - buffer[1] = (bufferlen-1); - buffer[2] = (bufferlen-1) >> 8; + buffer[0] = svcfte_cgamepacket_sized; + /*add a length in the 2nd/3rd bytes*/ + buffer[1] = (bufferlen-1); + buffer[2] = (bufferlen-1) >> 8; - bufferlen += 2; - } + bufferlen += 2; + if(multicastpos) multicastpos += 2; } break; case svc_temp_entity: + if (sv_csqcdebug.ival) + { + if (te_515sevilhackworkaround && writedest != &sv.multicast) + Con_Printf(CON_WARNING"Warning: unknown svc_temp_entity used outside of a multicast\n"); + /*shift the data up by two bytes, but don't care about the first byte*/ + memmove(buffer+3, buffer+1, bufferlen-1); + + buffer[0] = svcfte_temp_entity_sized; + /*add a length in the 2nd/3rd bytes, if needed*/ + buffer[1] = (bufferlen-1) & 0xff; + buffer[2] = ((bufferlen-1) >> 8); + if (te_515sevilhackworkaround) //we don't know how to translate it, so the qw receiver must be told to interpret as the nq version + buffer[2] |= 0x80; + + bufferlen += 2; + if(multicastpos) multicastpos += 2; + break; + } switch (buffer[1]) { default: if (te_515sevilhackworkaround) { if (writedest != &sv.multicast) - { Con_Printf(CON_WARNING"Warning: unknown svc_temp_entity used outside of a multicast\n"); - if (sv.csqcdebug) - { - /*shift the data up by two bytes, but don't care about the first byte*/ - memmove(buffer+3, buffer+1, bufferlen-1); + /*shift the data up by two bytes, but don't care about the first byte*/ + memmove(buffer+3, buffer+1, bufferlen-1); - /*add a length in the 2nd/3rd bytes, if needed*/ - buffer[1] = (bufferlen-1) & 0xff; - buffer[2] = (bufferlen-1) >> 8; + buffer[0] = svcfte_temp_entity_sized; + /*add a length in the 2nd/3rd bytes, if needed*/ + buffer[1] = (bufferlen-1) & 0xff; + buffer[2] = ((bufferlen-1) >> 8); + if (te_515sevilhackworkaround) //we don't know how to translate it, so the qw receiver must be told to interpret as the nq version + buffer[2] |= 0x80; - bufferlen += 2; - } - } - /*replace the svc itself*/ - buffer[0] = svcfte_cgamepacket; + bufferlen += 2; + if(multicastpos) multicastpos += 2; } break; case TENQ_NQEXPLOSION: @@ -1895,45 +1910,59 @@ void NPP_QWFlush(void) break; case svcfte_cgamepacket: - if (writedest != &sv.nqmulticast) + if (sv_csqcdebug.ival || writedest != &sv.nqmulticast) { - Con_Printf(CON_WARNING"Warning: svc_cgamepacket used outside of a multicast\n"); - if (sv.csqcdebug) - { - /*shift the data up by two bytes*/ - memmove(buffer+3, buffer+1, bufferlen-1); + if (writedest != &sv.nqmulticast) + Con_Printf(CON_WARNING"Warning: svc_cgamepacket used outside of a multicast\n"); + /*shift the data up by two bytes*/ + memmove(buffer+3, buffer+1, bufferlen-1); - /*add a length in the 2nd/3rd bytes*/ - buffer[1] = (bufferlen-1); - buffer[2] = (bufferlen-1) >> 8; + buffer[0] = svcfte_cgamepacket_sized; + /*add a length in the 2nd/3rd bytes*/ + buffer[1] = (bufferlen-1); + buffer[2] = (bufferlen-1) >> 8; - bufferlen += 2; - } + bufferlen += 2; + if(multicastpos) multicastpos += 2; } break; case svc_temp_entity: + if (sv_csqcdebug.ival) + { + if (te_515sevilhackworkaround && writedest != &sv.multicast) + Con_Printf(CON_WARNING"Warning: unknown svc_temp_entity used outside of a multicast\n"); + /*shift the data up by two bytes, but don't care about the first byte*/ + memmove(buffer+3, buffer+1, bufferlen-1); + + buffer[0] = svcfte_temp_entity_sized; + /*add a length in the 2nd/3rd bytes, if needed*/ + buffer[1] = (bufferlen-1) & 0xff; + buffer[2] = (bufferlen-1) >> 8; + if (!te_515sevilhackworkaround) //we translated it from qw, let the client know that its now the nq version + buffer[2] |= 0x80; + + bufferlen += 2; + if(multicastpos) multicastpos += 2; + break; + } switch(minortype) { default: if (te_515sevilhackworkaround) { - if (writedest != &sv.nqmulticast) - { - Con_Printf(CON_WARNING"Warning: unknown svc_temp_entity used outside of a multicast\n"); - if (sv.csqcdebug) - { - /*shift the data up by two bytes*/ - memmove(buffer+3, buffer+1, bufferlen-1); + Con_Printf(CON_WARNING"Warning: unknown svc_temp_entity used outside of a multicast\n"); + /*shift the data up by two bytes*/ + memmove(buffer+3, buffer+1, bufferlen-1); - /*add a length in the 2nd/3rd bytes*/ - buffer[1] = (bufferlen-1); - buffer[2] = (bufferlen-1) >> 8; + buffer[0] = svcfte_temp_entity_sized; + /*add a length in the 2nd/3rd bytes*/ + buffer[1] = (bufferlen-1); + buffer[2] = (bufferlen-1) >> 8; + if (!te_515sevilhackworkaround) //we translated it from qw, let the client know that its now the nq version + buffer[2] |= 0x80; - bufferlen += 2; - } - } - /*replace the svc itself*/ - buffer[0] = svcfte_cgamepacket; + bufferlen += 2; + if(multicastpos) multicastpos += 2; } break; case TEQW_LIGHTNINGBLOOD: @@ -2249,7 +2278,9 @@ void NPP_QWWriteByte(int dest, qbyte data) //replacement write func (nq to qw) break; default: protocollen = sizeof(buffer); - Con_Printf("QWWriteByte: bad tempentity - %i\n", data); + if (writedest != &sv.nqmulticast) + Con_Printf("QWWriteByte: bad tempentity - %i\n", data); + te_515sevilhackworkaround = true; break; } break; diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index e736f9fa8..fda5b91b1 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -987,6 +987,12 @@ void PR_LoadGlabalStruct(qboolean muted) globalvec (false, global_gravitydir); globalstring (false, parm_string); +#undef globalfloat +#undef globalint +#undef globalstring +#undef globalvec +#undef globalfunc + memset(&evalc_idealpitch, 0, sizeof(evalc_idealpitch)); memset(&evalc_pitch_speed, 0, sizeof(evalc_pitch_speed)); @@ -4055,12 +4061,12 @@ stuffcmd (clientent, value) */ static void QCBUILTIN PF_stuffcmd (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { - PF_stuffcmd_Internal(G_EDICTNUM(prinst, OFS_PARM0), PR_GetStringOfs(prinst, OFS_PARM1), 0); + PF_stuffcmd_Internal(G_EDICTNUM(prinst, OFS_PARM0), PF_VarString(prinst, 1, pr_globals), 0); } static void QCBUILTIN PF_stuffcmdflags (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { - PF_stuffcmd_Internal(G_EDICTNUM(prinst, OFS_PARM0), PR_GetStringOfs(prinst, OFS_PARM2), G_FLOAT(OFS_PARM1)); + PF_stuffcmd_Internal(G_EDICTNUM(prinst, OFS_PARM0), PF_VarString(prinst, 2, pr_globals), G_FLOAT(OFS_PARM1)); } //DP_QC_DROPCLIENT @@ -6168,53 +6174,55 @@ char *PF_infokey_Internal (int entnum, const char *key) } else if (entnum <= sv.allocated_client_slots) { + client_t *pl = &svs.clients[entnum-1]; + client_t *controller = pl->controller?pl->controller:pl; value = ov; if (!strcmp(key, "ip")) { - if (svs.clients[entnum-1].state > cs_zombie && svs.clients[entnum-1].protocol == SCP_BAD) + if (controller->state > cs_zombie && controller->protocol == SCP_BAD) sprintf(ov, "bot"); //bots don't have valid ips - else if (svs.clients[entnum-1].netchan.remote_address.type == NA_INVALID) + else if (controller->netchan.remote_address.type == NA_INVALID) sprintf(ov, ""); //bots don't have valid ips else - NET_BaseAdrToString (ov, sizeof(ov), &svs.clients[entnum-1].netchan.remote_address); + NET_BaseAdrToString (ov, sizeof(ov), &controller->netchan.remote_address); } else if (!strcmp(key, "realip")) { - if (svs.clients[entnum-1].state > cs_zombie && svs.clients[entnum-1].protocol == SCP_BAD) + if (pl->state > cs_zombie && controller->protocol == SCP_BAD) sprintf(ov, "bot"); //bots don't have valid ips - else if (svs.clients[entnum-1].realip_status) - NET_BaseAdrToString (ov, sizeof(ov), &svs.clients[entnum-1].realip); - else if (svs.clients[entnum-1].netchan.remote_address.type == NA_INVALID) + else if (controller->realip_status) + NET_BaseAdrToString (ov, sizeof(ov), &controller->realip); + else if (controller->netchan.remote_address.type == NA_INVALID) sprintf(ov, ""); //bots don't have valid ips else //FIXME: should we report the spoofable/proxy address if the real ip is not known? - NET_BaseAdrToString (ov, sizeof(ov), &svs.clients[entnum-1].netchan.remote_address); + NET_BaseAdrToString (ov, sizeof(ov), &controller->netchan.remote_address); } else if (!strcmp(key, "csqcactive")) - sprintf(ov, "%d", svs.clients[entnum-1].csqcactive); + sprintf(ov, "%d", controller->csqcactive); else if (!strcmp(key, "ping")) sprintf(ov, "%d", SV_CalcPing (&svs.clients[entnum-1], false)); else if (!strcmp(key, "svping")) sprintf(ov, "%d", SV_CalcPing (&svs.clients[entnum-1], true)); else if (!strcmp(key, "guid")) - sprintf(ov, "%s", svs.clients[entnum-1].guid); + sprintf(ov, "%s", pl->guid); else if (!strcmp(key, "challenge")) - sprintf(ov, "%u", svs.clients[entnum-1].challenge); + sprintf(ov, "%u", pl->challenge); else if (!strcmp(key, "*userid")) - sprintf(ov, "%d", svs.clients[entnum-1].userid); + sprintf(ov, "%d", pl->userid); else if (!strcmp(key, "download")) - sprintf(ov, "%d", svs.clients[entnum-1].download != NULL ? (int)(100*svs.clients[entnum-1].downloadcount/svs.clients[entnum-1].downloadsize) : -1); + sprintf(ov, "%d", pl->download != NULL ? (int)(100*pl->downloadcount/pl->downloadsize) : -1); // else if (!strcmp(key, "login")) //mvdsv // value = ""; else if (!strcmp(key, "protocol")) { value = ""; - switch(svs.clients[entnum-1].protocol) + switch(controller->protocol) { case SCP_BAD: value = ""; //could be a writebyted bot... break; case SCP_QUAKEWORLD: - if (!svs.clients[entnum-1].fteprotocolextensions && !svs.clients[entnum-1].fteprotocolextensions2) + if (!controller->fteprotocolextensions && !controller->fteprotocolextensions2) value = "quakeworld"; else value = "quakeworld+"; @@ -6232,7 +6240,7 @@ char *PF_infokey_Internal (int entnum, const char *key) value = "bjp3"; break; case SCP_FITZ666: - if (svs.clients[entnum-1].netchan.netprim.coordtype != COORDTYPE_FIXED_13_3) + if (controller->netchan.netprim.coordtype != COORDTYPE_FIXED_13_3) value = "rmq999"; else value = "fitz666"; @@ -6249,28 +6257,28 @@ char *PF_infokey_Internal (int entnum, const char *key) { #ifdef SVRANKING rankstats_t rs; - if (!svs.clients[entnum-1].rankid) + if (!pl->rankid) value = ""; - else if (Rank_GetPlayerStats(svs.clients[entnum-1].rankid, &rs)) + else if (Rank_GetPlayerStats(pl->rankid, &rs)) sprintf(ov, "%d", rs.trustlevel); else #endif value = ""; } else if (!strcmp(key, "*VIP")) - value = (svs.clients[entnum-1].penalties & BAN_VIP)?"1":""; + value = (pl->penalties & BAN_VIP)?"1":""; else if (!strcmp(key, "*ismuted")) - value = (svs.clients[entnum-1].penalties & BAN_MUTE)?"1":""; + value = (pl->penalties & BAN_MUTE)?"1":""; else if (!strcmp(key, "*isdeaf")) - value = (svs.clients[entnum-1].penalties & BAN_DEAF)?"1":""; + value = (pl->penalties & BAN_DEAF)?"1":""; else if (!strcmp(key, "*iscrippled")) - value = (svs.clients[entnum-1].penalties & BAN_CRIPPLED)?"1":""; + value = (pl->penalties & BAN_CRIPPLED)?"1":""; else if (!strcmp(key, "*iscuffed")) - value = (svs.clients[entnum-1].penalties & BAN_CUFF)?"1":""; + value = (pl->penalties & BAN_CUFF)?"1":""; else if (!strcmp(key, "*islagged")) - value = (svs.clients[entnum-1].penalties & BAN_LAGGED)?"1":""; + value = (pl->penalties & BAN_LAGGED)?"1":""; else - value = InfoBuf_ValueForKey (&svs.clients[entnum-1].userinfo, key); + value = InfoBuf_ValueForKey (&pl->userinfo, key); } else value = ""; @@ -6412,10 +6420,10 @@ void QCBUILTIN PF_multicast (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo NPP_Flush(); #endif - if (sv.csqcdebug) + if (sv_csqcdebug.ival) { #ifdef NQPROT - if (sv.nqmulticast.cursize && sv.nqmulticast.data[0] == svcfte_cgamepacket) + if (sv.nqmulticast.cursize && (sv.nqmulticast.data[0] == svcfte_cgamepacket||sv.nqmulticast.data[0] == svc_temp_entity)) { if (sv.nqmulticast.cursize + 2 > sv.nqmulticast.maxsize) sv.nqmulticast.cursize = 0; @@ -6425,6 +6433,10 @@ void QCBUILTIN PF_multicast (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo memmove(sv.nqmulticast.data+3, sv.nqmulticast.data+1, sv.nqmulticast.cursize-1); /*add a length in the 2nd/3rd bytes*/ + if (sv.nqmulticast.data[0] == svc_temp_entity) + sv.nqmulticast.data[0] = svcfte_temp_entity_sized; + else + sv.nqmulticast.data[0] = svcfte_cgamepacket_sized; sv.nqmulticast.data[1] = (sv.nqmulticast.cursize-1); sv.nqmulticast.data[2] = (sv.nqmulticast.cursize-1) >> 8; @@ -6432,7 +6444,7 @@ void QCBUILTIN PF_multicast (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo } } #endif - if (sv.multicast.cursize) + if (sv.multicast.cursize && (sv.multicast.data[0] == svcfte_cgamepacket||sv.multicast.data[0] == svc_temp_entity)) { if (sv.multicast.cursize + 2 > sv.multicast.maxsize) sv.multicast.cursize = 0; @@ -6442,6 +6454,10 @@ void QCBUILTIN PF_multicast (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo memmove(sv.multicast.data+3, sv.multicast.data+1, sv.multicast.cursize-1); /*add a length in the 2nd/3rd bytes*/ + if (sv.multicast.data[0] == svc_temp_entity) + sv.multicast.data[0] = svcfte_temp_entity_sized; + else + sv.multicast.data[0] = svcfte_cgamepacket_sized; sv.multicast.data[1] = (sv.multicast.cursize-1); sv.multicast.data[2] = (sv.multicast.cursize-1) >> 8; @@ -7216,7 +7232,7 @@ static void QCBUILTIN PF_readcmd (pubprogfuncs_t *prinst, struct globalvars_s *p SV_BeginRedirect(RD_OBLIVION, TL_FindLanguage("")); Cbuf_Execute(); - Con_Printf("PF_readcmd: %s\n%s", s, sv_redirected_buf); + Con_Printf("PF_readcmd: %s\n", s); G_INT(OFS_RETURN) = (int)PR_TempString(prinst, sv_redirected_buf); SV_EndRedirect(); @@ -10433,7 +10449,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"localcmd", PF_Fixme, 0, 0, 0, 13, "void(string,...)"}, {"cvar", PF_Fixme, 0, 0, 0, 14, "float(string name)"}, {"cvar_set", PF_Fixme, 0, 0, 0, 15, "void(string name, string value)"}, - {"dprint", PF_Fixme, 0, 0, 0, 16, "void(string text)"}, + {"dprint", PF_Fixme, 0, 0, 0, 16, "void(string text, ...)"}, {"ftos", PF_Fixme, 0, 0, 0, 17, "string(float)"}, {"fabs", PF_Fixme, 0, 0, 0, 18, "float(float)"}, {"vtos", PF_Fixme, 0, 0, 0, 19, "string(vector)"}, @@ -10538,8 +10554,8 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs #endif {"precache_sound", PF_precache_sound, 19, 19, 19, 0, D("string(string s)", "Precaches a sound, making it known to clients and loading it from disk. This builtin (strongly) should be called during spawn functions. This builtin must be called for the sound before the sound builtin is called, or it might not even be heard.")}, {"precache_model", PF_precache_model, 20, 20, 20, 0, D("string(string s)", "Precaches a model, making it known to clients and loading it from disk if it has a .bsp extension. This builtin (strongly) should be called during spawn functions. This must be called for each model name before setmodel may use that model name.\nModelindicies precached in SSQC will always be positive. CSQC precaches will be negative if they are not also on the server.")}, - {"stuffcmd", PF_stuffcmd, 21, 21, 21, 0, D("void(entity client, string s)", "Sends a console command (or cvar) to the client, where it will be executed. Different clients support different commands. Do NOT forget the final \\n.\nThis builtin is generally considered evil.")}, - {"stuffcmdflags", PF_stuffcmdflags, 0, 0, 0, 0, D("void(entity client, float flags, string s)", "Sends a console command (or cvar) to the client, where it will be executed. Different clients support different commands. Do NOT forget the final \\n.\nThis (just as evil) variant allows specifying some flags too. See the STUFFCMD_* constants.")}, + {"stuffcmd", PF_stuffcmd, 21, 21, 21, 0, D("void(entity client, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7)", "Sends a console command (or cvar) to the client, where it will be executed. Different clients support different commands. Do NOT forget the final \\n.\nThis builtin is generally considered evil.")}, + {"stuffcmdflags", PF_stuffcmdflags, 0, 0, 0, 0, D("void(entity client, float flags, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6)", "Sends a console command (or cvar) to the client, where it will be executed. Different clients support different commands. Do NOT forget the final \\n.\nThis (just as evil) variant allows specifying some flags too. See the STUFFCMD_* constants.")}, {"findradius", PF_findradius, 22, 22, 22, 0, D(/*"FTEDEP(\"Has recursion issues. Use findradius_list.\") "*/"entity(vector org, float rad, optional .entity chainfield)", "Finds all entities within a distance of the 'org' specified. One entity is returned directly, while other entities are returned via that entity's .chain field. Use findradius_list for an updated alternative without reenterancy issues.")}, #ifdef QCGC {"findradius_list", PF_findradius_list, 0, 0, 0, 0, D("entity*(vector org, float rad, __out int foundcount, int sort=0)", "Finds all entities linked with a bbox within a distance of the 'org' specified, returning the list as a temp-array (world signifies the end). Unlike findradius, sv_gameplayfix_blowupfallenzombies is ignored (use FL_FINDABLE_NONSOLID instead), while sv_gameplayfix_findradiusdistancetobox and dpcompat_findradiusarealinks are force-enabled. The resulting buffer will automatically be cleaned up by the engine and does not need to be freed.")}, @@ -10739,8 +10755,13 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"updatesoundpos", PF_h2updatesoundpos,0, 0, 105, 0}, {"stopsound", PF_StopSound, 0, 0, 106, 0, D("void(entity ent, float channel)", "Terminates playback of sounds on the specified entity-channel. CHAN_AUTO should not be used.")}, - {"precache_model4", PF_precache_model, 0, 0, 116, 0},//please don't use... - {"precache_sound4", PF_precache_sound, 0, 0, 117, 0}, + //shanjaq's fork of uhexen2... listed here to avoid confusion with other builtins. + {"set_extra_flags", PF_Fixme, 0, 0, 107, 0, "void(string model, float flags)"}, + {"set_fx_color", PF_Fixme, 0, 0, 108, 0, "void(string model,float r,float g,float b,float a)"}, + {"strhash", PF_Fixme, 0, 0, 109, 0, "float(string)"}, + + {"precache_model5", PF_precache_model, 0, 0, 116, 0},//please don't use... + {"precache_sound5", PF_precache_sound, 0, 0, 117, 0}, #else {"stopsound", PF_StopSound, 0, 0, 0, 0, D("void(entity ent, float channel)", "Terminates playback of sounds on the specified entity-channel. CHAN_AUTO should not be used.")}, #endif @@ -10910,7 +10931,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"stoh", PF_stoh, 0, 0, 0, 261, D("int(string)", "Reads a base-16 string (with or without 0x prefix) as an integer. Bugs out if given a base 8 or base 10 string. :P")}, {"htos", PF_htos, 0, 0, 0, 262, D("string(int)", "Formats an integer as a base16 string, with leading 0s and no prefix. Always returns 8 characters.")}, {"ftoi", PF_ftoi, 0, 0, 0, 0, D("int(float)", "Converts the given float into a true integer without depending on extended qcvm instructions.")}, - {"itof", PF_itof, 0, 0, 0, 0, D("float(int)", "Converts the given true integer into a float without depending on extended qcvm instructions.")}, + {"itof", PF_itof, 0, 0, 0, 0, D("float(int, optional float shift, float mask=24)", "Converts the given true integer into a float without depending on extended qcvm instructions. If shift and mask are specified then only specific parts of the integer will be cast to float.")}, #define qcskelblend \ "typedef struct\n{\n" \ @@ -11055,10 +11076,11 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"drawrotsubpic", PF_Fixme, 0, 0, 0, 0, D("void(vector pivot, vector mins, vector maxs, string pic, vector txmin, vector txsize, vector rgb, vector alphaandangles)", "Overcomplicated draw function for over complicated people. Positions follow drawrotpic, while texture coords follow drawsubpic. Due to argument count limitations in builtins, the alpha value and angles are combined into separate fields of a vector (tip: use fteqcc's [alpha, angle] feature.")}, //330 - {"getstati", PF_Fixme, 0, 0, 0, 330, D("#define getstati_punf(stnum) (float)(__variant)getstati(stnum)\nint(float stnum)", "Retrieves the numerical value of the given EV_INTEGER or EV_ENTITY stat. Use getstati_punf if you wish to type-pun a float stat as an int to avoid truncation issues in DP.")},// (EXT_CSQC) - {"getstatf", PF_Fixme, 0, 0, 0, 331, D("#define getstatbits getstatf\nfloat(float stnum, optional float firstbit, optional float bitcount)", "Retrieves the numerical value of the given EV_FLOAT stat. If firstbit and bitcount are specified, retrieves the upper bits of the STAT_ITEMS stat (converted into a float, so there are no VM dependancies).")},// (EXT_CSQC) + //NOTE: DP misnamed these to match its common misuse of clientstat, swapping getstatf+getstati. + {"getstati", PF_Fixme, 0, 0, 0, 330, D("#define getstati_punf(stnum) (float)(__variant)getstati(stnum)\nint(float stnum)", "Retrieves the full precision of a stat registered as EV_INTEGER.")},// (EXT_CSQC) + {"getstatf", PF_Fixme, 0, 0, 0, 331, D("#define getstatbits getstatf\nfloat(float stnum, optional float firstbit, optional float bitcount)", "Retrieves the numerical value of the given EV_FLOAT stat. If firstbit and bitcount are specified, then this builtin acts as getstati combined with itof, and which should be used for STAT_ITEMS (but not other stats).")},// (EXT_CSQC) {"getstats", PF_Fixme, 0, 0, 0, 332, D("string(float stnum)", "Retrieves the value of the given EV_STRING stat, as a tempstring.\nOlder engines may use 4 consecutive integer stats, with a limit of 15 chars (yes, really. 15.), but "FULLENGINENAME" uses a separate namespace for string stats and has a much higher length limit.")}, - {"getplayerstat", PF_Fixme, 0, 0, 0, 0, D("__variant(float playernum, float statnum, float stattype)", "Retrieves a specific player's stat, matching the type specified on the server. This builtin is primarily intended for mvd playback where ALL players are known. For EV_ENTITY, world will be returned if the entity is not in the pvs, use type-punning with EV_INTEGER to get the entity number if you just want to see if its set. STAT_ITEMS should be queried as an EV_INTEGER on account of runes and items2 being packed into the upper bits.")}, + {"getplayerstat", PF_Fixme, 0, 0, 0, 0, D("__variant(float playernum, float statnum, float stattype)", "Retrieves a specific player's stat, matching the type specified on the server. This builtin is primarily intended for mvd playback where ALL players are known. Return value matches the specified EV_ stattype. For EV_ENTITY, world will be returned if the entity is not in the pvs, use type-punning with EV_INTEGER to get the entity number if you just want to see if its set. STAT_ITEMS should be queried as an EV_INTEGER on account of runes and items2 being packed into the upper bits.")}, //EXT_CSQC {"setmodelindex", PF_Fixme, 0, 0, 0, 333, D("void(entity e, float mdlindex)", "Sets a model by precache index instead of by name. Otherwise identical to setmodel.")},// @@ -11453,7 +11475,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"fcopy", PF_fcopy, 0, 0, 0, 650, D("float(string src, string dst)", "Equivelent to fopen+fread+fwrite+fclose from QC (ie: reads from $gamedir/data/ or $gamedir, but always writes to $gamedir/data/ )")}, {"frename", PF_frename, 0, 0, 0, 651, D("float(string src, string dst)", "Renames the file, returning 0 on success. Both paths are relative to the data/ subdir.")}, {"fremove", PF_fremove, 0, 0, 0, 652, D("float(string fname)", "Deletes the named file - path is relative to data/ subdir, like fopen's FILE_WRITE. Returns 0 on success.")}, - {"fexists", PF_fexists, 0, 0, 0, 653, D("float(string fname)", "Use whichpack instead. Returns true if it exists inside the default writable path.")}, + {"fexists", PF_fexists, 0, 0, 0, 653, D("float(string fname)", "Returns true if it exists inside the default writable path. Use whichpack for greater portability.")}, {"rmtree", PF_rmtree, 0, 0, 0, 654, D("float(string path)", "Dangerous, but sandboxed to data/")}, {"walkmovedist", PF_walkmovedist, 0, 0, 0, 655, D("DEP float(float yaw, float dist, optional float settraceglobals)", "Attempt to walk the entity at a given angle for a given distance.\nif settraceglobals is set, the trace_* globals will be set, showing the results of the movement.\nThis function will trigger touch events."), true}, //end wrath extras @@ -11897,15 +11919,20 @@ svextqcfields } //targets -#define QW 1 //exists in qwssqc -#define NQ 2 //exists in nqssqc -#define CS 4 //exists in csqc -#define MENU 8 //exists in menuqc -#define H2 16 //exists in h2ssqc -//mere flags -#define FTE 32 //use fte opcodes -#define ID1 64 //symbol conflicts with vanilla defs.qc (so stripped, with exceptions) -#define DPX 128 //symbol conflicts with dpextensions.qc +#define QW (1u<<0) //exists in qwssqc +#define NQ (1u<<1) //exists in nqssqc +#define FTE_CS (1u<<2) //fte's csqc globals (the original) +#define QSS_CS (1u<<3) //qss's csqc globals (really nq, for simplicity) +#define DP_CS (1u<<4) //dp's csqc globals (eww!) +#define MENU (1u<<5) //exists in menuqc +#define H2 (1u<<6) //exists in h2ssqc +//mere flag +#define FTE (1u<<7) //use fte opcodes +#define ID1 (1u<<8) //symbol conflicts with vanilla defs.qc (so stripped, with exceptions) +#define DPX (1u<<9) //symbol conflicts with dpextensions.qc + +#define CS (QSS_CS|FTE_CS|DP_CS) //exists in csqc +#define GAME (QW|NQ|CS|H2) //all but menu #ifdef HEXEN2 #define ALL (QW|NQ|H2|CS|MENU) #else @@ -11926,7 +11953,215 @@ typedef struct qboolean misc; } knowndef_t; #include "cl_master.h" -void Key_PrintQCDefines(vfsfile_t *f); +void Key_PrintQCDefines(vfsfile_t *f, qboolean defines); + +#ifdef SERVERONLY + +#elif defined(NOQCDESCRIPTIONS) && NOQCDESCRIPTIONS > 1 + +#else +static qboolean PR_DumpPlatform_GenIfdef(vfsfile_t *f, unsigned int filetarg, unsigned int symboltarg, unsigned int *curtarg) +{ + if (!(symboltarg & filetarg)) + return false; + if ((symboltarg&filetarg) != (*curtarg&filetarg)) + { + if (*curtarg != (ALL & ~filetarg)) + VFS_PRINTF(f, "#endif\n"); + + if (((symboltarg | (~filetarg)) & ALL) == ALL) + *curtarg = ALL & ~filetarg; + else + { + *curtarg = symboltarg; + symboltarg = *curtarg & (ALL & filetarg); + if (symboltarg & CS) + symboltarg |= CS; + switch(symboltarg) + { + case 0: + return false; + case QW: + VFS_PRINTF(f, "#if defined(QWSSQC)\n"); + break; + case NQ: + VFS_PRINTF(f, "#if defined(NQSSQC)\n"); + break; + case QW|NQ: + VFS_PRINTF(f, "#ifdef SSQC\n"); + break; + case CS: + VFS_PRINTF(f, "#ifdef CSQC\n"); + break; + case QW|CS: + VFS_PRINTF(f, "#if defined(CSQC) || defined(QWSSQC)\n"); + break; + case NQ|CS: + VFS_PRINTF(f, "#if defined(CSQC) || defined(NQSSQC)\n"); + break; + case NQ|CS|QW: + VFS_PRINTF(f, "#if defined(CSQC) || defined(SSQC)\n"); + break; + case MENU: + VFS_PRINTF(f, "#ifdef MENU\n"); + break; + case QW|MENU: + VFS_PRINTF(f, "#if defined(QWSSQC) || defined(MENU)\n"); + break; + case NQ|MENU: + VFS_PRINTF(f, "#if defined(NQSSQC) || defined(MENU)\n"); + break; + case QW|NQ|MENU: + VFS_PRINTF(f, "#if defined(SSQC) || defined(MENU)\n"); + break; + case CS|MENU: + VFS_PRINTF(f, "#if defined(CSQC) || defined(MENU)\n"); + break; + case QW|CS|MENU: + VFS_PRINTF(f, "#if defined(CSQC) || defined(QWSSQC) || defined(MENU)\n"); + break; + case NQ|CS|MENU: + VFS_PRINTF(f, "#if defined(CSQC) || defined(NQSSQC) || defined(MENU)\n"); + break; + case H2: + VFS_PRINTF(f, "#ifdef H2\n"); + break; + case H2|QW: + VFS_PRINTF(f, "#if defined(H2) || defined(QWSSQC)\n"); + break; + case H2|NQ: + VFS_PRINTF(f, "#if defined(H2) || defined(NQSSQC)\n"); + break; + case H2|QW|NQ: + VFS_PRINTF(f, "#if defined(H2) || defined(SSQC)\n"); + break; + case H2|CS: + VFS_PRINTF(f, "#if defined(H2) || defined(CSQC)\n"); + break; + case H2|QW|CS: + VFS_PRINTF(f, "#if defined(H2) || defined(CSQC) || defined(QWSSQC)\n"); + break; + case H2|NQ|CS: + VFS_PRINTF(f, "#if defined(H2) || defined(CSQC) || defined(NQSSQC)\n"); + break; + case H2|NQ|CS|QW: + VFS_PRINTF(f, "#if defined(H2) || defined(CSQC) || defined(SSQC)\n"); + break; + case H2|MENU: + VFS_PRINTF(f, "#if defined(H2) || defined(MENU)\n"); + break; + case H2|QW|MENU: + VFS_PRINTF(f, "#if defined(H2) || defined(QWSSQC) || defined(MENU)\n"); + break; + case H2|NQ|MENU: + VFS_PRINTF(f, "#if defined(H2) || defined(NQSSQC) || defined(MENU)\n"); + break; + case H2|QW|NQ|MENU: + VFS_PRINTF(f, "#if defined(H2) || defined(SSQC) || defined(MENU)\n"); + break; + case H2|CS|MENU: + VFS_PRINTF(f, "#if defined(H2) || defined(CSQC) || defined(MENU)\n"); + break; + case H2|QW|CS|MENU: + VFS_PRINTF(f, "#if defined(H2) || defined(CSQC) || defined(QWSSQC) || defined(MENU)\n"); + break; + case H2|NQ|CS|MENU: + VFS_PRINTF(f, "#if defined(H2) || defined(CSQC) || defined(NQSSQC) || defined(MENU)\n"); + break; + case ALL: + VFS_PRINTF(f, "#if 1\n"); + break; + default: + VFS_PRINTF(f, "#if 0 //???\n"); + break; + } + } + } + return true; +} + +struct symtable_s +{ + unsigned int targ; + const char *fname; //filename to read symbol list from. + const char *warning; //text inserted before the symbol name. generally terse. + const char *define; //optional text to insert at top-level (to match the warning). + const char *symbols; +}; +static void PR_DumpPlatform_LoadSymbolTables(vfsfile_t *outfile, struct symtable_s *symtabs, unsigned int targ) +{ + char *i, *o; + qofs_t sz; + char *f; + for (; symtabs->fname; symtabs++) + { + if (!(symtabs->targ & targ)) + continue; + if (!symtabs->warning) + continue; + f = FS_MallocFile(symtabs->fname, FS_GAME, &sz); + if (f) + { + i = f; + symtabs->symbols = o = Z_Malloc(sz + 16); + + #define iswhite(c) ((c) == ' ' || (c) == '\r' || (c) == '\r' || (c) == '\n') + + *o++ = '\n'; + while (*i) + { + while (iswhite(*i)) + i++; + while (*i && !iswhite(*i)) + *o++ = *i++; + *o++ = '\n'; + } + *o = 0; + FS_FreeFile(f); + + if (symtabs->define) + VFS_PRINTF(outfile, "%s", symtabs->define); + } + } +} +static void PR_DumpPlatform_SymbolType(vfsfile_t *f, const struct symtable_s *symtabs, const char *symtype, const char *symbol) +{ //prefixes any symbols with the engines that they're not in... + int symstart = 0; + const char *colon; + + //we need to skip over any #defines prefixed to the type string + while(symtype[symstart] == '#') + { + while (symtype[symstart] && symtype[symstart] != '\n') + symstart++; + if (symtype[symstart]) + symstart++; //skip over the \n + } + //skip over any "typedef struct {...;};\n" blocks in there + while ((colon = strstr(symtype+symstart, ";\n"))) + symstart = colon+2 - symtype; + + //write those prefixes we tried to skip... + VFS_WRITE(f, symtype, symstart); + symtype += symstart; + + //now write our modifiers + symbol = va("\n%s\n", symbol); + for (; symtabs->fname; symtabs++) + { + if (!symtabs->symbols) + continue; + + if (strstr(symtabs->symbols, symbol)) + continue; + VFS_PRINTF(f, "%s ", symtabs->warning); + } + + //and write the rest of the type. + VFS_PRINTF(f, "%s ", symtype); +} +#endif + void PR_DumpPlatform_f(void) { #ifdef SERVERONLY @@ -11965,8 +12200,19 @@ void PR_DumpPlatform_f(void) unsigned int targ = 0; qboolean defines = false; qboolean accessors = false; + qboolean depfilter = false; char *comment; + struct symtable_s symtab[] = { + {NQ, "qss_ss.sym", "NOT_QSS", "#ifndef NOT_QSS\n#define NOT_QSS __deprecated(\"Not supported by QSS\")\n#endif\n"}, + {NQ, "dp_ss.sym", "NOT_DP", "#ifndef NOT_DP\n#define NOT_DP __deprecated(\"Not supported by Darkplaces\")\n#endif\n"}, + {CS, "qss_cs.sym", "NOT_QSS", "#ifndef NOT_QSS\n#define NOT_QSS __deprecated(\"Not supported by QSS\")\n#endif\n"}, + {CS, "dp_cs.sym", "NOT_DP", "#ifndef NOT_DP\n#define NOT_DP __deprecated(\"Not supported by Darkplaces\")\n#endif\n"}, + {MENU, "qss_menu.sym", "NOT_QSS", "#ifndef NOT_QSS\n#define NOT_QSS __deprecated(\"Not supported by QSS\")\n#endif\n"}, + {MENU, "dp_menu.sym", "NOT_DP", "#ifndef NOT_DP\n#define NOT_DP __deprecated(\"Not supported by Darkplaces\")\n#endif\n"}, + {0, NULL, NULL} + }; + #undef D #ifdef NOQCDESCRIPTIONS #define D(d) NULL @@ -11981,60 +12227,105 @@ void PR_DumpPlatform_f(void) {"other", "entity", QW|NQ|CS, D("Valid in touch functions, this is the entity that we touched.")}, {"world", "entity", QW|NQ|CS, D("The null entity. Hurrah. Readonly after map spawn time.")}, {"time", "float", QW|NQ|CS, D("The current game time. Stops when paused.")}, - {"cltime", "float", CS, D("A local timer that ticks relative to local time regardless of latency, packetloss, or pause.")}, + {"cltime", "float", FTE_CS, D("A local timer that ticks relative to local time regardless of latency, packetloss, or pause.")}, {"frametime", "float", QW|NQ|CS, D("The time since the last physics/render/input frame.")}, - {"player_localentnum", "float", CS, D("This is entity number the player is seeing from/spectating, or the player themself, can change mid-map.")}, - {"player_localnum", "float", CS, D("The 0-based player index, valid for getplayerkeyvalue calls.")}, - {"maxclients", "float", CS, D("Maximum number of player slots on the server.")}, - {"clientcommandframe", "float", CS, D("This is the input-frame sequence. frames < clientcommandframe have been sent to the server. frame==clientcommandframe is still being generated and can still change.")}, - {"servercommandframe", "float", CS, D("This is the input-frame that was last acknowledged by the server. Input frames greater than this should be applied to the player's entity.")}, + {"player_localentnum", "float", FTE_CS|DP_CS, D("This is entity number the player is seeing from/spectating, or the player themself, can change mid-map.")}, + {"player_localnum", "float", FTE_CS|DP_CS, D("The 0-based player index, valid for getplayerkeyvalue calls.")}, + {"maxclients", "float", FTE_CS|DP_CS, D("Maximum number of player slots on the server.")}, + {"clientcommandframe", "float", FTE_CS|DP_CS, D("This is the input-frame sequence. frames < clientcommandframe have been sent to the server. frame==clientcommandframe is still being generated and can still change.")}, + {"servercommandframe", "float", FTE_CS|DP_CS, D("This is the input-frame that was last acknowledged by the server. Input frames greater than this should be applied to the player's entity.")}, {"newmis", "entity", QW, D("A named entity that should be run soon, to reduce the effects of latency.")}, - {"force_retouch", "float", QW|NQ, D("If positive, causes all entities to check for triggers.")}, + {"force_retouch", "float", QW|NQ|QSS_CS, D("If positive, causes all entities to check for triggers.")}, {"mapname", "string", QW|NQ|CS, D("The short name of the map.")}, - {"deathmatch", "float", NQ}, - {"coop", "float", NQ}, - {"teamplay", "float", NQ}, - {"serverflags", "float", QW|NQ}, - {"total_secrets", "float", QW|NQ}, - {"total_monsters", "float", QW|NQ}, - {"found_secrets", "float", QW|NQ}, - {"killed_monsters", "float", QW|NQ}, - {"parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8, parm9, parm10, parm11, parm12, parm13, parm14, parm15, parm16", "float", QW|NQ, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, - {"intermission", "float", CS}, - {"v_forward, v_up, v_right", "vector", QW|NQ|CS}, - {"view_angles", "vector", CS, D("+x=DOWN")}, - {"trace_allsolid, trace_startsolid, trace_fraction", "float", QW|NQ|CS}, - {"trace_endpos, trace_plane_normal", "vector", QW|NQ|CS}, + {"deathmatch", "float", NQ|QSS_CS}, + {"coop", "float", NQ|QSS_CS}, + {"teamplay", "float", NQ|QSS_CS}, + {"serverflags", "float", QW|NQ|QSS_CS}, + {"total_secrets", "float", QW|NQ|QSS_CS}, + {"total_monsters", "float", QW|NQ|QSS_CS}, + {"found_secrets", "float", QW|NQ|QSS_CS}, + {"killed_monsters", "float", QW|NQ|QSS_CS}, + {"parm1", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm2", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm3", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm4", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm5", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm6", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm7", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm8", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm9", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm10", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm11", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm12", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm13", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm14", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm15", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"parm16", "float", QW|NQ|QSS_CS, "Player specific mod-defined values that are transferred from one map to the next. These are set by the qc inside calls to SetNewParms and SetChangeParms, and can then be read on a per-player basis after a call to the setspawnparms builtin. They are not otherwise valid."}, + {"intermission", "float", FTE_CS}, + {"v_forward", "vector", QW|NQ|CS}, + {"v_up", "vector", QW|NQ|CS}, + {"v_right", "vector", QW|NQ|CS}, + {"view_angles", "vector", FTE_CS, D("+x=DOWN")}, + {"trace_allsolid", "float", QW|NQ|CS}, + {"trace_startsolid", "float", QW|NQ|CS}, + {"trace_fraction", "float", QW|NQ|CS}, + {"trace_endpos", "vector", QW|NQ|CS}, + {"trace_plane_normal", "vector", QW|NQ|CS}, {"trace_plane_dist", "float", QW|NQ|CS}, {"trace_ent", "entity", QW|NQ|CS}, {"trace_inopen", "float", QW|NQ|CS}, {"trace_inwater", "float", QW|NQ|CS}, - {"input_timelength", "float", CS}, - {"input_angles", "vector", CS, D("+x=DOWN")}, - {"input_movevalues", "vector", CS}, - {"input_buttons", "float", CS}, - {"input_impulse", "float", CS}, - {"msg_entity", "entity", QW|NQ}, - {"main", "void()", QW|NQ, D("This function is never called, and is effectively dead code.")}, - {"StartFrame", "void()", QW|NQ, D("Called at the start of each new physics frame. Player entities may think out of sequence so try not to depend upon explicit ordering too much.")}, - {"PlayerPreThink", "void()", QW|NQ, D("With Prediction(QW compat/FTE default): Called before the player's input commands are processed.\nNo Prediction(NQ compat): Called AFTER the player's movement intents have already been processed (ie: velocity will have already changed according to input_*, but before the actual position change.")}, - {"PlayerPostThink", "void()", QW|NQ, D("Called after the player's input commands are processed.")}, - {"ClientKill", "void()", QW|NQ, D("Called in response to 'cmd kill' (or just 'kill').")}, - {"ClientConnect", "void()", QW|NQ|ID1, D("Called after the connecting client has finished loading and is ready to receive active entities. Note that this is NOT the first place that a client might be referred to. To determine if the client has csqc active (and kick anyone that doesn't), you can use if(infokeyf(self,INFOKEY_P_CSQCACTIVE)) {sprint(self, \"CSQC is required for this server\\n\");dropclient(self);}")}, - {"PutClientInServer", "void()", QW|NQ, D("Enginewise, this is only ever called immediately after ClientConnect and is thus a little redundant. Modwise, this is also called for respawning a player etc.")}, - {"ClientDisconnect", "void()", QW|NQ, D("Called once a client disconnects or times out. Not guarenteed to be called on map changes.")}, - {"SetNewParms", "void()", QW|NQ, D("Called without context when a new client initially connects (before ClientConnect is even called). This function is expected to only set the parm* globals so that they can be decoded properly later. You should not rely on 'self' being set.")}, - {"SetChangeParms", "void()", QW|NQ, D("Called for each client on map changes. Should copy various entity fields to the parm* globals.")}, + {"input_timelength", "float", FTE_CS}, + {"input_angles", "vector", FTE_CS, D("+x=DOWN")}, + {"input_movevalues", "vector", FTE_CS}, + {"input_buttons", "float", FTE_CS}, + {"input_impulse", "float", FTE_CS}, + {"msg_entity", "entity", QW|NQ|QSS_CS}, + {"main", "void()", QW|NQ|QSS_CS, D("This function is never called, and is effectively dead code.")}, + {"StartFrame", "void()", QW|NQ|QSS_CS, D("Called at the start of each new physics frame. Player entities may think out of sequence so try not to depend upon explicit ordering too much.")}, + {"PlayerPreThink", "void()", QW|NQ|QSS_CS, D("With Prediction(QW compat/FTE default): Called before the player's input commands are processed.\nNo Prediction(NQ compat): Called AFTER the player's movement intents have already been processed (ie: velocity will have already changed according to input_*, but before the actual position change.")}, + {"PlayerPostThink", "void()", QW|NQ|QSS_CS, D("Called after the player's input commands are processed.")}, + {"ClientKill", "void()", QW|NQ|QSS_CS, D("Called in response to 'cmd kill' (or just 'kill').")}, + {"ClientConnect", "void()", QW|NQ|QSS_CS|ID1, D("Called after the connecting client has finished loading and is ready to receive active entities. Note that this is NOT the first place that a client might be referred to. To determine if the client has csqc active (and kick anyone that doesn't), you can use if(infokeyf(self,INFOKEY_P_CSQCACTIVE)) {sprint(self, \"CSQC is required for this server\\n\");dropclient(self);}")}, + {"PutClientInServer", "void()", QW|NQ|QSS_CS, D("Enginewise, this is only ever called immediately after ClientConnect and is thus a little redundant. Modwise, this is also called for respawning a player etc.")}, + {"ClientDisconnect", "void()", QW|NQ|QSS_CS, D("Called once a client disconnects or times out. Not guarenteed to be called on map changes.")}, + {"SetNewParms", "void()", QW|NQ|QSS_CS, D("Called without context when a new client initially connects (before ClientConnect is even called). This function is expected to only set the parm* globals so that they can be decoded properly later. You should not rely on 'self' being set.")}, + {"SetChangeParms", "void()", QW|NQ|QSS_CS, D("Called for each client on map changes. Should copy various entity fields to the parm* globals.")}, + + {"CSQC_Init", "void(optional float apilevel, string enginename, float engineversion)", DP_CS, D("Arg list is shorter than FTE+QSS")}, + {"CSQC_Shutdown", "void()", DP_CS}, + {"CSQC_InputEvent", "float(float eventtype, float xscan, float ychar, optional float zdev)", DP_CS, D("Arg list is shorter than FTE+QSS")}, + {"CSQC_UpdateView", "void(float physicalwidth, float physicalheight, optional float notmenu)", DP_CS, D("width+height are misinterpreted as physical sizes rather than the more useful virtual sizes.")}, + {"CSQC_ConsoleCommand", "float(string cmd)", DP_CS}, + {"pmove_org", "vector", DP_CS}, + {"pmove_vel", "vector", DP_CS}, + {"pmove_mins", "vector", DP_CS}, + {"pmove_maxs", "vector", DP_CS}, + {"input_timelength", "float", DP_CS}, + {"input_angles", "vector", DP_CS}, + {"input_movevalues", "vector", DP_CS}, + {"input_buttons", "float", DP_CS}, + {"movevar_gravity", "float", DP_CS}, + {"movevar_stopspeed", "float", DP_CS}, + {"movevar_maxspeed", "float", DP_CS}, + {"movevar_spectatormaxspeed", "float", DP_CS}, + {"movevar_accelerate", "float", DP_CS}, + {"movevar_airaccelerate", "float", DP_CS}, + {"movevar_wateraccelerate", "float", DP_CS}, + {"movevar_friction", "float", DP_CS}, + {"movevar_waterfriction", "float", DP_CS}, + {"movevar_entgravity", "float", DP_CS}, + {"end_sys_globals", "void", QW|NQ|CS|MENU}, {"modelindex", ".float", QW|NQ|CS, D("This is the model precache index for the model that was set on the entity, instead of having to look up the model according to the .model field. Use setmodel to change it.")}, {"absmin", ".vector", QW|NQ|CS, D("Set by the engine when the entity is relinked (by setorigin, setsize, or setmodel). This is in world coordinates.")}, {"absmax", ".vector", QW|NQ|CS, D("Set by the engine when the entity is relinked (by setorigin, setsize, or setmodel). This is in world coordinates.")}, - {"ltime", ".float", QW|NQ, D("On MOVETYPE_PUSH entities, this is used as an alternative to the 'time' global, and .nextthink is synced to this instead of time. This allows time to effectively freeze if the entity is blocked, ensuring the think happens when the entity reaches the target point instead of randomly.")}, - {"entnum", ".float", CS, D("The entity number as its known on the server.")}, - {"drawmask", ".float", CS, D("Acts as a filter in the addentities call.")}, - {"predraw", ".float()", CS, D("Called by addentities after the filter and before the entity is actually drawn. Do your interpolation and animation in here. Should return one of the PREDRAW_* constants.")}, + {"ltime", ".float", QW|NQ|QSS_CS, D("On MOVETYPE_PUSH entities, this is used as an alternative to the 'time' global, and .nextthink is synced to this instead of time. This allows time to effectively freeze if the entity is blocked, ensuring the think happens when the entity reaches the target point instead of randomly.")}, + {"entnum", ".float", FTE_CS|DP_CS, D("The entity number as its known on the server.")}, + {"drawmask", ".float", FTE_CS|DP_CS, D("Acts as a filter in the addentities call.")}, + {"predraw", ".float()", FTE_CS|DP_CS, D("Called by addentities after the filter and before the entity is actually drawn. Do your interpolation and animation in here. Should return one of the PREDRAW_* constants.")}, {"lastruntime", ".float", QW, D("This field used to be used to avoid running an entity multiple times in a single frame due to quakeworld's out-of-order thinks. It is no longer used by FTE due to precision issues, but may still be updated for compatibility reasons.")}, {"movetype", ".float", QW|NQ|CS, D("Describes how the entity moves. One of the MOVETYPE_ constants.")}, {"solid", ".float", QW|NQ|CS, D("Describes whether the entity is solid or not, and any special properties infered by that. Must be one of the SOLID_ constants")}, @@ -12043,80 +12334,80 @@ void PR_DumpPlatform_f(void) {"velocity", ".vector", QW|NQ|CS, D("The direction and speed that the entity is moving in world space.")}, {"angles", ".vector", QW|NQ|CS, D("The eular angles the entity is facing in, in pitch, yaw, roll order. Due to a legacy bug, mdl/iqm/etc formats use +x=UP, bsp/spr/etc formats use +x=DOWN.")}, {"avelocity", ".vector", QW|NQ|CS, D("The amount the entity's angles change by per second. Note that this is direct eular angles, and thus the angular change is non-linear and often just looks buggy if you're changing more than one angle at a time.")}, - {"pmove_flags", ".float", CS}, - {"punchangle", ".vector", NQ}, + {"pmove_flags", ".float", FTE_CS}, + {"punchangle", ".vector", NQ|QSS_CS}, {"classname", ".string", QW|NQ|CS, D("Identifies the class/type of the entity. Useful for debugging, also used for loading, but its value is not otherwise significant to the engine, this leaves the mod free to set it to whatever it wants and randomly test strings for values in whatever inefficient way it chooses fit.")}, - {"renderflags", ".float", CS}, + {"renderflags", ".float", FTE_CS}, {"model", ".string", QW|NQ|CS, D("The model name that was set via setmodel, in theory. Often, this is cleared to null to prevent the engine from being seen by clients while not changing modelindex. This behaviour allows inline models to remain solid yet be invisible.")}, {"frame", ".float", QW|NQ|CS, D("The current frame the entity is meant to be displayed in. In CSQC, note the lerpfrac and frame2 fields as well. if it specifies a framegroup, the framegroup will autoanimate in ssqc, but not in csqc.")}, - {"frame1time", ".float", CS, D("The absolute time into the animation/framegroup specified by .frame.")}, - {"frame2", ".float", CS, D("The alternative frame. Visible only when lerpfrac is set to 1.")}, - {"frame2time", ".float", CS, D("The absolute time into the animation/framegroup specified by .frame2.")}, - {"lerpfrac", ".float", CS, D("If 0, use frame1 only. If 1, use frame2 only. Mix them together for values between.")}, + {"frame1time", ".float", FTE_CS, D("The absolute time into the animation/framegroup specified by .frame.")}, + {"frame2", ".float", FTE_CS, D("The alternative frame. Visible only when lerpfrac is set to 1.")}, + {"frame2time", ".float", FTE_CS, D("The absolute time into the animation/framegroup specified by .frame2.")}, + {"lerpfrac", ".float", FTE_CS, D("If 0, use frame1 only. If 1, use frame2 only. Mix them together for values between.")}, {"skin", ".float", QW|NQ|CS, D("The skin index to use. on a bsp entity, setting this to 1 will switch to the 'activated' texture instead. A negative value will be understood as a replacement contents value, so setting it to CONTENTS_WATER will make a movable pool of water.")}, {"effects", ".float", QW|NQ|CS, D("Lots of random flags that change random effects. See EF_* constants.")}, {"mins", ".vector", QW|NQ|CS, D("The minimum extent of the model (ie: the bottom-left coordinate relative to the entity's origin). Change via setsize. May also be changed by setmodel.")}, {"maxs", ".vector", QW|NQ|CS, D("like mins, but in the other direction.")}, {"size", ".vector", QW|NQ|CS, D("maxs-mins. Updated when the entity is relinked (by setorigin, setsize, setmodel)")}, {"touch", ".void()", QW|NQ|CS}, - {"use", ".void()", QW|NQ}, + {"use", ".void()", QW|NQ|QSS_CS|DP_CS}, {"think", ".void()", QW|NQ|CS}, {"blocked", ".void()", QW|NQ|CS}, {"nextthink", ".float", QW|NQ|CS, D("The time at which the entity is next scheduled to fire its think event. For MOVETYPE_PUSH entities, this is relative to that entity's ltime field, for all other entities it is relative to the time gloal.")}, - {"groundentity", ".entity", QW|NQ}, - {"health", ".float", QW|NQ}, - {"frags", ".float", QW|NQ}, - {"weapon", ".float", QW|NQ}, - {"weaponmodel", ".string", QW|NQ}, - {"weaponframe", ".float", QW|NQ}, - {"currentammo", ".float", QW|NQ}, - {"ammo_shells", ".float", QW|NQ}, - {"ammo_nails", ".float", QW|NQ}, - {"ammo_rockets", ".float", QW|NQ}, - {"ammo_cells", ".float", QW|NQ}, - {"items", ".float", QW|NQ}, - {"takedamage", ".float", QW|NQ}, + {"groundentity", ".entity", QW|NQ|QSS_CS}, + {"health", ".float", QW|NQ|QSS_CS}, + {"frags", ".float", QW|NQ|QSS_CS}, + {"weapon", ".float", QW|NQ|QSS_CS}, + {"weaponmodel", ".string", QW|NQ|QSS_CS}, + {"weaponframe", ".float", QW|NQ|QSS_CS}, + {"currentammo", ".float", QW|NQ|QSS_CS}, + {"ammo_shells", ".float", QW|NQ|QSS_CS}, + {"ammo_nails", ".float", QW|NQ|QSS_CS}, + {"ammo_rockets", ".float", QW|NQ|QSS_CS}, + {"ammo_cells", ".float", QW|NQ|QSS_CS}, + {"items", ".float", QW|NQ|QSS_CS}, + {"takedamage", ".float", QW|NQ|QSS_CS}, {"chain", ".entity", QW|NQ|CS}, - {"deadflag", ".float", QW|NQ}, - {"view_ofs", ".vector", QW|NQ}, - {"button0", ".float", QW|NQ}, - {"button1", ".float", QW|NQ}, - {"button2", ".float", QW|NQ}, - {"impulse", ".float", QW|NQ}, - {"fixangle", ".float", QW|NQ, "Forces the clientside view angles to change to the value of .angles (has some lag). If set to 1/TRUE, the server will guess whether to send a delta or an explicit angle. If 2, will always send a delta (due to lag between transmission and acknowledgement, this cannot be spammed reliably). If 3, will always send an explicit angle."}, - {"v_angle", ".vector", QW|NQ, "The angles a player is viewing. +x is DOWN (pitch, yaw, roll)"}, - {"idealpitch", ".float", NQ}, - {"netname", ".string", QW|NQ}, + {"deadflag", ".float", QW|NQ|QSS_CS}, + {"view_ofs", ".vector", QW|NQ|QSS_CS}, + {"button0", ".float", QW|NQ|QSS_CS}, + {"button1", ".float", QW|NQ|QSS_CS}, + {"button2", ".float", QW|NQ|QSS_CS}, + {"impulse", ".float", QW|NQ|QSS_CS}, + {"fixangle", ".float", QW|NQ|QSS_CS, "Forces the clientside view angles to change to the value of .angles (has some lag). If set to 1/TRUE, the server will guess whether to send a delta or an explicit angle. If 2, will always send a delta (due to lag between transmission and acknowledgement, this cannot be spammed reliably). If 3, will always send an explicit angle."}, + {"v_angle", ".vector", QW|NQ|QSS_CS, "The angles a player is viewing. +x is DOWN (pitch, yaw, roll)"}, + {"idealpitch", ".float", NQ|QSS_CS}, + {"netname", ".string", QW|NQ|QSS_CS|DP_CS}, {"enemy", ".entity", QW|NQ|CS}, {"flags", ".float", QW|NQ|CS}, {"colormap", ".float", QW|NQ|CS}, - {"team", ".float", QW|NQ}, - {"max_health", ".float", QW|NQ}, - {"teleport_time", ".float", QW|NQ, D("While active, prevents the player from using the +back command, also blocks waterjumping.")}, - {"armortype", ".float", QW|NQ}, - {"armorvalue", ".float", QW|NQ}, - {"waterlevel", ".float", QW|NQ}, - {"watertype", ".float", QW|NQ}, - {"ideal_yaw", ".float", QW|NQ}, - {"yaw_speed", ".float", QW|NQ}, - {"aiment", ".entity", QW|NQ}, - {"goalentity", ".entity", QW|NQ}, - {"spawnflags", ".float", QW|NQ}, - {"target", ".string", QW|NQ}, - {"targetname", ".string", QW|NQ}, - {"dmg_take", ".float", QW|NQ}, - {"dmg_save", ".float", QW|NQ}, - {"dmg_inflictor", ".entity", QW|NQ}, + {"team", ".float", QW|NQ|QSS_CS}, + {"max_health", ".float", QW|NQ|QSS_CS}, + {"teleport_time", ".float", QW|NQ|QSS_CS, D("While active, prevents the player from using the +back command, also blocks waterjumping.")}, + {"armortype", ".float", QW|NQ|QSS_CS}, + {"armorvalue", ".float", QW|NQ|QSS_CS}, + {"waterlevel", ".float", QW|NQ|QSS_CS}, + {"watertype", ".float", QW|NQ|QSS_CS}, + {"ideal_yaw", ".float", QW|NQ|QSS_CS}, + {"yaw_speed", ".float", QW|NQ|QSS_CS}, + {"aiment", ".entity", QW|NQ|QSS_CS}, + {"goalentity", ".entity", QW|NQ|QSS_CS}, + {"spawnflags", ".float", QW|NQ|QSS_CS}, + {"target", ".string", QW|NQ|QSS_CS}, + {"targetname", ".string", QW|NQ|QSS_CS}, + {"dmg_take", ".float", QW|NQ|QSS_CS}, + {"dmg_save", ".float", QW|NQ|QSS_CS}, + {"dmg_inflictor", ".entity", QW|NQ|QSS_CS}, {"owner", ".entity", QW|NQ|CS}, - {"movedir", ".vector", QW|NQ}, - {"message", ".string", QW|NQ}, - {"sounds", ".float", QW|NQ}, - {"noise", ".string", QW|NQ}, - {"noise1", ".string", QW|NQ}, - {"noise2", ".string", QW|NQ}, - {"noise3", ".string", QW|NQ}, + {"movedir", ".vector", QW|NQ|QSS_CS}, + {"message", ".string", QW|NQ|QSS_CS}, + {"sounds", ".float", QW|NQ|QSS_CS}, + {"noise", ".string", QW|NQ|QSS_CS}, + {"noise1", ".string", QW|NQ|QSS_CS}, + {"noise2", ".string", QW|NQ|QSS_CS}, + {"noise3", ".string", QW|NQ|QSS_CS}, {"end_sys_fields", "void", QW|NQ|CS|MENU}, {"time", "float", MENU, D("The current local time. Increases while paused.")}, @@ -12139,7 +12430,7 @@ void PR_DumpPlatform_f(void) {"trace_surface_id", "int", QW|NQ|CS, D("1-based. 0 if not known.")}, {"trace_bone_id", "int", QW|NQ|CS, D("1-based. 0 if not known. typically needs MOVE_HITMODEL.")}, {"trace_triangle_id", "int", QW|NQ|CS, D("1-based. 0 if not known.")}, - {"trace_networkentity", "int", CS, D("Repots which ssqc entnum was hit when a csqc traceline impacts an ssqc-based brush entity.")}, + {"trace_networkentity", "float", CS, D("Repots which ssqc entnum was hit when a csqc traceline impacts an ssqc-based brush entity.")}, {"pmove_org", "vector", CS, D("Reports the origin of the engineside player (after prediction). Does not work when the player is a csqc-owned entity.")}, {"pmove_vel", "vector", CS, D("Reports the velocity of the engineside player (after prediction). Does not work when the player is a csqc-owned entity.")}, @@ -12147,27 +12438,33 @@ void PR_DumpPlatform_f(void) {"global_gravitydir", "vector", QW|NQ|CS, D("The direction gravity should act in if not otherwise specified per entity."), 0,"'0 0 -1'"}, {"serverid", "int", QW|NQ|CS, D("The unique id of this server within the server cluster.")}, + {"message", ".string", CS, D("Allows the csqc to read the map description from the server.")}, - {"button3", ".float", QW|NQ}, - {"button4", ".float", QW|NQ}, - {"button5", ".float", QW|NQ}, - {"button6", ".float", QW|NQ}, - {"button7", ".float", QW|NQ}, - {"button8", ".float", QW|NQ}, + {"button3", ".float", QW|NQ}, + {"button4", ".float", QW|NQ}, + {"button5", ".float", QW|NQ}, + {"button6", ".float", QW|NQ}, + {"button7", ".float", QW|NQ}, + {"button8", ".float", QW|NQ}, //and for dp compat (these names are fucked, yes) -// {"buttonuse", ".float", QW|NQ}, -// {"buttonchat", ".float", QW|NQ}, -// {"cursor_active", ".float", QW|NQ}, -// {"button9", ".float", QW|NQ}, -// {"button10", ".float", QW|NQ}, -// {"button11", ".float", QW|NQ}, -// {"button12", ".float", QW|NQ}, -// {"button13", ".float", QW|NQ}, + {"buttonuse", ".float", NQ, D("For DP compat only.")}, + {"buttonchat", ".float", NQ, D("For DP compat only.")}, + {"cursor_active", ".float", NQ, D("For DP compat only.")}, + {"button9", ".float", NQ, D("For DP compat only.")}, + {"button10", ".float", NQ, D("For DP compat only.")}, + {"button11", ".float", NQ, D("For DP compat only.")}, + {"button12", ".float", NQ, D("For DP compat only.")}, + {"button13", ".float", NQ, D("For DP compat only.")}, -// {"button14", ".float", QW|NQ}, -// {"button15", ".float", QW|NQ}, -// {"button16", ".float", QW|NQ}, + {"button14", ".float", NQ, D("For DP compat only.")}, + {"button15", ".float", NQ, D("For DP compat only.")}, + {"button16", ".float", NQ, D("For DP compat only.")}, + + {"cursor_screen", ".vector", NQ, D("For DP compat only.")}, + {"cursor_start", ".vector", NQ, D("For DP compat only.")}, + {"cursor_impact", ".vector", NQ, D("For DP compat only.")}, + {"cursor_entitynumber", ".entity", NQ, D("For DP compat only.")}, #undef comfieldfloatdep #undef comfieldintdep @@ -12289,6 +12586,23 @@ void PR_DumpPlatform_f(void) {"drawfont", "float", CS|MENU, "Allows you to choose exactly which font is to be used to draw text. Fonts can be registered/allocated with the loadfont builtin."}, {"FONT_DEFAULT", "const float", CS|MENU, NULL, 0}, + +#define globalfloatdep(name,depreason) {#name, "DEP(\""depreason"\") float", CS}, +#define globalfunction(name,typestr) {#name, typestr, CS}, +#define globalfloat(name) {#name, "float", CS}, +#define globalentity(name) {#name, "entity", CS}, +#define globalvector(name) {#name, "vector", CS}, +#define globalstring(name) {#name, "string", CS}, +#define globalint(name) {#name, "int", CS}, + csqcglobals +#undef globalfunction +#undef globalfloat +#undef globalentity +#undef globalvector +#undef globalstring +#undef globalint +#undef globalfloatdep + {"TRUE", "const float", ALL, NULL, 1}, {"FALSE", "const float", ALL, "File not found...", 0}, {"M_PI", "const float", ALL, "Mathematica Pi constant.", M_PI}, @@ -12446,6 +12760,25 @@ 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, D("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}, + {"TE_SPIKE", "const float", QW|NQ|CS, NULL, TE_SPIKE}, + {"TE_SUPERSPIKE", "const float", QW|NQ|CS, NULL, TE_SUPERSPIKE}, + {"TE_GUNSHOT", "const float", QW|FTE_CS, NULL, TEQW_QWGUNSHOT}, + {"TE_EXPLOSION", "const float", QW|FTE_CS, NULL, TEQW_QWEXPLOSION}, + {"TE_GUNSHOT", "const float", NQ|QSS_CS|DP_CS, NULL, TENQ_NQGUNSHOT}, + {"TE_EXPLOSION", "const float", NQ|QSS_CS|DP_CS, NULL, TENQ_NQEXPLOSION}, + {"TE_TAREXPLOSION", "const float", QW|NQ|CS, NULL, TE_TAREXPLOSION}, + {"TE_LIGHTNING1", "const float", QW|NQ|CS, NULL, TE_LIGHTNING1}, + {"TE_LIGHTNING2", "const float", QW|NQ|CS, NULL, TE_LIGHTNING2}, + {"TE_WIZSPIKE", "const float", QW|NQ|CS, NULL, TE_WIZSPIKE}, + {"TE_KNIGHTSPIKE", "const float", QW|NQ|CS, NULL, TE_KNIGHTSPIKE}, + {"TE_LIGHTNING3", "const float", QW|NQ|CS, NULL, TE_LIGHTNING3}, + {"TE_LAVASPLASH", "const float", QW|NQ|CS, NULL, TE_LAVASPLASH}, + {"TE_TELEPORT", "const float", QW|NQ|CS, NULL, TE_TELEPORT}, + {"TE_BLOOD", "const float", QW|FTE_CS, NULL, TEQW_QWBLOOD}, + {"TE_EXPLOSION2", "const float", NQ|QSS_CS|DP_CS, NULL, TENQ_EXPLOSION2}, + {"TE_LIGHTNINGBLOOD", "const float", QW|FTE_CS, NULL, TEQW_LIGHTNINGBLOOD}, + {"TE_BEAM", "const float", NQ|QSS_CS|DP_CS, NULL, TENQ_BEAM}, + #ifdef HAVE_LEGACY {"MSG_BROADCAST", "const float", NQ, D("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", NQ, D("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}, @@ -12553,6 +12886,7 @@ void PR_DumpPlatform_f(void) {"MOVE_NORMAL", "const float", QW|NQ|CS, NULL, MOVE_NORMAL}, {"MOVE_NOMONSTERS", "const float", QW|NQ|CS, D("The trace will ignore all non-solid_bsp entities."), MOVE_NOMONSTERS}, {"MOVE_MISSILE", "const float", QW|NQ|CS, D("The trace will use a bbox size of +/- 15 against entities with FL_MONSTER set."), MOVE_MISSILE}, + {"MOVE_WORLDONLY", "const float", QW|NQ|CS, D("The trace will ignore everything but the worldmodel. This is useful for to prevent the q3bsp pvs+culling issues that come with spectator modes leaving the world ."), MOVE_WORLDONLY}, {"MOVE_HITMODEL", "const float", QW|NQ|CS, D("Traces will impact the actual mesh of the model instead of merely their bounding box. Should generally only be used for tracelines. Note that this flag is unreliable as an object can animate through projectiles. The bounding box MUST be set to completely encompass the entity or those extra areas will be non-solid (leaving a hole for things to go through)."), MOVE_HITMODEL}, {"MOVE_TRIGGERS", "const float", QW|NQ|CS, D("This trace type will impact only triggers. It will ignore non-solid entities."), MOVE_TRIGGERS}, {"MOVE_EVERYTHING", "const float", QW|NQ|CS, D("This type of trace will hit solids and triggers alike. Even non-solid entities."), MOVE_EVERYTHING}, @@ -12560,6 +12894,13 @@ void PR_DumpPlatform_f(void) {"MOVE_ENTCHAIN", "const float", QW|NQ|CS, D("Returns a list of entities impacted via the trace_ent.chain field"), MOVE_ENTCHAIN}, {"MOVE_OTHERONLY", "const float", QW|NQ|CS, D("Traces that use this trace type will collide against *only* the entity specified via the 'other' global, and will ignore all owner/solid_not/dimension etc rules, they will still adhere to contents and bsp/bbox rules though."), MOVE_OTHERONLY}, + {"CVAR_TYPEFLAG_EXISTS", "const float", ALL, D("Cvar name actually exists."), CVAR_TYPEFLAG_EXISTS}, + {"CVAR_TYPEFLAG_SAVED", "const float", ALL, D("Cvar is flaged for archival (might need cfg_save to actually save)."), CVAR_TYPEFLAG_SAVED}, + {"CVAR_TYPEFLAG_PRIVATE", "const float", ALL, D("QC is not allowed to read."), CVAR_TYPEFLAG_PRIVATE}, + {"CVAR_TYPEFLAG_ENGINE", "const float", ALL, D("Cvar was created by the engine itself (not user/mod created)."), CVAR_TYPEFLAG_ENGINE}, + {"CVAR_TYPEFLAG_HASDESCRIPTION","const float", ALL, D("cvar_description will return something (hopefully) useful."), CVAR_TYPEFLAG_HASDESCRIPTION}, + {"CVAR_TYPEFLAG_READONLY", "const float", ALL, D("cvar may not be changed by qc."), CVAR_TYPEFLAG_READONLY}, + {"RESTYPE_MODEL", "const float", ALL, D("RESTYPE_* constants are used as arguments with the resourcestatus builtin."), RESTYPE_MODEL}, {"RESTYPE_SOUND", "const float", ALL, D("precache_sound"), RESTYPE_SOUND}, {"RESTYPE_PARTICLE", "const float", ALL, D("particleeffectnum"), RESTYPE_PARTICLE}, @@ -12712,6 +13053,14 @@ void PR_DumpPlatform_f(void) {"VF_SKYROOM_CAMERA", "const float", CS, D("Controls the camera position of the skyroom (which will be drawn underneath transparent sky surfaces). This should move slightly with the real camera, but not so much that the skycamera enters walls. Requires a skyshader with a blend mode on the first pass (or no passes)."), VF_SKYROOM_CAMERA}, {"VF_PROJECTIONOFFSET", "const float", CS|MENU, D("vec2 horizontal+vertical offset for the projection matrix, for weird off-centre rendering."), VF_PROJECTIONOFFSET}, + {"DRAWFLAG_NORMAL", "const float", CS|MENU, D("Args for drawpic/drawfill/beginpolygon. Not to be confused with the hexen2-compatibility feature."), DRAWFLAG_NORMAL}, + {"DRAWFLAG_ADD", "const float", CS|MENU, D("Forces additive blending, overriding any shader settings."), DRAWFLAG_ADD}, + {"DRAWFLAG_MODULATE", "const float", CS|MENU, D("Forces alpha blending, overriding any shader settings."), DRAWFLAG_MODULATE}, +// {"DRAWFLAG_MODULATE2", "const float", CS|MENU, D("."), DRAWFLAG_MODULATE2}, + {"DRAWFLAG_2D", "const float", CS|MENU, D("For use with beginpolygon. The polygon will be drawn to the 2d screen, instead of being added to the 3d scene."), DRAWFLAG_2D}, + {"DRAWFLAG_TWOSIDED", "const float", CS|MENU, D("For use with beginpolygon. The polygon will be two-sided without any backface culling."), DRAWFLAG_TWOSIDED}, + {"DRAWFLAG_LINES", "const float", CS|MENU, D("For use with beginpolygon. The surface verticies should be interpreted as a line loop, instead of a triangle fan."), DRAWFLAG_LINES}, + {"IMGFMT_R8G8B8A8", "const float", CS|MENU, D("Typical 32bit rgba pixel format."), 1}, {"IMGFMT_R16G16B16A16F","const float", CS|MENU, D("Half-Float pixel format. Requires gl3 support."), 2}, {"IMGFMT_R32G32B32A32F","const float", CS|MENU, D("Regular Float pixel format. Requires gl3 support."), 3}, @@ -12749,7 +13098,7 @@ void PR_DumpPlatform_f(void) {"GGDI_OVERRIDES", "const float", CS|MENU, D("A list of settings overrides."), GGDI_OVERRIDES}, {"GGDI_LOADCOMMAND", "const float", CS|MENU, D("The console command needed to actually load the mod."), GGDI_LOADCOMMAND}, {"GGDI_ICON", "const float", CS|MENU, D("The mod's Icon path, ready for drawpic."), GGDI_ICON}, - {"GGDI_GAMEDIRLIST", "const float", CS|MENU, D("A semi-colon delimited list of gamedirs that the mod's content can be loaded through."), GGDI_ICON}, + {"GGDI_GAMEDIRLIST", "const float", CS|MENU, D("A semi-colon delimited list of gamedirs that the mod's content can be loaded through."), GGDI_ALLGAMEDIRS}, {"CLIENTTYPE_DISCONNECTED","const float", QW|NQ, D("Return value from clienttype() builtin. This entity is a player slot that is currently empty."), CLIENTTYPE_DISCONNECTED}, {"CLIENTTYPE_REAL", "const float", QW|NQ, D("This is a real player, and not a bot."), CLIENTTYPE_REAL}, @@ -12860,14 +13209,17 @@ void PR_DumpPlatform_f(void) #define DUMPHELP \ "Available options:\n" \ "-Ffte - target only FTE (optimations and additional extensions)\n" \ - "-Tnq - dump specifically NQ fields\n" \ - "-Tqw - dump specifically QW fields\n" \ - "-Tcs - dump specifically CSQC fields\n" \ - "-Tmenu - dump specifically menuqc fields\n" \ + "-Tnq - dump only NQ fields\n" \ + "-Tqw - dump only QW fields\n" \ + "-Tcs - dump only CSQC fields\n" \ + "-Tsimplecs - dump only Simple-CSQC fields\n" \ + "-Tdpcs - dump only DP-CSQC fields\n" \ + "-Tmenu - dump only menuqc fields\n" \ "-Tid1 - omits any symbols that conflict with vanilla defs.qc\n" \ "-Tdp - omits any symbols that conflict with dpextensions.qc\n" \ "-Fdefines - generate #defines instead of constants\n" \ "-Faccessors - use accessors instead of basic types via defines\n" \ + "-Fdepfilter - use symbol tables to include deprecation warnings for symbols not supported by other engines\n" \ "-O - write to a different qc file\n" targ = 0; for (i = 1; i < Cmd_Argc(); i++) @@ -12877,14 +13229,18 @@ void PR_DumpPlatform_f(void) targ |= FTE; else if (!stricmp(arg, "-Tnq")) targ |= NQ; - else if (!stricmp(arg, "-Tcs")) - targ |= CS; else if (!stricmp(arg, "-Tqw")) targ |= QW; + else if (!stricmp(arg, "-Tcs")) + targ |= FTE_CS; + else if (!stricmp(arg, "-Tsimplecs")) + targ |= QSS_CS; + else if (!stricmp(arg, "-Tdpcs")) + targ |= DP_CS; else if (!stricmp(arg, "-Tmenu")) targ |= MENU; else if (!stricmp(arg, "-Th2")) - targ |= H2; + targ |= H2; //TESTME else if (!stricmp(arg, "-Tid1")) targ |= ID1; else if (!stricmp(arg, "-Tdp")) @@ -12897,6 +13253,8 @@ void PR_DumpPlatform_f(void) accessors = true; else if (!stricmp(arg, "-Fnoaccessors")) accessors = false; + else if (!stricmp(arg, "-Fdepfilter")) + depfilter = true; else if (!Q_strncasecmp(arg, "-O", 2)) { if (arg[2]) @@ -12911,7 +13269,13 @@ void PR_DumpPlatform_f(void) } } if (!(targ & ALL)) - targ |= (QW|NQ|CS|MENU); + targ |= (QW|NQ|FTE_CS|MENU); + + //our #ifdefs can't cope with targetting more than one csqc type at a time. + if ((targ & QSS_CS) && (targ & (FTE_CS|DP_CS))) + targ &= ~(FTE_CS|DP_CS); //QSS doesn't support any other layours. + if ((targ & DP_CS) && (targ & FTE_CS)) + targ &= ~(FTE_CS); //if you're trying to target both, then you generally want to favour the lowest common denominator. FTE has workarounds in place so this is the most compatible option (which sucks). if (!*fname) fname = "fteextensions"; @@ -12929,15 +13293,7 @@ void PR_DumpPlatform_f(void) "This file was generated by %s %s, dated %s.\n" "This file can be regenerated by issuing the following command:\n" "%s %s\n" - "Available options:\n" - "-Ffte - target only FTE (optimations and additional extensions)\n" - "-Tnq - dump specifically NQ fields\n" - "-Tqw - dump specifically QW fields\n" - "-Tcs - dump specifically CSQC fields\n" - "-Tmenu - dump specifically menuqc fields\n" - "-Fdefines - generate #defines instead of constants\n" - "-Faccessors - use accessors instead of basic types via defines\n" - "-O - write to a different qc file\n" + "(Use the -help arg for a list of available args)\n" "*/\n" , FULLENGINENAME, STRINGIFY(SVNREVISION), #ifdef SVNDATE @@ -12957,7 +13313,7 @@ void PR_DumpPlatform_f(void) #ifndef HAVE_LEGACY VFS_PRINTF(f, "#pragma warning error F211 /*system crc outdated (eg: dp's csqc). Such mods will not run properly in FTE.*/\n"); #else - VFS_PRINTF(f, "#pragma warning disable F211 /*system crc outdated (eg: dp's csqc). Note that this may trigger emulation.*/\n"); +// VFS_PRINTF(f, "#pragma warning disable F211 /*system crc outdated (eg: dp's csqc). Note that this may trigger emulation.*/\n"); #endif VFS_PRINTF(f, "#pragma warning enable F301 /*non-utf-8 strings. Think of the foreigners! Also think of text editors that insist on screwing up your char encodings.*/\n"); VFS_PRINTF(f, "#pragma warning enable F302 /*uninitialised locals. They usually default to 0 in qc (except in recursive functions), but its still probably a bug*/\n"); @@ -12977,48 +13333,60 @@ void PR_DumpPlatform_f(void) if (targ&FTE) VFS_PRINTF(f, "#pragma target FTE\n#define FTEDEP DEP\n"); } - if ((targ&ALL) == CS) + if ((targ&ALL) == FTE_CS) VFS_PRINTF(f, "#ifndef CSQC\n" - "#define CSQC\n" + "\t#define CSQC\n" + "#endif\n" + ); + else if ((targ&ALL) == QSS_CS) + VFS_PRINTF(f, "#ifndef CSQC\n" + "\t#define CSQC\n" + "\t#define SIMPLE_CSQC\n" + "#endif\n" + ); + else if ((targ&ALL) == DP_CS) + VFS_PRINTF(f, "#ifndef CSQC\n" + "\t#define CSQC\n" + "\t#define DP_CSQC\n" "#endif\n" ); else if ((targ&ALL) == NQ) VFS_PRINTF(f, "#ifndef NETQUAKE\n" - "#define NETQUAKE\n" + "\t#define NETQUAKE\n" "#endif\n" "#ifndef NQSSQC\n" - "#define NQSSQC\n" + "\t#define NQSSQC\n" "#endif\n" "#ifndef SSQC\n" - "#define SSQC\n" + "\t#define SSQC\n" "#endif\n" ); else if ((targ&ALL) == QW) VFS_PRINTF(f, "#ifndef QUAKEWORLD\n" - "#define QUAKEWORLD\n" + "\t#define QUAKEWORLD\n" "#endif\n" "#ifndef QWSSQC\n" - "#define QWSSQC\n" + "\t#define QWSSQC\n" "#endif\n" "#ifndef SSQC\n" - "#define SSQC\n" + "\t#define SSQC\n" "#endif\n" ); else if ((targ&ALL) == MENU) VFS_PRINTF(f, "#ifndef MENU\n" - "#define MENU\n" + "\t#define MENU\n" "#endif\n" ); else VFS_PRINTF(f, "#if !defined(CSQC) && !defined(NQSSQC) && !defined(QWSSQC)&& !defined(MENU)\n" - "#ifdef QUAKEWORLD\n" - "#define QWSSQC\n" - "#else\n" - "#define NQSSQC\n" - "#endif\n" + "\t#ifdef QUAKEWORLD\n" + "\t\t#define QWSSQC\n" + "\t#else\n" + "\t\t#define NQSSQC\n" + "\t#endif\n" "#endif\n" "#if !defined(SSQC) && (defined(QWSSQC) || defined(NQSSQC))\n" - "#define SSQC\n" + "\t#define SSQC\n" "#endif\n" ); @@ -13026,21 +13394,23 @@ void PR_DumpPlatform_f(void) if (targ&(NQ|QW|H2)) { VFS_PRINTF(f, "#if defined(CSQC) || defined(MENU)\n" - "#define DEP_CSQC DEP\n" + "\t#define DEP_CSQC DEP\n" "#else\n" - "#define DEP_CSQC __deprecated(\"Use CSQC for this\")\n" + "\t#define DEP_CSQC __deprecated(\"Use CSQC for this\")\n" "#endif\n" ); } else VFS_PRINTF(f, "#define DEP_CSQC DEP\n"); VFS_PRINTF(f, "#ifndef DEP\n" - " #define DEP __deprecated //predefine this if you want to avoid our deprecation warnings.\n" + "\t#define DEP __deprecated //predefine this if you want to avoid our deprecation warnings.\n" "#endif\n" "#ifndef FTEDEP\n" - " #define FTEDEP(reason) //for symbols deprecated in FTE that may still be useful/required for other engines\n" + "\t#define FTEDEP(reason) //for symbols deprecated in FTE that may still be useful/required for other engines\n" "#endif\n"); + if (depfilter) + PR_DumpPlatform_LoadSymbolTables(f, symtab, targ); for (i = 0; i < QSG_Extensions_count; i++) { @@ -13100,68 +13470,12 @@ void PR_DumpPlatform_f(void) else continue; } - if ((nd&targ) != (d&targ)) - { - if (d != (ALL & ~targ)) - VFS_PRINTF(f, "#endif\n"); - if (((nd | (~targ)) & ALL) == ALL) - d = ALL & ~targ; //every part of the target is specified, so don't do the ifdef thing. - else - { - d = nd; - switch(d & (ALL & targ)) - { - case 0: - continue; - case QW: - VFS_PRINTF(f, "#if defined(QWSSQC)\n"); - break; - case NQ: - VFS_PRINTF(f, "#if defined(NQSSQC)\n"); - break; - case QW|NQ: - VFS_PRINTF(f, "#ifdef SSQC\n"); - break; - case CS: - VFS_PRINTF(f, "#ifdef CSQC\n"); - break; - case QW|CS: - VFS_PRINTF(f, "#if defined(CSQC) || defined(QWSSQC)\n"); - break; - case NQ|CS: - VFS_PRINTF(f, "#if defined(CSQC) || defined(NQSSQC)\n"); - break; - case NQ|CS|QW: - VFS_PRINTF(f, "#if defined(CSQC) || defined(SSQC)\n"); - break; - case MENU: - VFS_PRINTF(f, "#ifdef MENU\n"); - break; - case QW|MENU: - VFS_PRINTF(f, "#if defined(QWSSQC) || defined(MENU)\n"); - break; - case NQ|MENU: - VFS_PRINTF(f, "#if defined(NQSSQC) || defined(MENU)\n"); - break; - case QW|NQ|MENU: - VFS_PRINTF(f, "#if defined(SSQC) || defined(MENU)\n"); - break; - case CS|MENU: - VFS_PRINTF(f, "#if defined(CSQC) || defined(MENU)\n"); - break; - case QW|CS|MENU: - VFS_PRINTF(f, "#if defined(CSQC) || defined(QWSSQC) || defined(MENU)\n"); - break; - case NQ|CS|MENU: - VFS_PRINTF(f, "#if defined(CSQC) || defined(NQSSQC) || defined(MENU)\n"); - break; - case ALL: - break; - } - } - } + if (!PR_DumpPlatform_GenIfdef(f, targ, nd, &d)) + continue; if (knowndefs[i].desc) { + if (!strncmp(knowndefs[i].desc, "stub. ", 6)) + continue; //mostly for items2. :( if (!strncmp(type, "//", 2)) comment = va("\n/* %s */", knowndefs[i].desc); else @@ -13176,14 +13490,20 @@ void PR_DumpPlatform_f(void) if (defines) VFS_PRINTF(f, "#define %s %i%s\n", knowndefs[i].name, (int)knowndefs[i].value, comment); else - VFS_PRINTF(f, "%s %s = %i;%s\n", type, knowndefs[i].name, (int)knowndefs[i].value, comment); + { + PR_DumpPlatform_SymbolType(f, symtab, type, knowndefs[i].name); + VFS_PRINTF(f, "%s = %i;%s\n", knowndefs[i].name, (int)knowndefs[i].value, comment); + } } else { if (defines) VFS_PRINTF(f, "#define %s %g%s\n", knowndefs[i].name, knowndefs[i].value, comment); else - VFS_PRINTF(f, "%s %s = %g;%s\n", type, knowndefs[i].name, knowndefs[i].value, comment); + { + PR_DumpPlatform_SymbolType(f, symtab, type, knowndefs[i].name); + VFS_PRINTF(f, "%s = %g;%s\n", knowndefs[i].name, knowndefs[i].value, comment); + } } } else if (!strcmp(type, "const string")) @@ -13191,18 +13511,26 @@ void PR_DumpPlatform_f(void) if (defines) VFS_PRINTF(f, "#define %s %s%s\n", knowndefs[i].name, knowndefs[i].valuestr, comment); else - VFS_PRINTF(f, "%s %s = %s;%s\n", type, knowndefs[i].name, knowndefs[i].valuestr, comment); + { + PR_DumpPlatform_SymbolType(f, symtab, type, knowndefs[i].name); + VFS_PRINTF(f, "%s = %s;%s\n", knowndefs[i].name, knowndefs[i].valuestr, comment); + } } else if (knowndefs[i].valuestr) { - VFS_PRINTF(f, "%s %s = %s;%s\n", type, knowndefs[i].name, knowndefs[i].valuestr, comment); + PR_DumpPlatform_SymbolType(f, symtab, type, knowndefs[i].name); + VFS_PRINTF(f, "%s = %s;%s\n", knowndefs[i].name, knowndefs[i].valuestr, comment); } else if (knowndefs[i].value) { - VFS_PRINTF(f, "%s %s = %g;%s\n", type, knowndefs[i].name, knowndefs[i].value, comment); + PR_DumpPlatform_SymbolType(f, symtab, type, knowndefs[i].name); + VFS_PRINTF(f, "%s = %g;%s\n", knowndefs[i].name, knowndefs[i].value, comment); } else - VFS_PRINTF(f, "%s %s;%s\n", type, knowndefs[i].name, comment); + { + PR_DumpPlatform_SymbolType(f, symtab, type, knowndefs[i].name); + VFS_PRINTF(f, "%s;%s\n", knowndefs[i].name, comment); + } } for (i = 0; BuiltinList[i].name; i++) { @@ -13278,122 +13606,16 @@ void PR_DumpPlatform_f(void) if (!nd) /*no idea what its for*/ continue; nd |= (~targ & ALL); - if (!(nd & targ)) + if (!PR_DumpPlatform_GenIfdef(f, targ, nd, &d)) continue; - if ((nd&targ) != (d&targ)) - { - if (d != (ALL & ~targ)) - VFS_PRINTF(f, "#endif\n"); - if (((nd | (~targ)) & ALL) == ALL) - d = ALL & ~targ; - else - { - d = nd; - switch(d & (ALL & targ)) - { - case 0: - continue; - case QW: - VFS_PRINTF(f, "#if defined(QWSSQC)\n"); - break; - case NQ: - VFS_PRINTF(f, "#if defined(NQSSQC)\n"); - break; - case QW|NQ: - VFS_PRINTF(f, "#ifdef SSQC\n"); - break; - case CS: - VFS_PRINTF(f, "#ifdef CSQC\n"); - break; - case QW|CS: - VFS_PRINTF(f, "#if defined(CSQC) || defined(QWSSQC)\n"); - break; - case NQ|CS: - VFS_PRINTF(f, "#if defined(CSQC) || defined(NQSSQC)\n"); - break; - case NQ|CS|QW: - VFS_PRINTF(f, "#if defined(CSQC) || defined(SSQC)\n"); - break; - case MENU: - VFS_PRINTF(f, "#ifdef MENU\n"); - break; - case QW|MENU: - VFS_PRINTF(f, "#if defined(QWSSQC) || defined(MENU)\n"); - break; - case NQ|MENU: - VFS_PRINTF(f, "#if defined(NQSSQC) || defined(MENU)\n"); - break; - case QW|NQ|MENU: - VFS_PRINTF(f, "#if defined(SSQC) || defined(MENU)\n"); - break; - case CS|MENU: - VFS_PRINTF(f, "#if defined(CSQC) || defined(MENU)\n"); - break; - case QW|CS|MENU: - VFS_PRINTF(f, "#if defined(CSQC) || defined(QWSSQC) || defined(MENU)\n"); - break; - case NQ|CS|MENU: - VFS_PRINTF(f, "#if defined(CSQC) || defined(NQSSQC) || defined(MENU)\n"); - break; - case H2: - VFS_PRINTF(f, "#ifdef H2\n"); - break; - case H2|QW: - VFS_PRINTF(f, "#if defined(H2) || defined(QWSSQC)\n"); - break; - case H2|NQ: - VFS_PRINTF(f, "#if defined(H2) || defined(NQSSQC)\n"); - break; - case H2|QW|NQ: - VFS_PRINTF(f, "#if defined(H2) || defined(SSQC)\n"); - break; - case H2|CS: - VFS_PRINTF(f, "#if defined(H2) || defined(CSQC)\n"); - break; - case H2|QW|CS: - VFS_PRINTF(f, "#if defined(H2) || defined(CSQC) || defined(QWSSQC)\n"); - break; - case H2|NQ|CS: - VFS_PRINTF(f, "#if defined(H2) || defined(CSQC) || defined(NQSSQC)\n"); - break; - case H2|NQ|CS|QW: - VFS_PRINTF(f, "#if defined(H2) || defined(CSQC) || defined(SSQC)\n"); - break; - case H2|MENU: - VFS_PRINTF(f, "#if defined(H2) || defined(MENU)\n"); - break; - case H2|QW|MENU: - VFS_PRINTF(f, "#if defined(H2) || defined(QWSSQC) || defined(MENU)\n"); - break; - case H2|NQ|MENU: - VFS_PRINTF(f, "#if defined(H2) || defined(NQSSQC) || defined(MENU)\n"); - break; - case H2|QW|NQ|MENU: - VFS_PRINTF(f, "#if defined(H2) || defined(SSQC) || defined(MENU)\n"); - break; - case H2|CS|MENU: - VFS_PRINTF(f, "#if defined(H2) || defined(CSQC) || defined(MENU)\n"); - break; - case H2|QW|CS|MENU: - VFS_PRINTF(f, "#if defined(H2) || defined(CSQC) || defined(QWSSQC) || defined(MENU)\n"); - break; - case H2|NQ|CS|MENU: - VFS_PRINTF(f, "#if defined(H2) || defined(CSQC) || defined(NQSSQC) || defined(MENU)\n"); - break; - case ALL: - VFS_PRINTF(f, "#if 1\n"); - break; - default: - VFS_PRINTF(f, "#if 0 //???\n"); - break; - } - } - } + if (BuiltinList[i].obsolete) + VFS_PRINTF(f, "//"); + PR_DumpPlatform_SymbolType(f, symtab, BuiltinList[i].prototype, BuiltinList[i].name); if (idx) - VFS_PRINTF(f, "%s%s %s = #%u;", BuiltinList[i].obsolete?"//":"", BuiltinList[i].prototype, BuiltinList[i].name, idx); + VFS_PRINTF(f, "%s = #%u;", BuiltinList[i].name, idx); else - VFS_PRINTF(f, "%s%s %s = #%u:%s;", BuiltinList[i].obsolete?"//":"", BuiltinList[i].prototype, BuiltinList[i].name, idx, BuiltinList[i].name); + VFS_PRINTF(f, "%s = #%u:%s;", BuiltinList[i].name, idx, BuiltinList[i].name); nd = 0; for (j = 0; j < QSG_Extensions_count; j++) { @@ -13436,14 +13658,13 @@ void PR_DumpPlatform_f(void) else VFS_PRINTF(f, "\n"); } - if (d != (ALL & ~targ)) - VFS_PRINTF(f, "#endif\n"); + PR_DumpPlatform_GenIfdef(f, targ, ALL, &d); #if defined(CSQC_DAT) || defined(MENU_DAT) if (targ & (CS|MENU)) { VFS_PRINTF(f, "#if defined(CSQC) || defined(MENU)\n"); - Key_PrintQCDefines(f); + Key_PrintQCDefines(f, defines); VFS_PRINTF(f, "#endif\n"); } #endif diff --git a/engine/server/progdefs.h b/engine/server/progdefs.h index e7008af34..a969ecefd 100644 --- a/engine/server/progdefs.h +++ b/engine/server/progdefs.h @@ -243,7 +243,7 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldfloat(dimension_hit,"This is the bitmask of dimensions which the entity will be blocked by. If other.dimension_solid & self.dimension_hit, our traces will impact and not proceed. If its false, the traces will NOT impact, allowing self to pass straight through.")/*EXT_DIMENSION_PHYSICS*/\ /*comfieldfloat_legacy(hitcontentsmask,"Traces performed for this entity will impact against surfaces that match this contents mask.")*/ \ comfieldint(hitcontentsmaski,"Traces performed for this entity will impact against surfaces that match this contents mask (CONTENTBITS_* constants).")\ - comfieldfloat_legacy(dphitcontentsmask, "Some crappy field that inefficiently requires translating to the native contents flags. Ditch the 'dp', do it properly.")\ + comfieldfloatdep_legacy(dphitcontentsmask, "Some crappy field that inefficiently requires translating to the native contents flags. Ditch the 'dp', do it properly.", "Does not support mos-ecific contents.")\ comfieldfloat(scale,"Multiplier that resizes the entity. 1 is normal sized, 2 is double sized. scale 0 is remapped to 1. In SSQC, this is limited to 1/16th precision, with a maximum just shy of 16.")/*DP_ENT_SCALE*/\ comfieldfloat(fatness,"How many QuakeUnits to push the entity's verticies along their normals by.")/*FTE_PEXT_FATNESS*/\ comfieldfloat(alpha,"The transparency of the entity. 1 means opaque, 0.0001 means virtually invisible. 0 is remapped to 1, for compatibility.")/*DP_ENT_ALPHA*/\ @@ -312,7 +312,7 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldfloatdep_legacy(Version,"Obsolete", "Use SendFlags instead.")/*EXT_CSQC (obsolete)*/\ comfieldfloatdep_legacy(clientcolors,NULL, "Doesn't support RGB player colours.")\ comfieldfloat_legacy(viewzoom,NULL)/*DP_VIEWZOOM, stats*/\ - comfieldfloat_legacy(items2,NULL) /*added in quake 1.09 (for hipnotic). legacy because of stats*/\ + comfieldfloat_legacy(items2,"stub. commented by default, to prevent items2 being networked instead of runes.") /*added in quake 1.09 (for hipnotic). legacy because of stats*/\ svextqcfieldshexen2 \ comfieldfloat(pvsflags,"Reconfigures when the entity is visible to clients")/*EXT_CSQC_1*/\ comfieldfloat(uniquespawnid,"Incremented by 1 whenever the entity is respawned. Persists across remove calls, for when the two-second grace period is insufficient.")/*FTE_ENT_UNIQUESPAWNID*/\ diff --git a/engine/server/savegame.c b/engine/server/savegame.c index 02068db7e..3bb65e91d 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -1462,6 +1462,25 @@ void SV_LoadPlayers(loadplayer_t *lp, size_t slots) size_t clnum, p, p2; int to[255]; + //kick any splitscreen seats. they'll get re-added after load (filling slots like connecting players would) + for (clnum = 0; clnum < svs.allocated_client_slots; clnum++) + { + cl = &svs.clients[clnum]; + cl->controlled = NULL; //kill the links. + if (cl->controller) //its a slave + { + //unlink it + cl->controller = NULL; + + //make it into a pseudo-bot so the kicking doesn't do weird stuff. + cl->netchan.remote_address.type = NA_INVALID; //so the remaining client doesn't get the kick too. + cl->protocol = SCP_BAD; //make it a bit like a bot, so we don't try sending any datagrams/reliables at someone that isn't able to receive anything. + + //okay, it can get lost now. + cl->drop = true; + } + } + //despawn any entity data, and try to find the loaded player to move them to for (clnum = 0; clnum < svs.allocated_client_slots; clnum++) //clear the server for the level change. { @@ -1578,8 +1597,10 @@ static void SV_GameLoaded(loadplayer_t *lp, size_t slots, const char *savename) cl = &svs.clients[clnum]; cl->spawned = !!*lp[clnum].name; if (cl->spawned) + { sv.spawned_client_slots++; - + Q_strncpyz(cl->namebuf, lp[clnum].name, sizeof(cl->namebuf)); + } cl->name = PR_AddString(svprogfuncs, cl->namebuf, sizeof(cl->namebuf), false); cl->team = PR_AddString(svprogfuncs, cl->teambuf, sizeof(cl->teambuf), false); diff --git a/engine/server/server.h b/engine/server/server.h index 6d41e0388..5229e7898 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -110,7 +110,6 @@ typedef struct server_state_t state; // precache commands are only valid during load float gamespeed; //time progression multiplier, fixed per-level. - qboolean csqcdebug; unsigned int csqcchecksum; qboolean mapchangelocked; qboolean restarting; @@ -1092,6 +1091,7 @@ void SV_Master_Shutdown(void); void SV_Master_Heartbeat (void); extern cvar_t pr_ssqc_progs; +extern cvar_t sv_csqcdebug; extern cvar_t spawn; extern cvar_t teamplay; extern cvar_t deathmatch; diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 8dc276cb3..be7a6c3c9 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -2120,7 +2120,7 @@ static void SV_Status_f (void) Con_TPrintf("particles : %i/%i\n", count, MAX_SSPARTICLESPRE); } Con_TPrintf("gamedir : %s\n", FS_GetGamedir(true)); - if (sv.csqcdebug) + if (sv_csqcdebug.ival) Con_TPrintf("csqc debug : true\n"); #ifdef MVD_RECORDING SV_Demo_PrintOutputs(); diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 1a47e0752..3bf90bc3d 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -326,6 +326,9 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber) csqcmsgbuffer.packing = msg->packing; csqcmsgbuffer.prim = msg->prim; + if (sv_csqcdebug.ival) + svcnumber = svcfte_csqcentities_sized; + for (en = 0, entnum = 0; en < csqcnuments; en++, entnum++) { ent = csqcent[en]; @@ -422,7 +425,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber) MSG_WriteByte(msg, svcnumber); } SV_EmitDeltaEntIndex(msg, entnum, false, client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS); - if (sv.csqcdebug) //optional extra length prefix. + if (svcnumber == svcfte_csqcentities_sized) //optional extra length prefix. { if (!csqcmsgbuffer.cursize) Con_Printf("Warning: empty csqc packet on %s\n", PR_GetString(svprogfuncs, ent->v->classname)); diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index b2d9a1f1e..90cca4800 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -42,7 +42,6 @@ extern cvar_t skill; extern cvar_t sv_cheats; extern cvar_t sv_bigcoords; extern cvar_t sv_gamespeed; -extern cvar_t sv_csqcdebug; extern cvar_t sv_csqc_progname; extern cvar_t sv_calcphs; extern cvar_t sv_playerslots, maxclients, maxspectators; @@ -1103,12 +1102,6 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents, InfoBuf_SetValueForStarKey(&svs.info, "*csprogssize", ""); InfoBuf_SetValueForStarKey(&svs.info, "*csprogsname", ""); } - - sv.csqcdebug = sv_csqcdebug.value; - if (sv.csqcdebug) - InfoBuf_SetValueForStarKey(&svs.info, "*csqcdebug", "1"); - else - InfoBuf_RemoveKey(&svs.info, "*csqcdebug"); #endif if (svs.gametype == GT_PROGS) diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 4c6660c58..33105db85 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -214,6 +214,7 @@ vfsfile_t *sv_fraglogfile; void SV_AcceptClient (netadr_t *adr, int userid, char *userinfo); void PRH2_SetPlayerClass(client_t *cl, int classnum, qboolean fromqc); +void SV_DeDupeName(const char *val, client_t *cl, char *newname, size_t newnamesize); int nextuserid; @@ -2183,7 +2184,8 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id) int i, j; int curclients; qboolean loadgame; - const char *name; +// const char *name; + char newname[80]; unsigned int clients = 0, spectators = 0; qboolean asspec; @@ -2233,12 +2235,12 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id) } */ - name = Info_ValueForKey(info, "name"); + SV_DeDupeName(Info_ValueForKey(info, "name"), cl, newname, sizeof(newname)); for (i=0,cl=svs.clients ; istate == cs_loadzombie && !controller->spectator) { //if this is a loadzombie with the same name as the new seat is trying to use then lets use that slot. - if (!strcmp(cl->name, name)) + if (!strcmp(cl->name, newname)) break; } } @@ -2279,6 +2281,27 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id) return NULL; } + + { //save off anything we might want to preserve + qboolean tobeloaded = cl->istobeloaded; + qboolean spawned = cl->spawned; + unsigned int userid = cl->userid; + float spawn_parms[NUM_SPAWN_PARMS]; + memcpy(spawn_parms, cl->spawn_parms, sizeof(spawn_parms)); + + //now actually wipe the player slot + memset(cl, 0, sizeof(*cl)); + + //and restore preserved stuff, if its appropriate. + if (loadgame) + { + cl->istobeloaded = tobeloaded; + cl->spawned = spawned; + cl->userid = userid; + memcpy(cl->spawn_parms, spawn_parms, sizeof(cl->spawn_parms)); + } + } + cl->spectator = asspec; cl->netchan.remote_address = controller->netchan.remote_address; cl->netchan.message.prim = controller->netchan.message.prim; @@ -2601,6 +2624,7 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info) newcl = cl; preserveparms = true; temp.istobeloaded = cl->istobeloaded; + temp.spawned = cl->spawned; memcpy(temp.spawn_parms, cl->spawn_parms, sizeof(temp.spawn_parms)); if (cl->userid) temp.userid = cl->userid; @@ -5565,6 +5589,70 @@ void SV_FixupName(const char *in, char *out, unsigned int outlen) p[1] = 0; } +void SV_DeDupeName(const char *val, client_t *cl, char *newname, size_t newnamesize) +{ + int i; + client_t *client; + int dupc = 1; + char basic[80]; + const char *p; + if (!val) + val = ""; + //we block large names here because a) they're unwieldly. b) they might cause players to be invisible to older clients/server browsers/etc. + //bots with no name skip the fixup, to avoid default names(they're expected to be given a name eventually, so are allowed to be invisible for now) + if (cl && cl->protocol == SCP_BAD && !*val) + newname[0] = 0; + else + { + SV_FixupName(val, newname, newnamesize); + if (strlen(newname) > 40) + newname[40] = 0; + } + + //strip weirdness + deleetstring(basic, newname); + + + if (!cl || cl->protocol != SCP_BAD) + { //don't bother validating bot names. The gamecode is expected to not be stupid. + if (!basic[0] || strstr(basic, "console")) + strcpy(newname, "unnamed"); + + // check to see if another user by the same name exists + while (1) + { + for (i=0, client = svs.clients ; istate < cs_connected || client == cl) + continue; + if (!stricmp(client->name, newname)) + break; + } + if (i != svs.allocated_client_slots) + { // dup name + char tmpname[80]; + if (strlen(newname) > sizeof(cl->namebuf) - 1) + newname[sizeof(cl->namebuf) - 4] = 0; + p = newname; + + if (newname[0] == '(') + { + if (newname[2] == ')') + p = newname + 3; + else if (val[3] == ')') + p = newname + 4; + } + + memcpy(tmpname, p, strlen(p)+1); + + Q_snprintfz(newname, newnamesize, "(%d)%-.40s", dupc++, tmpname); + } + else + break; + } + } +} + qboolean ReloadRanking(client_t *cl, const char *newname) { @@ -5631,10 +5719,7 @@ into a more C freindly form. void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose) { const char *val, *p; - int i; - client_t *client; - int dupc = 1; - char newname[80], basic[80]; + char newname[80]; #ifdef SVRANKING extern cvar_t rank_filename; #endif @@ -5658,58 +5743,10 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose) // name for C code val = InfoBuf_BlobForKey (&cl->userinfo, "name", &blobsize, &large); - if (!val) + if (large) //don't allow it if there's even anything weird in there (simplies the necessary qc). val = ""; - //we block large names here because a) they're unwieldly. b) they might cause players to be invisible to older clients/server browsers/etc. - //bots with no name skip the fixup, to avoid default names(they're expected to be given a name eventually, so are allowed to be invisible for now) - if (large || (cl->protocol == SCP_BAD && !*val)) - newname[0] = 0; - else - { - SV_FixupName(val, newname, sizeof(newname)); - if (strlen(newname) > 40) - newname[40] = 0; - } - - deleetstring(basic, newname); - if (cl->protocol != SCP_BAD) - { //don't bother validating bot names. The gamecode is expected to not be stupid. - if (!basic[0] || strstr(basic, "console")) - strcpy(newname, "unnamed"); - - // check to see if another user by the same name exists - while (1) - { - for (i=0, client = svs.clients ; istate < cs_connected || client == cl) - continue; - if (!stricmp(client->name, newname)) - break; - } - if (i != svs.allocated_client_slots) - { // dup name - char tmpname[80]; - if (strlen(newname) > sizeof(cl->namebuf) - 1) - newname[sizeof(cl->namebuf) - 4] = 0; - p = newname; - - if (newname[0] == '(') - { - if (newname[2] == ')') - p = newname + 3; - else if (val[3] == ')') - p = newname + 4; - } - - memcpy(tmpname, p, strlen(p)+1); - - sprintf(newname, "(%d)%-.40s", dupc++, tmpname); - } - else - break; - } - } + //fixup and dedupe + SV_DeDupeName(val, cl, newname, sizeof(newname)); if (!cl->drop && strncmp(newname, cl->name, sizeof(cl->namebuf)-1)) { diff --git a/engine/server/sv_mvd.c b/engine/server/sv_mvd.c index bd4a708f2..8c5cbd0fb 100644 --- a/engine/server/sv_mvd.c +++ b/engine/server/sv_mvd.c @@ -2425,6 +2425,39 @@ int Dem_CountTeamPlayers (char *t) return count; } +//takes a quake-mark-up string (subject to com_parseutf and ^ etc) and spits out a usable utf-8 name +//in and out may overlap. +static char *FS_UTF8FromQuakeFilename(const char *in, qboolean dequake, qboolean keepmarkup, qboolean blockdirsep, char *out, size_t outsize) +{ + conchar_t cline[8192], *c; + char *outend = out+outsize-1; //-1 for our null + unsigned int charflags, codepoint; + + COM_ParseFunString(CON_WHITEMASK, in, cline, sizeof(cline), keepmarkup); + for (c = cline; *c; ) + { + c = Font_Decode(c, &charflags, &codepoint); + if (charflags & CON_HIDDEN) + continue; + if (dequake) + codepoint = COM_DeQuake(codepoint); + + if (codepoint == '/' && blockdirsep) codepoint = '-'; //spreading across multiple dirs is just awkward + else if (codepoint < ' ' ) codepoint = '-'; //C0 chars are all kinds of problematic + else if (codepoint == '\\') codepoint = '-'; //windows sucks. or string escapes do. + else if (codepoint == ':' ) codepoint = '-'; //drives, or Alternative Data Streams (read: often hidden) + else if (codepoint == '\"') codepoint = '-'; //erk! escapes necessitate escapes... + else if (codepoint == '<' ) codepoint = '-'; //pipe stuff sucks + else if (codepoint == '>' ) codepoint = '-'; //pipe stuff sucks + else if (codepoint == '|' ) codepoint = '-'; //pipe stuff sucks + else if (codepoint == '?' ) codepoint = '-'; //wildcards complicate things + else if (codepoint == '*' ) codepoint = '-'; //wildcards complicate things + + out += utf8_encode(out, codepoint, outend-out); + } + *out = 0; + return out; +} // <- void SV_MVDEasyRecord_f (void) @@ -2454,10 +2487,8 @@ void SV_MVDEasyRecord_f (void) if (c == 2) { - char *c; Q_strncpyz (name, Cmd_Argv(1), sizeof(name)); - while((c = strchr(name, ':'))) - *c = '-'; + FS_UTF8FromQuakeFilename(name, true, false, false, name, sizeof(name)); } else { @@ -2493,6 +2524,9 @@ void SV_MVDEasyRecord_f (void) snprintf (name, sizeof(name), "ffa_%s(%d)", svs.name, i); } } + + //convert to utf-8, so its readable on most systems (we convert utf-8 to utf-16 for windows, while linux tends to just use utf-8 in the first place) + FS_UTF8FromQuakeFilename(name, true, false, true, name, sizeof(name)); } // <- diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 85c62ef2c..564cdfa7e 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -275,7 +275,7 @@ void SV_New_f (void) if (dpcompat_nopreparse.ival && progstype != PROG_QW) { - SV_PrintToClient(host_client, PRINT_HIGH, "This server now has network preparsing disabled, and thus only supports NetQuake clients\n"); + SV_PrintToClient(host_client, PRINT_HIGH, "This server has network preparsing disabled, and thus only supports NetQuake clients\n"); Con_Printf("%s was not using NQ protocols\n", host_client->name); host_client->drop = true; return; @@ -364,7 +364,6 @@ void SV_New_f (void) #ifdef SVRANKING split->stats_started = realtime; #endif - splitnum++; } } else @@ -533,7 +532,7 @@ void SVNQ_New_f (void) if (dpcompat_nopreparse.ival && progstype == PROG_QW) { - SV_PrintToClient(host_client, PRINT_HIGH, "This server now has network preparsing disabled, and thus only supports QuakeWorld clients\n"); + SV_PrintToClient(host_client, PRINT_HIGH, "This server has network preparsing disabled, and thus only supports QuakeWorld clients\n"); Con_Printf("%s was not using QW protocols\n", host_client->name); host_client->drop = true; return; @@ -560,17 +559,25 @@ void SVNQ_New_f (void) { int id; qboolean big; //used as a filter to exclude protocols that don't match our coord+angles mode + qboolean pextonly; } preferedprot[] = { + //favour fitz over dp's. this is on the assumption that we can use pext stuff when both are available. + {SCP_FITZ666, true, true}, //actually fte+999... shh... + {SCP_FITZ666, false, true}, //actually fte+666. + //next best is probably dp's stuff {SCP_DARKPLACES7, true}, {SCP_DARKPLACES6, true}, + //unextended fitz is kinda lame, but has some bells on it. {SCP_FITZ666, true}, //actually 999... shh... {SCP_FITZ666, false}, + //well, we can still get bigger model/soundindexes out of this {SCP_BJP3, false} //should we only use this when we have >255 models/sounds? }; for (i = 0; i < countof(preferedprot); i++) { if (preferedprot[i].big == !!(protext1 & PEXT_FLOATCOORDS)) + if (!preferedprot[i].pextonly || (protext2&PEXT2_REPLACEMENTDELTAS)) { if (host_client->supportedprotocols & (1u<fteprotocolextensions2 & PEXT2_PREDINFO)) + if (!ISNQCLIENT(client) || (client->fteprotocolextensions & PEXT_CSQC) || (client->fteprotocolextensions2 & PEXT2_PREDINFO)) { //nq does not normally get serverinfo sent to it. i = InfoBuf_ToString(&svs.info, buffer, sizeof(buffer), prioritykeys, ignorekeys, NULL, &client->infosync, &svs.info); Info_SetValueForStarKey(buffer, "*z_ext", va("%i", client->zquake_extensions), sizeof(buffer)); //should already be in there, so this should only ever make it shorter. ClientReliableWrite_Begin(client, svc_stufftext, 20 + i); ClientReliableWrite_String (client, va("fullserverinfo \"%s\"\n", buffer) ); } - else if (sv.csqcdebug) - { - i = InfoBuf_ToString(&svs.info, buffer, sizeof(buffer), prioritykeys, ignorekeys, NULL, &client->infosync, &svs.info); - ClientReliableWrite_Begin(client, svc_stufftext, 22 + i); - ClientReliableWrite_String (client, va("//fullserverinfo \"%s\"\n", buffer) ); - } } else if (client->prespawn_idx == 3) { diff --git a/engine/server/world.c b/engine/server/world.c index a1c1e6254..eea46dd5f 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -2511,7 +2511,7 @@ static void World_ClipToNetwork (world_t *w, moveclip_t *clip) else { trace.ent = w->edicts; //misreport world - clip->trace.entnum = touch->number; //with an ssqc ent number + trace.entnum = touch->number; //with an ssqc ent number } clip->trace = trace; } diff --git a/engine/vk/vk_init.c b/engine/vk/vk_init.c index 5d5f997d9..4dfe9d2e6 100644 --- a/engine/vk/vk_init.c +++ b/engine/vk/vk_init.c @@ -1119,8 +1119,8 @@ void VK_Draw_Init(void) void VK_Draw_Shutdown(void) { R2D_Shutdown(); - Image_Shutdown(); Shader_Shutdown(); + Image_Shutdown(); } void VK_CreateSampler(unsigned int flags, vk_image_t *img) @@ -2094,6 +2094,8 @@ void VK_R_DeInit (void) VK_Shutdown_PostProc(); VK_DestroySwapChain(); VKBE_Shutdown(); + + R2D_Shutdown(); Shader_Shutdown(); Image_Shutdown(); }