Add some extension checks to avoid problems when running menusys in engines that lack support for various features...

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5812 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2021-04-08 19:16:34 +00:00
parent d855cc6e84
commit cd50a54a5a
14 changed files with 3836 additions and 3609 deletions

View File

@ -6,8 +6,7 @@
#define CSQC //select the module #define CSQC //select the module
#ifdef CSQC_SIMPLE #ifdef CSQC_SIMPLE
#include "qsextensions.qc" //also sets up system defs #include "qsextensions.qc" //also sets up system defs
#undef CSQC_SIMPLE #include "fteextensions.qc" //extra stuff
#include "fteextensions.qc" //extra stuff...
#else #else
#include "fteextensions.qc" //also sets up system defs #include "fteextensions.qc" //also sets up system defs
#endif #endif

View File

@ -1,16 +1,8 @@
/* /*
This file was generated by FTE Quake 5740, dated 2020-08-03T10:34:44.534153Z. This file was generated by FTE Quake 5781, dated 2020-10-26T11:48:50.477494Z.
This file can be regenerated by issuing the following command: This file can be regenerated by issuing the following command:
pr_dumpplatform -o fteextensions pr_dumpplatform -o fteextensions
Available options: (Use the -help arg for a list of available args)
-Ffte - target only FTE (optimations and additional extensions)
-Tnq - dump specifically NQ fields
-Tqw - dump specifically QW fields
-Tcs - dump specifically CSQC fields
-Tmenu - dump specifically menuqc fields
-Fdefines - generate #defines instead of constants
-Faccessors - use accessors instead of basic types via defines
-O - write to a different qc file
*/ */
#pragma noref 1 #pragma noref 1
//#pragma flag enable logicops //#pragma flag enable logicops
@ -18,23 +10,22 @@ Available options:
#pragma warning error Q105 /*too few parms. The vanilla qcc didn't validate properly, hence why fteqcc normally treats it as a warning.*/ #pragma warning error Q105 /*too few parms. The vanilla qcc didn't validate properly, hence why fteqcc normally treats it as a warning.*/
#pragma warning error Q106 /*assignment to constant/lvalue. Define them as var if you want to initialise something.*/ #pragma warning error Q106 /*assignment to constant/lvalue. Define them as var if you want to initialise something.*/
#pragma warning error Q208 /*system crc unknown. Compatibility goes out of the window if you disable this.*/ #pragma warning error Q208 /*system crc unknown. Compatibility goes out of the window if you disable this.*/
#pragma warning disable F211 /*system crc outdated (eg: dp's csqc). Note that this may trigger emulation.*/
#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.*/ #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.*/
#pragma warning enable F302 /*uninitialised locals. They usually default to 0 in qc (except in recursive functions), but its still probably a bug*/ #pragma warning enable F302 /*uninitialised locals. They usually default to 0 in qc (except in recursive functions), but its still probably a bug*/
#if !defined(CSQC) && !defined(NQSSQC) && !defined(QWSSQC)&& !defined(MENU) #if !defined(CSQC) && !defined(NQSSQC) && !defined(QWSSQC)&& !defined(MENU)
#ifdef QUAKEWORLD #ifdef QUAKEWORLD
#define QWSSQC #define QWSSQC
#else #else
#define NQSSQC #define NQSSQC
#endif #endif
#endif #endif
#if !defined(SSQC) && (defined(QWSSQC) || defined(NQSSQC)) #if !defined(SSQC) && (defined(QWSSQC) || defined(NQSSQC))
#define SSQC #define SSQC
#endif #endif
#if defined(CSQC) || defined(MENU) #if defined(CSQC) || defined(MENU)
#define DEP_CSQC DEP #define DEP_CSQC DEP
#else #else
#define DEP_CSQC __deprecated("Use CSQC for this") #define DEP_CSQC __deprecated("Use CSQC for this")
#endif #endif
#ifndef DEP #ifndef DEP
#define DEP __deprecated //predefine this if you want to avoid our deprecation warnings. #define DEP __deprecated //predefine this if you want to avoid our deprecation warnings.
@ -210,7 +201,7 @@ Available options:
#define FTE_MULTIPROGS /* Multiple progs.dat files can be loaded inside the same qcvm. Insert new ones with addprogs inside the 'init' function, and use externvalue+externset to rewrite globals (and hook functions) to link them together. Note that the result is generally not very clean unless you carefully design for it beforehand. */ #define FTE_MULTIPROGS /* Multiple progs.dat files can be loaded inside the same qcvm. Insert new ones with addprogs inside the 'init' function, and use externvalue+externset to rewrite globals (and hook functions) to link them together. Note that the result is generally not very clean unless you carefully design for it beforehand. */
#define FTE_MULTITHREADED /* Faux multithreading, allowing multiple contexts to run in sequence. */ #define FTE_MULTITHREADED /* Faux multithreading, allowing multiple contexts to run in sequence. */
#define FTE_MVD_PLAYERSTATS /* In csqc, getplayerstat can be used to query any player's stats when playing back MVDs. isdemo will return 2 in this case. */ #define FTE_MVD_PLAYERSTATS /* In csqc, getplayerstat can be used to query any player's stats when playing back MVDs. isdemo will return 2 in this case. */
#define FTE_PART_SCRIPT /* Specifies that the r_particledesc cvar can be used to select a list of particle effects to load from particles/*.cfg, the format of which is documented elsewhere. */ #define FTE_PART_SCRIPT /* Specifies that the r_particledesc cvar can be used to select a list of particle effects to load from particles/foo.cfg, the format of which is documented elsewhere. */
#define FTE_PART_NAMESPACES /* Specifies that the engine can use foo.bar to load effect foo from particle description bar. When used via ssqc, this should cause the client to download whatever effects as needed. */ #define FTE_PART_NAMESPACES /* Specifies that the engine can use foo.bar to load effect foo from particle description bar. When used via ssqc, this should cause the client to download whatever effects as needed. */
#define FTE_PART_NAMESPACE_EFFECTINFO /* Specifies that effectinfo.bar can load effects from effectinfo.txt for DP compatibility. */ #define FTE_PART_NAMESPACE_EFFECTINFO /* Specifies that effectinfo.bar can load effects from effectinfo.txt for DP compatibility. */
#define FTE_QC_BASEFRAME /* Specifies that .basebone and .baseframe exist in ssqc. These fields affect all bones in the entity's model with a lower index than the .basebone field, allowing you to give separate control to the legs of a skeletal model, without affecting the torso animations, from ssqc. */ #define FTE_QC_BASEFRAME /* Specifies that .basebone and .baseframe exist in ssqc. These fields affect all bones in the entity's model with a lower index than the .basebone field, allowing you to give separate control to the legs of a skeletal model, without affecting the torso animations, from ssqc. */
@ -319,20 +310,40 @@ float total_secrets;
float total_monsters; float total_monsters;
float found_secrets; float found_secrets;
float killed_monsters; float killed_monsters;
float parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8, parm9, parm10, parm11, parm12, parm13, parm14, parm15, parm16; /* 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. */ float parm1; /* 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. */
float parm2; /* 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. */
float parm3; /* 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. */
float parm4; /* 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. */
float parm5; /* 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. */
float parm6; /* 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. */
float parm7; /* 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. */
float parm8; /* 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. */
float parm9; /* 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. */
float parm10; /* 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. */
float parm11; /* 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. */
float parm12; /* 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. */
float parm13; /* 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. */
float parm14; /* 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. */
float parm15; /* 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. */
float parm16; /* 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. */
#endif #endif
#ifdef CSQC #ifdef CSQC
float intermission; float intermission;
#endif #endif
#if defined(CSQC) || defined(SSQC) #if defined(CSQC) || defined(SSQC)
vector v_forward, v_up, v_right; vector v_forward;
vector v_up;
vector v_right;
#endif #endif
#ifdef CSQC #ifdef CSQC
vector view_angles; /* +x=DOWN */ vector view_angles; /* +x=DOWN */
#endif #endif
#if defined(CSQC) || defined(SSQC) #if defined(CSQC) || defined(SSQC)
float trace_allsolid, trace_startsolid, trace_fraction; float trace_allsolid;
vector trace_endpos, trace_plane_normal; float trace_startsolid;
float trace_fraction;
vector trace_endpos;
vector trace_plane_normal;
float trace_plane_dist; float trace_plane_dist;
entity trace_ent; entity trace_ent;
float trace_inopen; float trace_inopen;
@ -520,7 +531,7 @@ int trace_bone_id; /* 1-based. 0 if not known. typically needs MOVE_HITMODEL. */
int trace_triangle_id; /* 1-based. 0 if not known. */ int trace_triangle_id; /* 1-based. 0 if not known. */
#endif #endif
#ifdef CSQC #ifdef CSQC
int trace_networkentity; /* Repots which ssqc entnum was hit when a csqc traceline impacts an ssqc-based brush entity. */ float trace_networkentity; /* Repots which ssqc entnum was hit when a csqc traceline impacts an ssqc-based brush entity. */
vector pmove_org; /* Reports the origin of the engineside player (after prediction). Does not work when the player is a csqc-owned entity. */ vector pmove_org; /* Reports the origin of the engineside player (after prediction). Does not work when the player is a csqc-owned entity. */
vector pmove_vel; /* Reports the velocity of the engineside player (after prediction). Does not work when the player is a csqc-owned entity. */ vector pmove_vel; /* Reports the velocity of the engineside player (after prediction). Does not work when the player is a csqc-owned entity. */
float pmove_onground; /* Reports the onground state of the engineside player (after prediction). Does not work when the player is a csqc-owned entity. */ float pmove_onground; /* Reports the onground state of the engineside player (after prediction). Does not work when the player is a csqc-owned entity. */
@ -529,6 +540,9 @@ float pmove_onground; /* Reports the onground state of the engineside player (af
vector global_gravitydir = '0 0 -1'; /* The direction gravity should act in if not otherwise specified per entity. */ vector global_gravitydir = '0 0 -1'; /* The direction gravity should act in if not otherwise specified per entity. */
int serverid; /* The unique id of this server within the server cluster. */ int serverid; /* The unique id of this server within the server cluster. */
#endif #endif
#ifdef CSQC
.string message; /* Allows the csqc to read the map description from the server. */
#endif
#ifdef SSQC #ifdef SSQC
.float button3; .float button3;
.float button4; .float button4;
@ -538,6 +552,21 @@ int serverid; /* The unique id of this server within the server cluster. */
.float button8; .float button8;
#endif #endif
#if defined(NQSSQC) #if defined(NQSSQC)
.float buttonuse; /* For DP compat only. */
.float buttonchat; /* For DP compat only. */
.float cursor_active; /* For DP compat only. */
.float button9; /* For DP compat only. */
.float button10; /* For DP compat only. */
.float button11; /* For DP compat only. */
.float button12; /* For DP compat only. */
.float button13; /* For DP compat only. */
.float button14; /* For DP compat only. */
.float button15; /* For DP compat only. */
.float button16; /* For DP compat only. */
.vector cursor_screen; /* For DP compat only. */
.vector cursor_start; /* For DP compat only. */
.vector cursor_impact; /* For DP compat only. */
.entity cursor_entitynumber; /* For DP compat only. */
.float lastruntime; /* 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. */ .float lastruntime; /* 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. */
#endif #endif
#if defined(CSQC) || defined(QWSSQC) #if defined(CSQC) || defined(QWSSQC)
@ -552,7 +581,7 @@ int serverid; /* The unique id of this server within the server cluster. */
.float dimension_solid; /* This is the bitmask of dimensions which the entity is solid within. This is not networked, instead csqc traces impacting ssqc entities assumes the ssqc entity to have a dimension_solid of 1. */ .float dimension_solid; /* This is the bitmask of dimensions which the entity is solid within. This is not networked, instead csqc traces impacting ssqc entities assumes the ssqc entity to have a dimension_solid of 1. */
.float 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. */ .float 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. */
.int hitcontentsmaski; /* Traces performed for this entity will impact against surfaces that match this contents mask (CONTENTBITS_* constants). */ .int hitcontentsmaski; /* Traces performed for this entity will impact against surfaces that match this contents mask (CONTENTBITS_* constants). */
.float dphitcontentsmask; /* Some crappy field that inefficiently requires translating to the native contents flags. Ditch the 'dp', do it properly. */ __deprecated("Does not support mos-ecific contents.") .float dphitcontentsmask; /* Some crappy field that inefficiently requires translating to the native contents flags. Ditch the 'dp', do it properly. */
.float 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. */ .float 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. */
.float fatness; /* How many QuakeUnits to push the entity's verticies along their normals by. */ .float fatness; /* How many QuakeUnits to push the entity's verticies along their normals by. */
.float alpha; /* The transparency of the entity. 1 means opaque, 0.0001 means virtually invisible. 0 is remapped to 1, for compatibility. */ .float alpha; /* The transparency of the entity. 1 means opaque, 0.0001 means virtually invisible. 0 is remapped to 1, for compatibility. */
@ -621,7 +650,6 @@ __deprecated("Does not work with MVDs nor splitscreen.") .float dimension_ghost_
__deprecated("Use SendFlags instead.") .float Version; /* Obsolete */ __deprecated("Use SendFlags instead.") .float Version; /* Obsolete */
__deprecated("Doesn't support RGB player colours.") .float clientcolors; __deprecated("Doesn't support RGB player colours.") .float clientcolors;
.float viewzoom; .float viewzoom;
.float items2;
.float playerclass; .float playerclass;
.float hasted; .float hasted;
.float light_level; /* Used by hexen2 to indicate the light level where the player is standing. */ .float light_level; /* Used by hexen2 to indicate the light level where the player is standing. */
@ -731,6 +759,7 @@ string startspot; /* Receives the value of the second argument to changelevel fr
var float dimension_send; /* Used by multicast functionality. Multicasts (and related builtins that multicast internally) will only be sent to players where (player.dimension_see & dimension_send) is non-zero. */ var float dimension_send; /* Used by multicast functionality. Multicasts (and related builtins that multicast internally) will only be sent to players where (player.dimension_see & dimension_send) is non-zero. */
//var float dimension_default = 255; //var float dimension_default = 255;
/* Default dimension bitmask */ /* Default dimension bitmask */
__unused var string __fullspawndata; /* Set by the engine before calls to spawn functions, and is most easily parsed with the tokenize builtin. This allows you to handle halflife's multiple-fields-with-the-same-name (or target-specific fields). */
#endif #endif
#if defined(CSQC) || defined(SSQC) #if defined(CSQC) || defined(SSQC)
__used var float physics_mode = 2; /* 0: original csqc - physics are not run __used var float physics_mode = 2; /* 0: original csqc - physics are not run
@ -746,6 +775,42 @@ var vector drawfontscale = '1 1 0'; /* Specifies a scaler for all text rendering
float drawfont; /* Allows you to choose exactly which font is to be used to draw text. Fonts can be registered/allocated with the loadfont builtin. */ float drawfont; /* Allows you to choose exactly which font is to be used to draw text. Fonts can be registered/allocated with the loadfont builtin. */
const float FONT_DEFAULT = 0; const float FONT_DEFAULT = 0;
#endif #endif
#ifdef CSQC
float(vector angles, float isdelta) CSQC_Parse_SetAngles;
void(float playernum) CSQC_PlayerInfoChanged;
void() CSQC_ServerInfoChanged;
DEP("use CSQC_Event_Sound") float(float channel, string soundname, vector pos, float vol, float attenuation, float flags) CSQC_ServerSound;
void(int entidx, string newentdata) CSQC_MapEntityEdited;
float clframetime;
float servertime;
float serverprevtime;
float serverdeltatime;
float deathmatch;
float coop;
int trace_surfaceflagsi;
string trace_surfacename;
int trace_endcontentsi;
string trace_dphittexturename;
DEP("Does not support mod-specific contents.") float trace_dpstartcontents;
DEP("Does not support mod-specific contents.") float trace_dphitcontents;
DEP("Does not support mod-specific surface flags") float trace_dphitq3surfaceflags;
DEP("Does not support all mod-specific surface flags.") float trace_surfaceflagsf;
DEP("Does not support all mod-specific contents.") float trace_endcontentsf;
float intermission_time;
vector pmove_mins;
vector pmove_maxs;
float pmove_jump_held;
float pmove_waterjumptime;
float input_lightlevel;
float input_weapon;
float input_servertime;
float input_clienttime;
float input_cursor_entitynumber;
float dimension_default;
float autocvar_vid_conwidth;
float autocvar_vid_conheight;
float cycle_wrapped;
#endif
const float TRUE = 1; const float TRUE = 1;
const float FALSE = 0; /* File not found... */ const float FALSE = 0; /* File not found... */
const float M_PI = 3.14159; /* Mathematica Pi constant. */ const float M_PI = 3.14159; /* Mathematica Pi constant. */
@ -909,7 +974,39 @@ const float ATTN_STATIC = 3; /* Even more attenuation to avoid torches drowing o
#ifdef SSQC #ifdef SSQC
const float SVC_CGAMEPACKET = 83; /* 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. */ const float SVC_CGAMEPACKET = 83; /* 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. */
#endif #endif
#if defined(CSQC) || defined(SSQC)
const float TE_SPIKE = 0;
const float TE_SUPERSPIKE = 1;
#endif
#if defined(CSQC) || defined(QWSSQC)
const float TE_GUNSHOT = 2;
const float TE_EXPLOSION = 3;
#endif
#if defined(NQSSQC) #if defined(NQSSQC)
const float TE_GUNSHOT = 2;
const float TE_EXPLOSION = 3;
#endif
#if defined(CSQC) || defined(SSQC)
const float TE_TAREXPLOSION = 4;
const float TE_LIGHTNING1 = 5;
const float TE_LIGHTNING2 = 6;
const float TE_WIZSPIKE = 7;
const float TE_KNIGHTSPIKE = 8;
const float TE_LIGHTNING3 = 9;
const float TE_LAVASPLASH = 10;
const float TE_TELEPORT = 11;
#endif
#if defined(CSQC) || defined(QWSSQC)
const float TE_BLOOD = 12;
#endif
#if defined(NQSSQC)
const float TE_EXPLOSION2 = 12;
#endif
#if defined(CSQC) || defined(QWSSQC)
const float TE_LIGHTNINGBLOOD = 13;
#endif
#if defined(NQSSQC)
const float TE_BEAM = 13;
const float MSG_BROADCAST = 0; /* The byte(s) will be unreliably sent to all players. MSG_ constants are valid arguments to the Write* builtin family. */ const float MSG_BROADCAST = 0; /* The byte(s) will be unreliably sent to all players. MSG_ constants are valid arguments to the Write* builtin family. */
const float MSG_ONE = 1; /* 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. */ const float MSG_ONE = 1; /* 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. */
const float MSG_ALL = 2; /* The byte(s) will be reliably sent to all players. */ const float MSG_ALL = 2; /* The byte(s) will be reliably sent to all players. */
@ -1030,6 +1127,7 @@ const float FL_LAGGEDMOVE = 65536; /* Enables anti-lag on rockets etc. */
const float MOVE_NORMAL = 0; const float MOVE_NORMAL = 0;
const float MOVE_NOMONSTERS = 1; /* The trace will ignore all non-solid_bsp entities. */ const float MOVE_NOMONSTERS = 1; /* The trace will ignore all non-solid_bsp entities. */
const float MOVE_MISSILE = 2; /* The trace will use a bbox size of +/- 15 against entities with FL_MONSTER set. */ const float MOVE_MISSILE = 2; /* The trace will use a bbox size of +/- 15 against entities with FL_MONSTER set. */
const float MOVE_WORLDONLY = 3; /* 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 . */
const float MOVE_HITMODEL = 4; /* 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). */ const float MOVE_HITMODEL = 4; /* 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). */
const float MOVE_TRIGGERS = 16; /* This trace type will impact only triggers. It will ignore non-solid entities. */ const float MOVE_TRIGGERS = 16; /* This trace type will impact only triggers. It will ignore non-solid entities. */
const float MOVE_EVERYTHING = 32; /* This type of trace will hit solids and triggers alike. Even non-solid entities. */ const float MOVE_EVERYTHING = 32; /* This type of trace will hit solids and triggers alike. Even non-solid entities. */
@ -1041,6 +1139,12 @@ const float MOVE_LAGGED = 64; /* Will use antilag based upon the player's latenc
const float MOVE_ENTCHAIN = 128; /* Returns a list of entities impacted via the trace_ent.chain field */ const float MOVE_ENTCHAIN = 128; /* Returns a list of entities impacted via the trace_ent.chain field */
const float MOVE_OTHERONLY = 256; /* 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. */ const float MOVE_OTHERONLY = 256; /* 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. */
#endif #endif
const float CVAR_TYPEFLAG_EXISTS = 1; /* Cvar name actually exists. */
const float CVAR_TYPEFLAG_SAVED = 2; /* Cvar is flaged for archival (might need cfg_save to actually save). */
const float CVAR_TYPEFLAG_PRIVATE = 4; /* QC is not allowed to read. */
const float CVAR_TYPEFLAG_ENGINE = 8; /* Cvar was created by the engine itself (not user/mod created). */
const float CVAR_TYPEFLAG_HASDESCRIPTION = 16; /* cvar_description will return something (hopefully) useful. */
const float CVAR_TYPEFLAG_READONLY = 32; /* cvar may not be changed by qc. */
const float RESTYPE_MODEL = 0; /* RESTYPE_* constants are used as arguments with the resourcestatus builtin. */ const float RESTYPE_MODEL = 0; /* RESTYPE_* constants are used as arguments with the resourcestatus builtin. */
const float RESTYPE_SOUND = 1; /* precache_sound */ const float RESTYPE_SOUND = 1; /* precache_sound */
const float RESTYPE_PARTICLE = 2; /* particleeffectnum */ const float RESTYPE_PARTICLE = 2; /* particleeffectnum */
@ -1119,7 +1223,10 @@ const float EV_FIELD = 5;
const float EV_FUNCTION = 6; const float EV_FUNCTION = 6;
const float EV_POINTER = 7; const float EV_POINTER = 7;
const float EV_INTEGER = 8; const float EV_INTEGER = 8;
const float EV_VARIANT = 9; const float EV_UINT = 9;
const float EV_INT64 = 10;
const float EV_UINT64 = 11;
const float EV_DOUBLE = 12;
hashtable gamestate; /* Special hash table index for hash_add and hash_get. Entries in this table will persist over map changes (and doesn't need to be created/deleted). */ hashtable gamestate; /* Special hash table index for hash_add and hash_get. Entries in this table will persist over map changes (and doesn't need to be created/deleted). */
const float HASH_REPLACE = 256; /* Used with hash_add. Attempts to remove the old value instead of adding two values for a single key. */ const float HASH_REPLACE = 256; /* Used with hash_add. Attempts to remove the old value instead of adding two values for a single key. */
const float HASH_ADD = 512; /* Used with hash_add. The new entry will be inserted in addition to the existing entry. */ const float HASH_ADD = 512; /* Used with hash_add. The new entry will be inserted in addition to the existing entry. */
@ -1148,6 +1255,7 @@ const float STAT_USER = 32; /* Custom user stats start here (lower values are re
#endif #endif
#if defined(CSQC) || defined(MENU) #if defined(CSQC) || defined(MENU)
const float PRECACHE_PIC_FROMWAD = 1; /* Attempt to load it from the legacy gfx.wad file (usually its better to just use a gfx/ prefix instead). */ const float PRECACHE_PIC_FROMWAD = 1; /* Attempt to load it from the legacy gfx.wad file (usually its better to just use a gfx/ prefix instead). */
const float PRECACHE_PIC_NOCLAMP = 4; /* Texture coords for the pic will not be clamped nor padded nor atlased. */
const float PRECACHE_PIC_DOWNLOAD = 256; /* If no image could be loaded then attempt to download one from the server. This flag can cause the function to block until completion. (Slow!) */ const float PRECACHE_PIC_DOWNLOAD = 256; /* If no image could be loaded then attempt to download one from the server. This flag can cause the function to block until completion. (Slow!) */
const float PRECACHE_PIC_TEST = 512; /* The precache will block until the image is fully loaded, returning a null string on failure. (Slow!) */ const float PRECACHE_PIC_TEST = 512; /* The precache will block until the image is fully loaded, returning a null string on failure. (Slow!) */
const float VF_MIN = 1; /* The top-left of the 3d viewport in screenspace. The VF_ values are used via the setviewprop/getviewprop builtins. */ const float VF_MIN = 1; /* The top-left of the 3d viewport in screenspace. The VF_ values are used via the setviewprop/getviewprop builtins. */
@ -1218,6 +1326,12 @@ const float VF_SKYROOM_CAMERA = 222; /* Controls the camera position of the skyr
#endif #endif
#if defined(CSQC) || defined(MENU) #if defined(CSQC) || defined(MENU)
const float VF_PROJECTIONOFFSET = 224; /* vec2 horizontal+vertical offset for the projection matrix, for weird off-centre rendering. */ const float VF_PROJECTIONOFFSET = 224; /* vec2 horizontal+vertical offset for the projection matrix, for weird off-centre rendering. */
const float DRAWFLAG_NORMAL = 0; /* Args for drawpic/drawfill/beginpolygon. Not to be confused with the hexen2-compatibility feature. */
const float DRAWFLAG_ADD = 1; /* Forces additive blending, overriding any shader settings. */
const float DRAWFLAG_MODULATE = 2; /* Forces alpha blending, overriding any shader settings. */
const float DRAWFLAG_2D = 4; /* For use with beginpolygon. The polygon will be drawn to the 2d screen, instead of being added to the 3d scene. */
const float DRAWFLAG_TWOSIDED = 1024; /* For use with beginpolygon. The polygon will be two-sided without any backface culling. */
const float DRAWFLAG_LINES = 2048; /* For use with beginpolygon. The surface verticies should be interpreted as a line loop, instead of a triangle fan. */
const float IMGFMT_R8G8B8A8 = 1; /* Typical 32bit rgba pixel format. */ const float IMGFMT_R8G8B8A8 = 1; /* Typical 32bit rgba pixel format. */
const float IMGFMT_R16G16B16A16F = 2; /* Half-Float pixel format. Requires gl3 support. */ const float IMGFMT_R16G16B16A16F = 2; /* Half-Float pixel format. Requires gl3 support. */
const float IMGFMT_R32G32B32A32F = 3; /* Regular Float pixel format. Requires gl3 support. */ const float IMGFMT_R32G32B32A32F = 3; /* Regular Float pixel format. Requires gl3 support. */
@ -1260,7 +1374,7 @@ const float GGDI_DESCRIPTION = 1; /* The human-readable title of the mod. Empty
const float GGDI_OVERRIDES = 2; /* A list of settings overrides. */ const float GGDI_OVERRIDES = 2; /* A list of settings overrides. */
const float GGDI_LOADCOMMAND = 3; /* The console command needed to actually load the mod. */ const float GGDI_LOADCOMMAND = 3; /* The console command needed to actually load the mod. */
const float GGDI_ICON = 4; /* The mod's Icon path, ready for drawpic. */ const float GGDI_ICON = 4; /* The mod's Icon path, ready for drawpic. */
const float GGDI_GAMEDIRLIST = 4; /* A semi-colon delimited list of gamedirs that the mod's content can be loaded through. */ const float GGDI_GAMEDIRLIST = 5; /* A semi-colon delimited list of gamedirs that the mod's content can be loaded through. */
#endif #endif
#ifdef SSQC #ifdef SSQC
const float CLIENTTYPE_DISCONNECTED = 0; /* Return value from clienttype() builtin. This entity is a player slot that is currently empty. */ const float CLIENTTYPE_DISCONNECTED = 0; /* Return value from clienttype() builtin. This entity is a player slot that is currently empty. */
@ -1382,7 +1496,7 @@ float() random = #12;
void(string,...) localcmd = #13; void(string,...) localcmd = #13;
float(string name) cvar = #14; float(string name) cvar = #14;
void(string name, string value) cvar_set = #15; void(string name, string value) cvar_set = #15;
void(string text) dprint = #16; void(string text, ...) dprint = #16;
string(float) ftos = #17; string(float) ftos = #17;
float(float) fabs = #18; float(float) fabs = #18;
string(vector) vtos = #19; string(vector) vtos = #19;
@ -1610,11 +1724,11 @@ string(string s) precache_model = #20; /*
#endif #endif
#ifdef SSQC #ifdef SSQC
void(entity client, string s) stuffcmd = #21; /* void(entity client, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7) stuffcmd = #21; /*
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. 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.
This builtin is generally considered evil. */ This builtin is generally considered evil. */
void(entity client, float flags, string s) stuffcmdflags = #0:stuffcmdflags; /* Part of FTE_QC_STUFFCMDFLAGS void(entity client, float flags, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6) stuffcmdflags = #0:stuffcmdflags; /* Part of FTE_QC_STUFFCMDFLAGS
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. 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.
This (just as evil) variant allows specifying some flags too. See the STUFFCMD_* constants. */ This (just as evil) variant allows specifying some flags too. See the STUFFCMD_* constants. */
@ -2041,7 +2155,7 @@ string(float ccase, float redalpha, float redchars, string str, ...) strconv = #
string(float pad, string str1, ...) strpad = #225; /* Part of FTE_STRINGS string(float pad, string str1, ...) strpad = #225; /* Part of FTE_STRINGS
Pads the string with spaces, to ensure its a specific length (so long as a fixed-width font is used, anyway). If pad is negative, the spaces are added on the left. If positive the padding is on the right. */ Pads the string with spaces, to ensure its a specific length (so long as a fixed-width font is used, anyway). If pad is negative, the spaces are added on the left. If positive the padding is on the right. */
string(infostring old, string key, string value) infoadd = #226; /* Part of FTE_STRINGS infostring(infostring old, string key, string value) infoadd = #226; /* Part of FTE_STRINGS
Returns a new tempstring infostring with the named value changed (or added if it was previously unspecified). Key and value may not contain the \ character. */ Returns a new tempstring infostring with the named value changed (or added if it was previously unspecified). Key and value may not contain the \ character. */
string(infostring info, string key) infoget = #227; /* Part of FTE_STRINGS string(infostring info, string key) infoget = #227; /* Part of FTE_STRINGS
@ -2157,8 +2271,8 @@ string(int) htos = #262; /* Part of FTE_QC_INTCONV
int(float) ftoi = #0:ftoi; /* Part of FTE_QC_INTCONV int(float) ftoi = #0:ftoi; /* Part of FTE_QC_INTCONV
Converts the given float into a true integer without depending on extended qcvm instructions. */ Converts the given float into a true integer without depending on extended qcvm instructions. */
float(int) itof = #0:itof; /* Part of FTE_QC_INTCONV float(int, optional float shift, float mask=24) itof = #0:itof; /* Part of FTE_QC_INTCONV
Converts the given true integer into a float without depending on extended qcvm instructions. */ 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. */
#if defined(CSQC) || defined(SSQC) #if defined(CSQC) || defined(SSQC)
float(float modlindex, optional float useabstransforms) skel_create = #263; /* Part of FTE_CSQC_SKELETONOBJECTS float(float modlindex, optional float useabstransforms) skel_create = #263; /* Part of FTE_CSQC_SKELETONOBJECTS
@ -2280,6 +2394,32 @@ int(int faceid, brushface_t *in_faces, int numfaces, vector *points, int maxpoin
int(float modelid, vector *planes, float *dists, int numplanes, int *out_brushes, int *out_faces, int maxresults) brush_findinvolume = #0:brush_findinvolume; /* Part of FTE_RAW_MAP int(float modelid, vector *planes, float *dists, int numplanes, int *out_brushes, int *out_faces, int maxresults) brush_findinvolume = #0:brush_findinvolume; /* Part of FTE_RAW_MAP
Allows you to easily obtain a list of brushes+faces within the given bounding region. If out_faces is not null, the same brush might be listed twice. */ Allows you to easily obtain a list of brushes+faces within the given bounding region. If out_faces is not null, the same brush might be listed twice. */
typedef struct
{
string shadername;
int contents;
int cpwidth;
int cpheight;
int tesswidth;
int tessheight;
vector texinfo;/*scalex,y,rot*/
} patchinfo_t;
typedef struct
{
vector xyz;
vector rgb; float a;
float s, t;
} patchvert_t;
#define patch_delete(modelidx,patchidx) brush_delete(modelidx,patchidx)
int(float modelidx, int patchid, patchvert_t *out_controlverts, int maxcp, patchinfo_t *out_info) patch_getcp = #0:patch_getcp; /*
Queries a patch's information. You must pre-allocate the face array for the builtin to write to. Return value is the total number of control verts that were retrieved, 0 on error. */
int(float modelidx, int patchid, patchvert_t *out_verts, int maxverts, __out patchinfo_t out_info) patch_getmesh = #0:patch_getmesh; /*
Queries a patch's information. You must pre-allocate the face array for the builtin to write to. Return value is the total number of control verts that were retrieved, 0 on error. */
int(float modelidx, int oldpatchid, patchvert_t *in_controlverts, patchinfo_t in_info) patch_create = #0:patch_create; /*
Inserts a new patch into the model. Return value is the new patch's id. */
typedef struct typedef struct
{ {
vector dest; vector dest;
@ -2296,8 +2436,14 @@ void(optional entity ent, optional vector neworigin) touchtriggers = #279; /*
void(float buf, float fl) WriteFloat = #280; /* void(float buf, float fl) WriteFloat = #280; /*
Writes a full 32bit float without any data conversions at all, for full precision. */ Writes a full 32bit float without any data conversions at all, for full precision. */
void(float buf, __double dbl) WriteDouble = #0:WriteDouble; /*
Writes a full 64bit double-precision float without any data conversions at all, for excessive precision. */
void(float buf, int fl) WriteInt = #0:WriteInt; /* void(float buf, int fl) WriteInt = #0:WriteInt; /*
Equivelent to WriteLong, but doesn't truncate to a float first before converting back to an int. */ Writes all 4 bytes of a 32bit integer without truncating to a float first before converting back to an int (unlike WriteLong does, but otherwise equivelent). */
void(float buf, __int64 fl) WriteInt64 = #0:WriteInt64; /*
Writes all 8 bytes of a 64bit integer. */
#endif #endif
#if defined(CSQC) || defined(SSQC) #if defined(CSQC) || defined(SSQC)
@ -2531,18 +2677,18 @@ void(vector pivot, vector mins, vector maxs, string pic, vector txmin, vector tx
#ifdef CSQC #ifdef CSQC
#define getstati_punf(stnum) (float)(__variant)getstati(stnum) #define getstati_punf(stnum) (float)(__variant)getstati(stnum)
int(float stnum) getstati = #330; /* int(float stnum) getstati = #330; /*
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. */ Retrieves the full precision of a stat registered as EV_INTEGER. */
#define getstatbits getstatf #define getstatbits getstatf
float(float stnum, optional float firstbit, optional float bitcount) getstatf = #331; /* float(float stnum, optional float firstbit, optional float bitcount) getstatf = #331; /*
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). */ 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). */
string(float stnum) getstats = #332; /* string(float stnum) getstats = #332; /*
Retrieves the value of the given EV_STRING stat, as a tempstring. Retrieves the value of the given EV_STRING stat, as a tempstring.
Older engines may use 4 consecutive integer stats, with a limit of 15 chars (yes, really. 15.), but FTE Quake uses a separate namespace for string stats and has a much higher length limit. */ Older engines may use 4 consecutive integer stats, with a limit of 15 chars (yes, really. 15.), but FTE Quake uses a separate namespace for string stats and has a much higher length limit. */
__variant(float playernum, float statnum, float stattype) getplayerstat = #0:getplayerstat; /* __variant(float playernum, float statnum, float stattype) getplayerstat = #0:getplayerstat; /*
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. */ 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. */
void(entity e, float mdlindex) setmodelindex = #333; /* void(entity e, float mdlindex) setmodelindex = #333; /*
Sets a model by precache index instead of by name. Otherwise identical to setmodel. */ Sets a model by precache index instead of by name. Otherwise identical to setmodel. */
@ -2773,9 +2919,15 @@ string() readstring = #366; /*
float() readfloat = #367; /* float() readfloat = #367; /*
Reads a float without any truncation nor conversions. Data MUST have originally been written with WriteFloat. */ Reads a float without any truncation nor conversions. Data MUST have originally been written with WriteFloat. */
__double() readdouble = #0:readdouble; /*
Reads a double-precision float without any truncation nor conversions. Data MUST have originally been written with WriteDouble. */
int() readint = #0:readint; /* int() readint = #0:readint; /*
Reads a 32bit int without any conversions to float, otherwise interchangable with readlong. */ Reads a 32bit int without any conversions to float, otherwise interchangable with readlong. */
__int64() readint64 = #0:readint64; /*
Reads a 64bit int. Paired with WriteInt64. */
float() readentitynum = #368; /* float() readentitynum = #368; /*
Reads the serverside index of an entity, paired with WriteEntity. There may be nothing else known about the entity yet, so the result typically needs to be saved as-is and re-looked up each frame. This can be done via getentity(NUM, GE_*) for non-csqc ents, or findentity(world,entnum,NUM) - both of which can fail due to latency. */ Reads the serverside index of an entity, paired with WriteEntity. There may be nothing else known about the entity yet, so the result typically needs to be saved as-is and re-looked up each frame. This can be done via getentity(NUM, GE_*) for non-csqc ents, or findentity(world,entnum,NUM) - both of which can fail due to latency. */
@ -2949,7 +3101,7 @@ void(strbuf bufhandle, float string_index, string str) bufstr_set = #447; /* Par
float(strbuf bufhandle, string str, float ordered) bufstr_add = #448; /* Part of DP_QC_STRINGBUFFERS*/ float(strbuf bufhandle, string str, float ordered) bufstr_add = #448; /* Part of DP_QC_STRINGBUFFERS*/
void(strbuf bufhandle, float string_index) bufstr_free = #449; /* Part of DP_QC_STRINGBUFFERS*/ void(strbuf bufhandle, float string_index) bufstr_free = #449; /* Part of DP_QC_STRINGBUFFERS*/
float(string name) iscachedpic = #451; float(string name) iscachedpic = #451;
string(string name, optional float trywad) precache_pic = #452; string(string name, optional float flags) precache_pic = #452;
float(vector position, float character, vector scale, vector rgb, float alpha, optional float flag) drawcharacter = #454; float(vector position, float character, vector scale, vector rgb, float alpha, optional float flag) drawcharacter = #454;
float(vector position, string text, vector scale, vector rgb, float alpha, optional float flag) drawrawstring = #455; float(vector position, string text, vector scale, vector rgb, float alpha, optional float flag) drawrawstring = #455;
float(vector position, string pic, vector size, vector rgb, float alpha, optional float flag) drawpic = #456; float(vector position, string pic, vector size, vector rgb, float alpha, optional float flag) drawpic = #456;
@ -3035,7 +3187,11 @@ string(string s) strdecolorize = #477; /* Part of DP_QC_STRINGCOLORFUNCTIONS
Flattens any markup/colours, removing them from the string. */ Flattens any markup/colours, removing them from the string. */
string(float uselocaltime, string format, ...) strftime = #478; /* Part of DP_QC_STRFTIME*/ string(float uselocaltime, string format, ...) strftime = #478; /* Part of DP_QC_STRFTIME*/
float(string s, string separator1, ...) tokenizebyseparator = #479; /* Part of DP_QC_TOKENIZEBYSEPARATOR*/ float(string s, string separator1, ...) tokenizebyseparator = #479; /* Part of DP_QC_TOKENIZEBYSEPARATOR
Splits up the string using only the specified delimiters/separators. Multiple delimiters can be given, they are each considered equivelent (though should start with the longest if you want to do weird subseparator stuff).
The resulting tokens can be queried via argv (and argv_start|end_index builtins, if you want to determine which of the separators was present between two tokens).
Note that while an input string containing JUST a separator will return 2, a string with no delimiter will return 1, while (in FTE) an empty string will ALWAYS return 0. */
string(string s) strtolower = #480; /* Part of DP_QC_STRING_CASE_FUNCTIONS*/ string(string s) strtolower = #480; /* Part of DP_QC_STRING_CASE_FUNCTIONS*/
string(string s) strtoupper = #481; /* Part of DP_QC_STRING_CASE_FUNCTIONS*/ string(string s) strtoupper = #481; /* Part of DP_QC_STRING_CASE_FUNCTIONS*/
#if defined(CSQC) || defined(SSQC) #if defined(CSQC) || defined(SSQC)
@ -3315,154 +3471,154 @@ float(string fname) fremove = #652; /*
Deletes the named file - path is relative to data/ subdir, like fopen's FILE_WRITE. Returns 0 on success. */ Deletes the named file - path is relative to data/ subdir, like fopen's FILE_WRITE. Returns 0 on success. */
float(string fname) fexists = #653; /* float(string fname) fexists = #653; /*
Use whichpack instead. Returns true if it exists inside the default writable path. */ Returns true if it exists inside the default writable path. Use whichpack for greater portability. */
float(string path) rmtree = #654; /* float(string path) rmtree = #654; /*
Dangerous, but sandboxed to data/ */ Dangerous, but sandboxed to data/ */
#if defined(CSQC) || defined(MENU) #if defined(CSQC) || defined(MENU)
#define K_TAB 9 const float K_TAB = 9;
#define K_ENTER 13 const float K_ENTER = 13;
#define K_ESCAPE 27 const float K_ESCAPE = 27;
#define K_SPACE 32 const float K_SPACE = 32;
#define K_BACKSPACE 127 const float K_BACKSPACE = 127;
#define K_UPARROW 128 const float K_UPARROW = 128;
#define K_DOWNARROW 129 const float K_DOWNARROW = 129;
#define K_LEFTARROW 130 const float K_LEFTARROW = 130;
#define K_RIGHTARROW 131 const float K_RIGHTARROW = 131;
#define K_LALT 132 const float K_LALT = 132;
#define K_RALT -245 const float K_RALT = -245;
#define K_LCTRL 133 const float K_LCTRL = 133;
#define K_RCTRL -246 const float K_RCTRL = -246;
#define K_LSHIFT 134 const float K_LSHIFT = 134;
#define K_RSHIFT -247 const float K_RSHIFT = -247;
#define K_F1 135 const float K_F1 = 135;
#define K_F2 136 const float K_F2 = 136;
#define K_F3 137 const float K_F3 = 137;
#define K_F4 138 const float K_F4 = 138;
#define K_F5 139 const float K_F5 = 139;
#define K_F6 140 const float K_F6 = 140;
#define K_F7 141 const float K_F7 = 141;
#define K_F8 142 const float K_F8 = 142;
#define K_F9 143 const float K_F9 = 143;
#define K_F10 144 const float K_F10 = 144;
#define K_F11 145 const float K_F11 = 145;
#define K_F12 146 const float K_F12 = 146;
#define K_INS 147 const float K_INS = 147;
#define K_DEL 148 const float K_DEL = 148;
#define K_PGDN 149 const float K_PGDN = 149;
#define K_PGUP 150 const float K_PGUP = 150;
#define K_HOME 151 const float K_HOME = 151;
#define K_END 152 const float K_END = 152;
#define K_KP_HOME 164 const float K_KP_HOME = 164;
#define K_KP_UPARROW 165 const float K_KP_UPARROW = 165;
#define K_KP_PGUP 166 const float K_KP_PGUP = 166;
#define K_KP_LEFTARROW 161 const float K_KP_LEFTARROW = 161;
#define K_KP_5 162 const float K_KP_5 = 162;
#define K_KP_RIGHTARROW 163 const float K_KP_RIGHTARROW = 163;
#define K_KP_END 158 const float K_KP_END = 158;
#define K_KP_DOWNARROW 159 const float K_KP_DOWNARROW = 159;
#define K_KP_PGDN 160 const float K_KP_PGDN = 160;
#define K_KP_ENTER 172 const float K_KP_ENTER = 172;
#define K_KP_INS 157 const float K_KP_INS = 157;
#define K_KP_DEL 167 const float K_KP_DEL = 167;
#define K_KP_SLASH 168 const float K_KP_SLASH = 168;
#define K_KP_MINUS 170 const float K_KP_MINUS = 170;
#define K_KP_PLUS 171 const float K_KP_PLUS = 171;
#define K_KP_NUMLOCK 154 const float K_KP_NUMLOCK = 154;
#define K_KP_STAR 169 const float K_KP_STAR = 169;
#define K_KP_EQUALS 173 const float K_KP_EQUALS = 173;
#define K_MOUSE1 512 const float K_MOUSE1 = 512;
#define K_MOUSE2 513 const float K_MOUSE2 = 513;
#define K_MOUSE3 514 const float K_MOUSE3 = 514;
#define K_MOUSE4 517 const float K_MOUSE4 = 517;
#define K_MOUSE5 518 const float K_MOUSE5 = 518;
#define K_MOUSE6 519 const float K_MOUSE6 = 519;
#define K_MOUSE7 520 const float K_MOUSE7 = 520;
#define K_MOUSE8 521 const float K_MOUSE8 = 521;
#define K_MOUSE9 522 const float K_MOUSE9 = 522;
#define K_MOUSE10 523 const float K_MOUSE10 = 523;
#define K_MWHEELUP 515 const float K_MWHEELUP = 515;
#define K_MWHEELDOWN 516 const float K_MWHEELDOWN = 516;
#define K_LWIN -239 const float K_LWIN = -239;
#define K_RWIN -240 const float K_RWIN = -240;
#define K_APP -241 const float K_APP = -241;
#define K_SEARCH -242 const float K_SEARCH = -242;
#define K_POWER -130 const float K_POWER = -130;
#define K_VOLUP -243 const float K_VOLUP = -243;
#define K_VOLDOWN -244 const float K_VOLDOWN = -244;
#define K_JOY1 768 const float K_JOY1 = 768;
#define K_JOY2 769 const float K_JOY2 = 769;
#define K_JOY3 770 const float K_JOY3 = 770;
#define K_JOY4 771 const float K_JOY4 = 771;
#define K_AUX1 784 const float K_AUX1 = 784;
#define K_AUX2 785 const float K_AUX2 = 785;
#define K_AUX3 786 const float K_AUX3 = 786;
#define K_AUX4 787 const float K_AUX4 = 787;
#define K_AUX5 788 const float K_AUX5 = 788;
#define K_AUX6 789 const float K_AUX6 = 789;
#define K_AUX7 790 const float K_AUX7 = 790;
#define K_AUX8 791 const float K_AUX8 = 791;
#define K_AUX9 792 const float K_AUX9 = 792;
#define K_AUX10 793 const float K_AUX10 = 793;
#define K_AUX11 794 const float K_AUX11 = 794;
#define K_AUX12 795 const float K_AUX12 = 795;
#define K_AUX13 796 const float K_AUX13 = 796;
#define K_AUX14 797 const float K_AUX14 = 797;
#define K_AUX15 798 const float K_AUX15 = 798;
#define K_AUX16 799 const float K_AUX16 = 799;
#define K_AUX17 800 const float K_AUX17 = 800;
#define K_AUX18 801 const float K_AUX18 = 801;
#define K_AUX19 802 const float K_AUX19 = 802;
#define K_AUX20 803 const float K_AUX20 = 803;
#define K_AUX21 804 const float K_AUX21 = 804;
#define K_AUX22 805 const float K_AUX22 = 805;
#define K_AUX23 806 const float K_AUX23 = 806;
#define K_AUX24 807 const float K_AUX24 = 807;
#define K_AUX25 808 const float K_AUX25 = 808;
#define K_AUX26 809 const float K_AUX26 = 809;
#define K_AUX27 810 const float K_AUX27 = 810;
#define K_AUX28 811 const float K_AUX28 = 811;
#define K_AUX29 812 const float K_AUX29 = 812;
#define K_AUX30 813 const float K_AUX30 = 813;
#define K_AUX31 814 const float K_AUX31 = 814;
#define K_AUX32 815 const float K_AUX32 = 815;
#define K_PAUSE 153 const float K_PAUSE = 153;
#define K_PRINTSCREEN 174 const float K_PRINTSCREEN = 174;
#define K_CAPSLOCK 155 const float K_CAPSLOCK = 155;
#define K_SCROLLLOCK 156 const float K_SCROLLLOCK = 156;
#define K_SEMICOLON 59 const float K_SEMICOLON = 59;
#define K_PLUS 43 const float K_PLUS = 43;
#define K_MINUS 45 const float K_MINUS = 45;
#define K_TILDE 126 const float K_TILDE = 126;
#define K_BACKQUOTE 96 const float K_BACKQUOTE = 96;
#define K_BACKSLASH 92 const float K_BACKSLASH = 92;
#define K_GP_A 826 const float K_GP_A = 826;
#define K_GP_B 827 const float K_GP_B = 827;
#define K_GP_X 828 const float K_GP_X = 828;
#define K_GP_Y 829 const float K_GP_Y = 829;
#define K_GP_LSHOULDER 824 const float K_GP_LSHOULDER = 824;
#define K_GP_RSHOULDER 825 const float K_GP_RSHOULDER = 825;
#define K_GP_LTRIGGER 830 const float K_GP_LTRIGGER = 830;
#define K_GP_RTRIGGER 831 const float K_GP_RTRIGGER = 831;
#define K_GP_BACK 821 const float K_GP_BACK = 821;
#define K_GP_START 820 const float K_GP_START = 820;
#define K_GP_LTHUMB 822 const float K_GP_LTHUMB = 822;
#define K_GP_RTHUMB 823 const float K_GP_RTHUMB = 823;
#define K_GP_DPAD_UP 816 const float K_GP_DPAD_UP = 816;
#define K_GP_DPAD_DOWN 817 const float K_GP_DPAD_DOWN = 817;
#define K_GP_DPAD_LEFT 818 const float K_GP_DPAD_LEFT = 818;
#define K_GP_DPAD_RIGHT 819 const float K_GP_DPAD_RIGHT = 819;
#define K_GP_GUIDE -202 const float K_GP_GUIDE = -202;
#define K_GP_UNKNOWN -255 const float K_GP_UNKNOWN = -255;
#define K_GP_LTHUMB_UP 832 const float K_GP_LTHUMB_UP = 832;
#define K_GP_LTHUMB_DOWN 833 const float K_GP_LTHUMB_DOWN = 833;
#define K_GP_LTHUMB_LEFT 834 const float K_GP_LTHUMB_LEFT = 834;
#define K_GP_LTHUMB_RIGHT 835 const float K_GP_LTHUMB_RIGHT = 835;
#define K_GP_RTHUMB_UP 836 const float K_GP_RTHUMB_UP = 836;
#define K_GP_RTHUMB_DOWN 837 const float K_GP_RTHUMB_DOWN = 837;
#define K_GP_RTHUMB_LEFT 838 const float K_GP_RTHUMB_LEFT = 838;
#define K_GP_RTHUMB_RIGHT 839 const float K_GP_RTHUMB_RIGHT = 839;
#endif #endif
#ifdef _ACCESSORS #ifdef _ACCESSORS
accessor strbuf : float accessor strbuf : float

View File

@ -1,13 +1,10 @@
#pragma progs_dat "../menu.dat" #pragma progs_dat "../menu.dat"
//#pragma target fte
#pragma target fte
#define MENU //select the module #define MENU //select the module
#include "fteextensions.qc" //also sets up system defs
#includelist #includelist
fteextensions.qc //also sets up system defs
menusys/mitems.qc //root item type menusys/mitems.qc //root item type
menusys/mitems_common.qc //basic types menusys/mitems_common.qc //basic types
menusys/mitem_desktop.qc //other sort of root item menusys/mitem_desktop.qc //other sort of root item

View File

@ -53,6 +53,7 @@ helper functions to avoid blowing up in older clients.
#endif #endif
float(string cmd, float assumption) checkcommand2 = float(string cmd, float assumption) checkcommand2 =
{ {
__using checkcommand;
if (!checkextension("FTE_QC_CHECKCOMMAND")) if (!checkextension("FTE_QC_CHECKCOMMAND"))
return assumption; return assumption;
return checkcommand(cmd); return checkcommand(cmd);
@ -63,6 +64,7 @@ float(__variant cmd, float assumption) checkbuiltin2 =
return assumption; return assumption;
return checkbuiltin(cmd); return checkbuiltin(cmd);
}; };
#define checkbuiltin2(c,a) ((a)?checkbuiltin2(c,a):checkbuiltin(c))
#ifdef CSQC #ifdef CSQC
float() clientstate = float() clientstate =

View File

@ -31,6 +31,8 @@ void(mitem_desktop desktop) M_Menu_Mods =
float mod; float mod;
for (mod = 0; ; mod++) for (mod = 0; ; mod++)
{ {
__using GGDI_DESCRIPTION, GGDI_LOADCOMMAND, GGDI_ICON;
string gamedir = getgamedirinfo(mod, GGDI_GAMEDIR); string gamedir = getgamedirinfo(mod, GGDI_GAMEDIR);
if not(gamedir) if not(gamedir)
break; break;

View File

@ -6,7 +6,17 @@ static string newgameinfo;
nonstatic void(mitem_desktop desktop) M_Dir = nonstatic void(mitem_desktop desktop) M_Dir =
{ //implementing this primarily so its available in QSS. :P { //implementing this primarily so its available in QSS. :P
string path = argv(1); string path = argv(1);
searchhandle h = search_begin(path, SB_FULLPACKAGEPATH, 0); string pack = argv(2);
searchhandle h;
if (path == "")
{
print("m_dir <FILEPATH> [PACKAGE]\n");
return;
}
if (pack != "")
h = search_begin(path, SB_FULLPACKAGEPATH|SB_FORCESEARCH|16, 0, argv(2));
else
h = search_begin(path, SB_FULLPACKAGEPATH|16|32, 0);
print(sprintf("Directory listing of %S (%g files)\n", path, search_getsize(h))); print(sprintf("Directory listing of %S (%g files)\n", path, search_getsize(h)));
for (float i = 0; i < search_getsize(h); i++) for (float i = 0; i < search_getsize(h); i++)
{ {
@ -32,15 +42,12 @@ nonstatic void(mitem_desktop desktop) M_Dir =
#define FOURCC(a,b,c,d) ((int)(a)<<0i)|((int)(b)<<8i)|((int)(c)<<16i)|((int)(d)<<24i) #define FOURCC(a,b,c,d) ((int)(a)<<0i)|((int)(b)<<8i)|((int)(c)<<16i)|((int)(d)<<24i)
static string(string name) getmapdesc = static string(string name) getmapdesc =
{ {
filestream f; if (checkbuiltin(fread) && checkbuiltin(fseek) && checkbuiltin(memalloc) && checkbuiltin(memfree) && checkbuiltin(memgetval) && checkbuiltin(itof) && checkbuiltin(ftoi))
if (!checkbuiltin(fread) || !checkbuiltin(fseek) || !checkbuiltin(memalloc) || !checkbuiltin(memgetval))
return ""; //we can't do that in this engine... don't show anything, because its pointless showing the same thing twice.
else
{ //we can do it, so do it. { //we can do it, so do it.
f = fopen(name, FILE_READ); filestream f = fopen(name, FILE_READ);
if (f < 0) if (f < 0)
print(sprintf("Unable to read %s\n", name)); print(sprintf("Unable to read %s\n", name));
}
name = substring(name, 5, -5); name = substring(name, 5, -5);
if (f < 0) if (f < 0)
return name; return name;
@ -94,6 +101,8 @@ static string(string name) getmapdesc =
memfree(header); memfree(header);
fclose(f); fclose(f);
return name; return name;
}
return ""; //we can't do that in this engine... don't show anything, because its pointless showing the same thing twice.
}; };
static string(string name) packagetogamedir = static string(string name) packagetogamedir =

View File

@ -2,7 +2,7 @@ class mitem_playerpreview : mitem_spinnymodel
{ {
virtual void(vector pos) item_draw = virtual void(vector pos) item_draw =
{ {
if (checkbuiltin2(setcustomskin, FALSE)) if (checkbuiltin(setcustomskin))
{ {
//if you wanted to get more advanced, you could use q3 skins here. //if you wanted to get more advanced, you could use q3 skins here.
if (cvar("noskins")==1) if (cvar("noskins")==1)

View File

@ -7,7 +7,7 @@ no background tint, so the game is still visible so you can preview it.
nonstatic void(mitem_desktop desktop) M_Configs = nonstatic void(mitem_desktop desktop) M_Configs =
{ {
local float i; float i;
mitem_exmenu m; mitem_exmenu m;
m = spawn(mitem_exmenu, item_text:_("Game Presets / Configs"), item_flags:IF_SELECTABLE, item_command:"m_options"); m = spawn(mitem_exmenu, item_text:_("Game Presets / Configs"), item_flags:IF_SELECTABLE, item_command:"m_options");
desktop.add(m, RS_X_MIN_PARENT_MIN|RS_Y_MIN_PARENT_MIN | RS_X_MAX_PARENT_MAX|RS_Y_MAX_PARENT_MAX, '0 0', '0 0'); desktop.add(m, RS_X_MIN_PARENT_MIN|RS_Y_MIN_PARENT_MIN | RS_X_MAX_PARENT_MAX|RS_Y_MAX_PARENT_MAX, '0 0', '0 0');
@ -28,8 +28,11 @@ nonstatic void(mitem_desktop desktop) M_Configs =
float fs, y=0; float fs, y=0;
float c = 0;
fs = search_begin("configs/game_*.cfg", TRUE, TRUE); fs = search_begin("configs/game_*.cfg", TRUE, TRUE);
float c = search_getsize(fs); if (fs >= 0)
{
c = search_getsize(fs);
for (i = 0; i < c; i++) for (i = 0; i < c; i++)
{ {
string fname = search_getfilename(fs, i); string fname = search_getfilename(fs, i);
@ -40,6 +43,7 @@ nonstatic void(mitem_desktop desktop) M_Configs =
fr.add(spawn(mitem_text, item_text:dname, item_command:iname, item_scale:16, item_flags:IF_CENTERALIGN), RS_X_MIN_PARENT_MIN|RS_Y_MIN_PARENT_MIN | RS_X_MAX_PARENT_MAX|RS_Y_MAX_OWN_MIN, [0, y+=16], '100 16'); fr.add(spawn(mitem_text, item_text:dname, item_command:iname, item_scale:16, item_flags:IF_CENTERALIGN), RS_X_MIN_PARENT_MIN|RS_Y_MIN_PARENT_MIN | RS_X_MAX_PARENT_MAX|RS_Y_MAX_OWN_MIN, [0, y+=16], '100 16');
} }
search_end(fs); search_end(fs);
}
if (c <= 0) if (c <= 0)
fr.add(spawn(mitem_text, item_text:"No configs found", item_scale:16, item_flags:IF_CENTERALIGN), RS_X_MIN_PARENT_MIN|RS_Y_MIN_PARENT_MIN | RS_X_MAX_PARENT_MAX|RS_Y_MAX_OWN_MIN, [0, y], '100 16'); fr.add(spawn(mitem_text, item_text:"No configs found", item_scale:16, item_flags:IF_CENTERALIGN), RS_X_MIN_PARENT_MIN|RS_Y_MIN_PARENT_MIN | RS_X_MAX_PARENT_MAX|RS_Y_MAX_OWN_MIN, [0, y], '100 16');

View File

@ -6,6 +6,7 @@ nonstatic void(mitem_desktop desktop) M_Quit =
{ {
local float pos; local float pos;
mitem_exmenu m; mitem_exmenu m;
float unsaved = FALSE;
m = spawn(mitem_exmenu, item_text:_("Options"), item_flags:IF_SELECTABLE, item_command:"m_main"); m = spawn(mitem_exmenu, item_text:_("Options"), item_flags:IF_SELECTABLE, item_command:"m_main");
desktop.add(m, RS_X_MIN_PARENT_MIN|RS_Y_MIN_PARENT_MIN | RS_X_MAX_PARENT_MAX|RS_Y_MAX_PARENT_MAX, '0 0', '0 0'); desktop.add(m, RS_X_MIN_PARENT_MIN|RS_Y_MIN_PARENT_MIN | RS_X_MAX_PARENT_MAX|RS_Y_MAX_PARENT_MAX, '0 0', '0 0');
desktop.item_focuschange(m, IF_KFOCUSED); desktop.item_focuschange(m, IF_KFOCUSED);
@ -18,7 +19,9 @@ nonstatic void(mitem_desktop desktop) M_Quit =
// mitem_pic banner = spawn(mitem_pic, item_text:"gfx/p_option.lmp", item_size_y:24, item_flags:IF_CENTERALIGN); // mitem_pic banner = spawn(mitem_pic, item_text:"gfx/p_option.lmp", item_size_y:24, item_flags:IF_CENTERALIGN);
// m.add(banner, RS_X_MIN_PARENT_MID|RS_Y_MIN_PARENT_MID | RS_X_MAX_PARENT_MID|RS_Y_MAX_PARENT_MID, [(-160-banner.item_size_x)*0.5, pos-32], [(-160+banner.item_size_x)*0.5, pos-8]); // m.add(banner, RS_X_MIN_PARENT_MID|RS_Y_MIN_PARENT_MID | RS_X_MAX_PARENT_MID|RS_Y_MAX_PARENT_MID, [(-160-banner.item_size_x)*0.5, pos-32], [(-160+banner.item_size_x)*0.5, pos-8]);
if (cvars_haveunsaved()) if (checkbuiltin(cvars_haveunsaved))
unsaved = cvars_haveunsaved(); //engines that don't have this are assumed to always save regardless. Which makes prompting for it irrelevant. The all-saved text ignores saving entirely so it still makes sense.
if (unsaved)
{ {
m.add(spawn(mitem_text, item_text:"Save configuration?", item_scale:16, item_flags:IF_CENTERALIGN), RS_X_MIN_PARENT_MID|RS_Y_MIN_PARENT_MID | RS_X_MAX_PARENT_MID|RS_Y_MAX_PARENT_MID, [-160, pos-(8+16)], [0, pos-8]); pos += 16; m.add(spawn(mitem_text, item_text:"Save configuration?", item_scale:16, item_flags:IF_CENTERALIGN), RS_X_MIN_PARENT_MID|RS_Y_MIN_PARENT_MID | RS_X_MAX_PARENT_MID|RS_Y_MAX_PARENT_MID, [-160, pos-(8+16)], [0, pos-8]); pos += 16;

View File

@ -27,7 +27,7 @@ var float autocvar_sb_showname = 1;
#define COLUMN_FRAGLIMIT COLUMN(4*8, fraglimit, "FL", ui.drawstring(pos, sprintf("%-3g", gethostcachenumber(field_fraglimit, sv)), '8 8', col, 1, 0);) #define COLUMN_FRAGLIMIT COLUMN(4*8, fraglimit, "FL", ui.drawstring(pos, sprintf("%-3g", gethostcachenumber(field_fraglimit, sv)), '8 8', col, 1, 0);)
#define COLUMN_TIMELIMIT COLUMN(4*8, timelimit, "TL", ui.drawstring(pos, sprintf("%-3g", gethostcachenumber(field_timelimit, sv)), '8 8', col, 1, 0);) #define COLUMN_TIMELIMIT COLUMN(4*8, timelimit, "TL", ui.drawstring(pos, sprintf("%-3g", gethostcachenumber(field_timelimit, sv)), '8 8', col, 1, 0);)
#define COLUMN_GAMEDIR COLUMN(8*8, gamedir, "Gamedir", ui.drawstring(pos, sprintf("%-.8s", gethostcachestring(field_gamedir, sv)), '8 8', col, 1, 0);) #define COLUMN_GAMEDIR COLUMN(8*8, gamedir, "Gamedir", ui.drawstring(pos, sprintf("%-.8s", gethostcachestring(field_gamedir, sv)), '8 8', col, 1, 0);)
#define COLUMN_ADDRESS COLUMN(16*8, address, "Address", ui.drawstring(pos, sprintf("%-.16s", gethostcachestring(field_address, sv)), '8 8', col, 1, 0);) #define COLUMN_ADDRESS COLUMN(21*8, address, "Address", ui.drawstring(pos, sprintf("%-.21s", gethostcachestring(field_address, sv)), '8 8', col, 1, 0);)
#define COLUMN_MAP COLUMN(8*8, map, "Map", ui.drawstring(pos, sprintf("%-.8s", gethostcachestring(field_map, sv)), '8 8', col, 1, 0);) #define COLUMN_MAP COLUMN(8*8, map, "Map", ui.drawstring(pos, sprintf("%-.8s", gethostcachestring(field_map, sv)), '8 8', col, 1, 0);)
#define COLUMN_HOSTNAME COLUMN(64*8, name, "Name", ui.drawstring(pos, sprintf("%s", gethostcachestring(field_name, sv)), '8 8', col, 1, 0);) #define COLUMN_HOSTNAME COLUMN(64*8, name, "Name", ui.drawstring(pos, sprintf("%s", gethostcachestring(field_name, sv)), '8 8', col, 1, 0);)
//FIXME: add a little * icon before the hostname for favourites or something //FIXME: add a little * icon before the hostname for favourites or something
@ -149,6 +149,20 @@ class mitem_servers : mitem
ui.setcliparea(omin_x, omin_y, omax_x - omin_x, omax_y - omin_y); ui.setcliparea(omin_x, omin_y, omax_x - omin_x, omax_y - omin_y);
}; };
static string() getgamedircmd =
{ //sadly the vanilla NQ network protocol gave clients no idea which gamedir the server is actually using.
//many extended protocols still lack that info, so be sure to try to switch according to the server browser's gamedir info, because its more robust than not even trying.
float field_gamedir = gethostcacheindexforkey("gamedir");
if (field_gamedir < 0)
field_gamedir = gethostcacheindexforkey("mod");
if (field_gamedir < 0)
return ""; //erk. dodgy engine?
string gd = gethostcachestring(field_gamedir, server_selected);
if (strstrofs(gd, "\"")>=0 || strstrofs(gd, "\n")>=0 || strstrofs(gd, "\r")>=0)
return ""; //no, just no. trust the engine to reject bad paths, we're just preventing cbuf corruption here (DP doesn't support "%S").
return sprintf("gamedir \"%s\";", gd);
};
virtual float(vector pos, float scan, float char, float down) item_keypress = virtual float(vector pos, float scan, float char, float down) item_keypress =
{ {
float displaysize; float displaysize;
@ -195,7 +209,7 @@ class mitem_servers : mitem
//connect on double clicks. because we can. //connect on double clicks. because we can.
addr = gethostcachestring(gethostcacheindexforkey("cname"), server_selected); addr = gethostcachestring(gethostcacheindexforkey("cname"), server_selected);
if (addr) if (addr)
localcmd(sprintf("m_pop;connect \"%s\"\n", addr)); localcmd(sprintf("m_pop;%sconnect \"%s\"\n", getgamedircmd(), addr));
} }
else else
server_selected = news; server_selected = news;
@ -207,19 +221,19 @@ class mitem_servers : mitem
{ //connect normally { //connect normally
addr = gethostcachestring(gethostcacheindexforkey("cname"), server_selected); addr = gethostcachestring(gethostcacheindexforkey("cname"), server_selected);
if (addr) if (addr)
localcmd(sprintf("m_pop;connect \"%s\"\n", addr)); localcmd(sprintf("m_pop;%sconnect \"%s\"\n", getgamedircmd(), addr));
} }
else if (scan == 's') else if (scan == 's')
{ //s = join as a spectator { //s = join as a spectator
addr = gethostcachestring(gethostcacheindexforkey("cname"), server_selected); addr = gethostcachestring(gethostcacheindexforkey("cname"), server_selected);
if (addr) if (addr)
localcmd(sprintf("m_pop;observe \"%s\"\n", addr)); localcmd(sprintf("m_pop;%sobserve \"%s\"\n", getgamedircmd(), addr));
} }
else if (scan == 'j') else if (scan == 'j')
{ //s = join as a spectator { //s = join as a spectator
addr = gethostcachestring(gethostcacheindexforkey("cname"), server_selected); addr = gethostcachestring(gethostcacheindexforkey("cname"), server_selected);
if (addr) if (addr)
localcmd(sprintf("m_pop;join \"%s\"\n", addr)); localcmd(sprintf("m_pop;%sjoin \"%s\"\n", getgamedircmd(), addr));
} }
else if (scan == K_UPARROW || scan == K_MWHEELUP) else if (scan == K_UPARROW || scan == K_MWHEELUP)
{ {
@ -303,7 +317,10 @@ class mitem_servers_players : mitem
return; return;
for (player = 0, y = 0; player < 256; player++) for (player = 0, y = 0; player < 256; player++)
{ {
string playerinfo = gethostcachestring(gethostcacheindexforkey(sprintf("player%g", player)), listing.server_selected); float key = gethostcacheindexforkey(sprintf("player%g", player));
if (key < 0)
break; //probably DP. this isn't going to work for us.
string playerinfo = gethostcachestring(key, listing.server_selected);
if (!playerinfo) if (!playerinfo)
break; break;
tokenize(playerinfo); tokenize(playerinfo);
@ -335,6 +352,9 @@ class mitem_servers_players : mitem
pos_x += 16*6; pos_x += 16*6;
y = 0; y = 0;
} }
if (checkbuiltin(drawtextfield))
{
// drawtextfield(opos, item_size, 3, gethostcachestring(gethostcacheindexforkey("serverinfo"), listing.server_selected)); // drawtextfield(opos, item_size, 3, gethostcachestring(gethostcacheindexforkey("serverinfo"), listing.server_selected));
m = tokenizebyseparator(gethostcachestring(gethostcacheindexforkey("serverinfo"), listing.server_selected), "\\"); m = tokenizebyseparator(gethostcachestring(gethostcacheindexforkey("serverinfo"), listing.server_selected), "\\");
for(player = 1; player <= m; player += 2) for(player = 1; player <= m; player += 2)
@ -350,6 +370,7 @@ class mitem_servers_players : mitem
pos_x += 32*8; pos_x += 32*8;
} }
} }
}
}; };
}; };

View File

@ -1,6 +1,6 @@
#include "../menusys/mitem_grid.qc" #include "../menusys/mitem_grid.qc"
enum enum : int
{ {
GPMI_NAME, //name of the package, for use with the pkg command. GPMI_NAME, //name of the package, for use with the pkg command.
GPMI_CATEGORY, //category text GPMI_CATEGORY, //category text
@ -20,6 +20,7 @@ class mitem_updategrid : mitem_grid
{ {
virtual void(vector pos) item_draw = virtual void(vector pos) item_draw =
{ //make sure we see any updates as they're detected... { //make sure we see any updates as they're detected...
__using getpackagemanagerinfo, ftoi;
if (getpackagemanagerinfo(grid_numchildren, GPMI_NAME)) if (getpackagemanagerinfo(grid_numchildren, GPMI_NAME))
{ {
grid_numchildren++; grid_numchildren++;
@ -35,6 +36,7 @@ class mitem_updategrid : mitem_grid
}; };
void(vector pos, float idx) mitem_updategrid::grid_draw = void(vector pos, float idx) mitem_updategrid::grid_draw =
{ {
__using getpackagemanagerinfo, ftoi;
string text = getpackagemanagerinfo(idx, GPMI_TITLE); string text = getpackagemanagerinfo(idx, GPMI_TITLE);
vector col = item_rgb; vector col = item_rgb;
@ -88,6 +90,7 @@ void(vector pos, float idx) mitem_updategrid::grid_draw =
}; };
*/float(vector pos, float scan, float char, float down, float idx) mitem_updategrid::grid_keypress = */float(vector pos, float scan, float char, float down, float idx) mitem_updategrid::grid_keypress =
{ {
__using getpackagemanagerinfo, ftoi;
string text; string text;
if (!down) if (!down)
return FALSE; return FALSE;
@ -136,6 +139,7 @@ class menu_updates : mitem_exmenu
virtual string(string key) get = virtual string(string key) get =
{ {
__using getpackagemanagerinfo, ftoi;
if (key == "info") if (key == "info")
{ {
string text=__NULL__, tmp; string text=__NULL__, tmp;
@ -157,6 +161,9 @@ void(mitem_desktop desktop) M_Menu_Updates =
mitem it; mitem it;
float h = (480+240)/2; float h = (480+240)/2;
if (!checkbuiltin(getpackagemanagerinfo))
return; //not supported in this engine...
localcmd("pkg update\n"); localcmd("pkg update\n");
//create the menu, give it focus, and make sure its displayed over everything else. //create the menu, give it focus, and make sure its displayed over everything else.

View File

@ -31,6 +31,7 @@ void() mitem_desktop::mitem_desktop =
#define menu_font_fallback autocvar(gl_font, "") #define menu_font_fallback autocvar(gl_font, "")
queryscreensize(); queryscreensize();
__using(loadfont, drawfont)
if (checkextension("DP_GFX_FONTS")) if (checkextension("DP_GFX_FONTS"))
{ {
//make sure we have a font that can cope with slightly up-scaled stuff. //make sure we have a font that can cope with slightly up-scaled stuff.
@ -127,8 +128,11 @@ float(vector pos, float scan, float char, float down) mitem_desktop::item_keypre
if (scan == K_MOUSE1 && down) if (scan == K_MOUSE1 && down)
{ {
#if defined(CSQC) && defined(FTE_SPLITSCREEN) #if defined(CSQC) && defined(FTE_SPLITSCREEN)
__using(numclientseats)
{
if (numclientseats) if (numclientseats)
localcmd("in_forcesplitclient 0\n"); cvar_set("in_forceseat", "0"); //disable it.
}
#endif #endif
if (item_flags & IF_NOCURSOR) if (item_flags & IF_NOCURSOR)
{ {
@ -140,12 +144,15 @@ float(vector pos, float scan, float char, float down) mitem_desktop::item_keypre
if (scan == K_MOUSE2 && down) if (scan == K_MOUSE2 && down)
{ {
#if defined(CSQC) && defined(FTE_SPLITSCREEN) #if defined(CSQC) && defined(FTE_SPLITSCREEN)
__using(numclientseats)
{
if (numclientseats > 3) if (numclientseats > 3)
localcmd(strcat("in_forcesplitclient ", ftos(1 + ((ui.mousepos[0]>ui.screensize[0]/2)?1:0) + ((ui.mousepos[1]>ui.screensize[1]/2)?2:0)), "\n")); cvar_set("in_forceseat", ftos(1 + ((ui.mousepos[0]>ui.screensize[0]/2)?1:0) + ((ui.mousepos[1]>ui.screensize[1]/2)?2:0)));
else if (numclientseats > 1) else if (numclientseats > 1)
localcmd(strcat("in_forcesplitclient ", ftos(1 + floor(ui.mousepos[1]*numclientseats/ui.screensize[1])), "\n")); cvar_set("in_forceseat", ftos(1 + floor(ui.mousepos[1]*numclientseats/ui.screensize[1])));
else if (numclientseats) else if (numclientseats)
localcmd("in_forcesplitclient 0\n"); cvar_set("in_forceseat", "0"); //disable it.
}
#endif #endif
if (item_flags & IF_NOCURSOR) if (item_flags & IF_NOCURSOR)
{ {
@ -185,7 +192,7 @@ void(float seat, vector minpos, vector size) mitem_desktop::drawgame_helper =
clearscene(); clearscene();
addentities(MASK_ENGINE|MASK_VIEWMODEL); addentities(MASK_ENGINE|MASK_VIEWMODEL);
} }
else else __using(VF_VIEWENTITY, VF_LPLAYER)
{ {
setviewprop(VF_LPLAYER, seat); setviewprop(VF_LPLAYER, seat);
setproperty(VF_VIEWENTITY, player_localentnum); setproperty(VF_VIEWENTITY, player_localentnum);
@ -220,6 +227,7 @@ void(vector pos) mitem_desktop::item_draw =
else if (this.drawgame != __NULL__) else if (this.drawgame != __NULL__)
{ {
#ifdef FTE_SPLITSCREEN #ifdef FTE_SPLITSCREEN
__using numclientseats, VF_LPLAYER;
if (numclientseats > 3) if (numclientseats > 3)
{ {
drawgame_helper(0, [0, 0], 0.5*ui.screensize); drawgame_helper(0, [0, 0], 0.5*ui.screensize);

View File

@ -67,10 +67,18 @@ class mitem_spinnymodel : mitem
//it might end up clobbering any fields used for multiple things... //it might end up clobbering any fields used for multiple things...
virtual void(vector pos) item_draw = virtual void(vector pos) item_draw =
{ {
#ifndef CSQC
if (!checkbuiltin(clearscene) || !checkbuiltin(setviewprop) || !checkbuiltin(addentity) || !checkbuiltin(renderscene))
{
drawstring(pos, "Renderscene unsupported", [8,8], [1,1,1],1,0);
return;
}
__using VF_ORIGIN, VF_ANGLES, VF_MIN, VF_SIZE, VF_FOV, VF_AFOV;
#endif
vector orgbias; vector orgbias;
orgbias = '0 0 0'; orgbias = '0 0 0';
if (dp_workarounds) if (dp_workarounds)
orgbias = (vector)getviewprop(VF_ORIGIN); //DP still lights the entity even if the world isn't drawn. this results in inconsistant/buggy light levels. there's nothing we can do about that other than stopping it from being completely black. __using(getviewprop) orgbias = (vector)getviewprop(VF_ORIGIN); //DP still lights the entity even if the world isn't drawn. this results in inconsistant/buggy light levels. there's nothing we can do about that other than stopping it from being completely black.
origin = orgbias; origin = orgbias;
origin_z += zbias; origin_z += zbias;
@ -137,8 +145,13 @@ class mitem_spinnymodel : mitem
// return; // return;
} }
#ifndef CSQC
if (checkbuiltin(precache_model) && checkbuiltin(setmodel))
{
precache_model(item_text); precache_model(item_text);
setmodel(this, item_text); //use the size information from the engine, woo for unreliability. setmodel(this, item_text); //use the size information from the engine, woo for unreliability.
}
#endif
zbias += (mins_z - maxs_z)/2 - mins_z; //center the model on its z axis, so the whole thing is visible. zbias += (mins_z - maxs_z)/2 - mins_z; //center the model on its z axis, so the whole thing is visible.
frame = firstframe; frame = firstframe;
if (!angles_y && !rotatespeed) if (!angles_y && !rotatespeed)

View File

@ -171,7 +171,13 @@ class mitem_label : mitem
if (ui.drawrectmax[0] > ui.drawrectmin[0] && ui.drawrectmax[1] > ui.drawrectmin[1]) if (ui.drawrectmax[0] > ui.drawrectmin[0] && ui.drawrectmax[1] > ui.drawrectmin[1])
{ {
ui.setcliparea(ui.drawrectmin[0], ui.drawrectmin[1], ui.drawrectmax[0] - ui.drawrectmin[0], ui.drawrectmax[1] - ui.drawrectmin[1]); ui.setcliparea(ui.drawrectmin[0], ui.drawrectmin[1], ui.drawrectmax[0] - ui.drawrectmin[0], ui.drawrectmax[1] - ui.drawrectmin[1]);
if (checkbuiltin(drawtextfield))
clientsize[1] = drawtextfield(textpos, clientsize, fl, text) * item_scale; clientsize[1] = drawtextfield(textpos, clientsize, fl, text) * item_scale;
else
{
drawstring(textpos, text, [8,8], [1,1,1],1,0);
clientsize[1] = 8;
}
ui.setcliparea(omin_x, omin_y, omax_x - omin_x, omax_y - omin_y); ui.setcliparea(omin_x, omin_y, omax_x - omin_x, omax_y - omin_y);
if (vslider) if (vslider)