1
0
Fork 0
forked from fte/fteqw

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
#ifdef CSQC_SIMPLE
#include "qsextensions.qc" //also sets up system defs
#undef CSQC_SIMPLE
#include "fteextensions.qc" //extra stuff...
#include "fteextensions.qc" //extra stuff
#else
#include "fteextensions.qc" //also sets up system defs
#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:
pr_dumpplatform -o fteextensions
Available options:
-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
(Use the -help arg for a list of available args)
*/
#pragma noref 1
//#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 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 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 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)
#ifdef QUAKEWORLD
#define QWSSQC
#else
#define NQSSQC
#endif
#ifdef QUAKEWORLD
#define QWSSQC
#else
#define NQSSQC
#endif
#endif
#if !defined(SSQC) && (defined(QWSSQC) || defined(NQSSQC))
#define SSQC
#define SSQC
#endif
#if defined(CSQC) || defined(MENU)
#define DEP_CSQC DEP
#define DEP_CSQC DEP
#else
#define DEP_CSQC __deprecated("Use CSQC for this")
#define DEP_CSQC __deprecated("Use CSQC for this")
#endif
#ifndef DEP
#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_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_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_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. */
@ -319,20 +310,40 @@ float total_secrets;
float total_monsters;
float found_secrets;
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
#ifdef CSQC
float intermission;
#endif
#if defined(CSQC) || defined(SSQC)
vector v_forward, v_up, v_right;
vector v_forward;
vector v_up;
vector v_right;
#endif
#ifdef CSQC
vector view_angles; /* +x=DOWN */
#endif
#if defined(CSQC) || defined(SSQC)
float trace_allsolid, trace_startsolid, trace_fraction;
vector trace_endpos, trace_plane_normal;
float trace_allsolid;
float trace_startsolid;
float trace_fraction;
vector trace_endpos;
vector trace_plane_normal;
float trace_plane_dist;
entity trace_ent;
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. */
#endif
#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_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. */
@ -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. */
int serverid; /* The unique id of this server within the server cluster. */
#endif
#ifdef CSQC
.string message; /* Allows the csqc to read the map description from the server. */
#endif
#ifdef SSQC
.float button3;
.float button4;
@ -538,6 +552,21 @@ int serverid; /* The unique id of this server within the server cluster. */
.float button8;
#endif
#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. */
#endif
#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_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). */
.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 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. */
@ -621,7 +650,6 @@ __deprecated("Does not work with MVDs nor splitscreen.") .float dimension_ghost_
__deprecated("Use SendFlags instead.") .float Version; /* Obsolete */
__deprecated("Doesn't support RGB player colours.") .float clientcolors;
.float viewzoom;
.float items2;
.float playerclass;
.float hasted;
.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_default = 255;
/* 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
#if defined(CSQC) || defined(SSQC)
__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. */
const float FONT_DEFAULT = 0;
#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 FALSE = 0; /* File not found... */
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
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
#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)
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_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. */
@ -1030,6 +1127,7 @@ const float FL_LAGGEDMOVE = 65536; /* Enables anti-lag on rockets etc. */
const float MOVE_NORMAL = 0;
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_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_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. */
@ -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_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
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_SOUND = 1; /* precache_sound */
const float RESTYPE_PARTICLE = 2; /* particleeffectnum */
@ -1119,7 +1223,10 @@ const float EV_FIELD = 5;
const float EV_FUNCTION = 6;
const float EV_POINTER = 7;
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). */
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. */
@ -1148,6 +1255,7 @@ const float STAT_USER = 32; /* Custom user stats start here (lower values are re
#endif
#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_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_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. */
@ -1218,6 +1326,12 @@ const float VF_SKYROOM_CAMERA = 222; /* Controls the camera position of the skyr
#endif
#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 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_R16G16B16A16F = 2; /* Half-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_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_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
#ifdef SSQC
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;
float(string name) cvar = #14;
void(string name, string value) cvar_set = #15;
void(string text) dprint = #16;
void(string text, ...) dprint = #16;
string(float) ftos = #17;
float(float) fabs = #18;
string(vector) vtos = #19;
@ -1610,11 +1724,11 @@ string(string s) precache_model = #20; /*
#endif
#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.
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.
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
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. */
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
Converts the given float into a true integer without depending on extended qcvm instructions. */
float(int) itof = #0:itof; /* Part of FTE_QC_INTCONV
Converts the given true integer into a float without depending on extended qcvm instructions. */
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. If shift and mask are specified then only specific parts of the integer will be cast to float. */
#if defined(CSQC) || defined(SSQC)
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
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
{
vector dest;
@ -2296,8 +2436,14 @@ void(optional entity ent, optional vector neworigin) touchtriggers = #279; /*
void(float buf, float fl) WriteFloat = #280; /*
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; /*
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
#if defined(CSQC) || defined(SSQC)
@ -2531,18 +2677,18 @@ void(vector pivot, vector mins, vector maxs, string pic, vector txmin, vector tx
#ifdef CSQC
#define getstati_punf(stnum) (float)(__variant)getstati(stnum)
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
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; /*
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. */
__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; /*
Sets a model by precache index instead of by name. Otherwise identical to setmodel. */
@ -2773,9 +2919,15 @@ string() readstring = #366; /*
float() readfloat = #367; /*
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; /*
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; /*
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*/
void(strbuf bufhandle, float string_index) bufstr_free = #449; /* Part of DP_QC_STRINGBUFFERS*/
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, 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;
@ -3035,7 +3187,11 @@ string(string s) strdecolorize = #477; /* Part of DP_QC_STRINGCOLORFUNCTIONS
Flattens any markup/colours, removing them from the string. */
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) strtoupper = #481; /* Part of DP_QC_STRING_CASE_FUNCTIONS*/
#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. */
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; /*
Dangerous, but sandboxed to data/ */
#if defined(CSQC) || defined(MENU)
#define K_TAB 9
#define K_ENTER 13
#define K_ESCAPE 27
#define K_SPACE 32
#define K_BACKSPACE 127
#define K_UPARROW 128
#define K_DOWNARROW 129
#define K_LEFTARROW 130
#define K_RIGHTARROW 131
#define K_LALT 132
#define K_RALT -245
#define K_LCTRL 133
#define K_RCTRL -246
#define K_LSHIFT 134
#define K_RSHIFT -247
#define K_F1 135
#define K_F2 136
#define K_F3 137
#define K_F4 138
#define K_F5 139
#define K_F6 140
#define K_F7 141
#define K_F8 142
#define K_F9 143
#define K_F10 144
#define K_F11 145
#define K_F12 146
#define K_INS 147
#define K_DEL 148
#define K_PGDN 149
#define K_PGUP 150
#define K_HOME 151
#define K_END 152
#define K_KP_HOME 164
#define K_KP_UPARROW 165
#define K_KP_PGUP 166
#define K_KP_LEFTARROW 161
#define K_KP_5 162
#define K_KP_RIGHTARROW 163
#define K_KP_END 158
#define K_KP_DOWNARROW 159
#define K_KP_PGDN 160
#define K_KP_ENTER 172
#define K_KP_INS 157
#define K_KP_DEL 167
#define K_KP_SLASH 168
#define K_KP_MINUS 170
#define K_KP_PLUS 171
#define K_KP_NUMLOCK 154
#define K_KP_STAR 169
#define K_KP_EQUALS 173
#define K_MOUSE1 512
#define K_MOUSE2 513
#define K_MOUSE3 514
#define K_MOUSE4 517
#define K_MOUSE5 518
#define K_MOUSE6 519
#define K_MOUSE7 520
#define K_MOUSE8 521
#define K_MOUSE9 522
#define K_MOUSE10 523
#define K_MWHEELUP 515
#define K_MWHEELDOWN 516
#define K_LWIN -239
#define K_RWIN -240
#define K_APP -241
#define K_SEARCH -242
#define K_POWER -130
#define K_VOLUP -243
#define K_VOLDOWN -244
#define K_JOY1 768
#define K_JOY2 769
#define K_JOY3 770
#define K_JOY4 771
#define K_AUX1 784
#define K_AUX2 785
#define K_AUX3 786
#define K_AUX4 787
#define K_AUX5 788
#define K_AUX6 789
#define K_AUX7 790
#define K_AUX8 791
#define K_AUX9 792
#define K_AUX10 793
#define K_AUX11 794
#define K_AUX12 795
#define K_AUX13 796
#define K_AUX14 797
#define K_AUX15 798
#define K_AUX16 799
#define K_AUX17 800
#define K_AUX18 801
#define K_AUX19 802
#define K_AUX20 803
#define K_AUX21 804
#define K_AUX22 805
#define K_AUX23 806
#define K_AUX24 807
#define K_AUX25 808
#define K_AUX26 809
#define K_AUX27 810
#define K_AUX28 811
#define K_AUX29 812
#define K_AUX30 813
#define K_AUX31 814
#define K_AUX32 815
#define K_PAUSE 153
#define K_PRINTSCREEN 174
#define K_CAPSLOCK 155
#define K_SCROLLLOCK 156
#define K_SEMICOLON 59
#define K_PLUS 43
#define K_MINUS 45
#define K_TILDE 126
#define K_BACKQUOTE 96
#define K_BACKSLASH 92
#define K_GP_A 826
#define K_GP_B 827
#define K_GP_X 828
#define K_GP_Y 829
#define K_GP_LSHOULDER 824
#define K_GP_RSHOULDER 825
#define K_GP_LTRIGGER 830
#define K_GP_RTRIGGER 831
#define K_GP_BACK 821
#define K_GP_START 820
#define K_GP_LTHUMB 822
#define K_GP_RTHUMB 823
#define K_GP_DPAD_UP 816
#define K_GP_DPAD_DOWN 817
#define K_GP_DPAD_LEFT 818
#define K_GP_DPAD_RIGHT 819
#define K_GP_GUIDE -202
#define K_GP_UNKNOWN -255
#define K_GP_LTHUMB_UP 832
#define K_GP_LTHUMB_DOWN 833
#define K_GP_LTHUMB_LEFT 834
#define K_GP_LTHUMB_RIGHT 835
#define K_GP_RTHUMB_UP 836
#define K_GP_RTHUMB_DOWN 837
#define K_GP_RTHUMB_LEFT 838
#define K_GP_RTHUMB_RIGHT 839
const float K_TAB = 9;
const float K_ENTER = 13;
const float K_ESCAPE = 27;
const float K_SPACE = 32;
const float K_BACKSPACE = 127;
const float K_UPARROW = 128;
const float K_DOWNARROW = 129;
const float K_LEFTARROW = 130;
const float K_RIGHTARROW = 131;
const float K_LALT = 132;
const float K_RALT = -245;
const float K_LCTRL = 133;
const float K_RCTRL = -246;
const float K_LSHIFT = 134;
const float K_RSHIFT = -247;
const float K_F1 = 135;
const float K_F2 = 136;
const float K_F3 = 137;
const float K_F4 = 138;
const float K_F5 = 139;
const float K_F6 = 140;
const float K_F7 = 141;
const float K_F8 = 142;
const float K_F9 = 143;
const float K_F10 = 144;
const float K_F11 = 145;
const float K_F12 = 146;
const float K_INS = 147;
const float K_DEL = 148;
const float K_PGDN = 149;
const float K_PGUP = 150;
const float K_HOME = 151;
const float K_END = 152;
const float K_KP_HOME = 164;
const float K_KP_UPARROW = 165;
const float K_KP_PGUP = 166;
const float K_KP_LEFTARROW = 161;
const float K_KP_5 = 162;
const float K_KP_RIGHTARROW = 163;
const float K_KP_END = 158;
const float K_KP_DOWNARROW = 159;
const float K_KP_PGDN = 160;
const float K_KP_ENTER = 172;
const float K_KP_INS = 157;
const float K_KP_DEL = 167;
const float K_KP_SLASH = 168;
const float K_KP_MINUS = 170;
const float K_KP_PLUS = 171;
const float K_KP_NUMLOCK = 154;
const float K_KP_STAR = 169;
const float K_KP_EQUALS = 173;
const float K_MOUSE1 = 512;
const float K_MOUSE2 = 513;
const float K_MOUSE3 = 514;
const float K_MOUSE4 = 517;
const float K_MOUSE5 = 518;
const float K_MOUSE6 = 519;
const float K_MOUSE7 = 520;
const float K_MOUSE8 = 521;
const float K_MOUSE9 = 522;
const float K_MOUSE10 = 523;
const float K_MWHEELUP = 515;
const float K_MWHEELDOWN = 516;
const float K_LWIN = -239;
const float K_RWIN = -240;
const float K_APP = -241;
const float K_SEARCH = -242;
const float K_POWER = -130;
const float K_VOLUP = -243;
const float K_VOLDOWN = -244;
const float K_JOY1 = 768;
const float K_JOY2 = 769;
const float K_JOY3 = 770;
const float K_JOY4 = 771;
const float K_AUX1 = 784;
const float K_AUX2 = 785;
const float K_AUX3 = 786;
const float K_AUX4 = 787;
const float K_AUX5 = 788;
const float K_AUX6 = 789;
const float K_AUX7 = 790;
const float K_AUX8 = 791;
const float K_AUX9 = 792;
const float K_AUX10 = 793;
const float K_AUX11 = 794;
const float K_AUX12 = 795;
const float K_AUX13 = 796;
const float K_AUX14 = 797;
const float K_AUX15 = 798;
const float K_AUX16 = 799;
const float K_AUX17 = 800;
const float K_AUX18 = 801;
const float K_AUX19 = 802;
const float K_AUX20 = 803;
const float K_AUX21 = 804;
const float K_AUX22 = 805;
const float K_AUX23 = 806;
const float K_AUX24 = 807;
const float K_AUX25 = 808;
const float K_AUX26 = 809;
const float K_AUX27 = 810;
const float K_AUX28 = 811;
const float K_AUX29 = 812;
const float K_AUX30 = 813;
const float K_AUX31 = 814;
const float K_AUX32 = 815;
const float K_PAUSE = 153;
const float K_PRINTSCREEN = 174;
const float K_CAPSLOCK = 155;
const float K_SCROLLLOCK = 156;
const float K_SEMICOLON = 59;
const float K_PLUS = 43;
const float K_MINUS = 45;
const float K_TILDE = 126;
const float K_BACKQUOTE = 96;
const float K_BACKSLASH = 92;
const float K_GP_A = 826;
const float K_GP_B = 827;
const float K_GP_X = 828;
const float K_GP_Y = 829;
const float K_GP_LSHOULDER = 824;
const float K_GP_RSHOULDER = 825;
const float K_GP_LTRIGGER = 830;
const float K_GP_RTRIGGER = 831;
const float K_GP_BACK = 821;
const float K_GP_START = 820;
const float K_GP_LTHUMB = 822;
const float K_GP_RTHUMB = 823;
const float K_GP_DPAD_UP = 816;
const float K_GP_DPAD_DOWN = 817;
const float K_GP_DPAD_LEFT = 818;
const float K_GP_DPAD_RIGHT = 819;
const float K_GP_GUIDE = -202;
const float K_GP_UNKNOWN = -255;
const float K_GP_LTHUMB_UP = 832;
const float K_GP_LTHUMB_DOWN = 833;
const float K_GP_LTHUMB_LEFT = 834;
const float K_GP_LTHUMB_RIGHT = 835;
const float K_GP_RTHUMB_UP = 836;
const float K_GP_RTHUMB_DOWN = 837;
const float K_GP_RTHUMB_LEFT = 838;
const float K_GP_RTHUMB_RIGHT = 839;
#endif
#ifdef _ACCESSORS
accessor strbuf : float

View file

@ -1,13 +1,10 @@
#pragma progs_dat "../menu.dat"
#pragma target fte
//#pragma target fte
#define MENU //select the module
#include "fteextensions.qc" //also sets up system defs
#includelist
fteextensions.qc //also sets up system defs
menusys/mitems.qc //root item type
menusys/mitems_common.qc //basic types
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
float(string cmd, float assumption) checkcommand2 =
{
__using checkcommand;
if (!checkextension("FTE_QC_CHECKCOMMAND"))
return assumption;
return checkcommand(cmd);
@ -63,6 +64,7 @@ float(__variant cmd, float assumption) checkbuiltin2 =
return assumption;
return checkbuiltin(cmd);
};
#define checkbuiltin2(c,a) ((a)?checkbuiltin2(c,a):checkbuiltin(c))
#ifdef CSQC
float() clientstate =

View file

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

View file

@ -6,7 +6,17 @@ static string newgameinfo;
nonstatic void(mitem_desktop desktop) M_Dir =
{ //implementing this primarily so its available in QSS. :P
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)));
for (float i = 0; i < search_getsize(h); i++)
{
@ -32,68 +42,67 @@ 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)
static string(string name) getmapdesc =
{
filestream f;
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
if (checkbuiltin(fread) && checkbuiltin(fseek) && checkbuiltin(memalloc) && checkbuiltin(memfree) && checkbuiltin(memgetval) && checkbuiltin(itof) && checkbuiltin(ftoi))
{ //we can do it, so do it.
f = fopen(name, FILE_READ);
filestream f = fopen(name, FILE_READ);
if (f < 0)
print(sprintf("Unable to read %s\n", name));
}
name = substring(name, 5, -5);
if (f < 0)
return name;
int *header = memalloc(sizeof(int)*4);
int bspver = 0, entofs, entlen;
if (fread(f, (void*)header, sizeof(int)*4) == sizeof(int)*4 && ((bspver=header[0]),(
bspver == FOURCC('I','B','S','P') || //IBSP (q2/q3)
bspver == FOURCC('R','B','S','P') || //RBSP (jk2o etc)
bspver == FOURCC('F','B','S','P') || //IBSP (qfusion/warsow)
bspver == 29i || //q1
bspver == 30i || //hl
bspver == FOURCC('B','S','P','2')))) //bsp2
{
if (bspver == FOURCC('I','B','S','P'))
{ //has an actual version number! ooo...
entofs = header[2];
entlen = header[3];
}
else
name = substring(name, 5, -5);
if (f < 0)
return name;
int *header = memalloc(sizeof(int)*4);
int bspver = 0, entofs, entlen;
if (fread(f, (void*)header, sizeof(int)*4) == sizeof(int)*4 && ((bspver=header[0]),(
bspver == FOURCC('I','B','S','P') || //IBSP (q2/q3)
bspver == FOURCC('R','B','S','P') || //RBSP (jk2o etc)
bspver == FOURCC('F','B','S','P') || //IBSP (qfusion/warsow)
bspver == 29i || //q1
bspver == 30i || //hl
bspver == FOURCC('B','S','P','2')))) //bsp2
{
entofs = header[1];
entlen = header[2];
}
fseek(f, entofs);
string s = (string)memalloc(entlen+1);
fread(f, (void*)s, entlen);
float argc = tokenize(s);
if (argv(0) == "{")
{
for (float p = 1; p < argc; p+=2)
{
string t = argv(p);
if (t == "message")
{ //finally found the human-readable name of the map. woo.
name = argv(p+1);
break;
}
if (t == "}") //don't read the message from some kind of trigger
break;
if (t == "{") //some sort of corruption
break;
if (bspver == FOURCC('I','B','S','P'))
{ //has an actual version number! ooo...
entofs = header[2];
entlen = header[3];
}
else
{
entofs = header[1];
entlen = header[2];
}
fseek(f, entofs);
string s = (string)memalloc(entlen+1);
fread(f, (void*)s, entlen);
float argc = tokenize(s);
if (argv(0) == "{")
{
for (float p = 1; p < argc; p+=2)
{
string t = argv(p);
if (t == "message")
{ //finally found the human-readable name of the map. woo.
name = argv(p+1);
break;
}
if (t == "}") //don't read the message from some kind of trigger
break;
if (t == "{") //some sort of corruption
break;
}
}
else
name = "ERROR";
memfree((void*)s);
}
else
name = "ERROR";
memfree((void*)s);
name = sprintf("UNSUPPORTED %i", bspver);
memfree(header);
fclose(f);
return name;
}
else
name = sprintf("UNSUPPORTED %i", bspver);
memfree(header);
fclose(f);
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 =

View file

@ -2,7 +2,7 @@ class mitem_playerpreview : mitem_spinnymodel
{
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 (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 =
{
local float i;
float i;
mitem_exmenu m;
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');
@ -28,18 +28,22 @@ nonstatic void(mitem_desktop desktop) M_Configs =
float fs, y=0;
float c = 0;
fs = search_begin("configs/game_*.cfg", TRUE, TRUE);
float c = search_getsize(fs);
for (i = 0; i < c; i++)
if (fs >= 0)
{
string fname = search_getfilename(fs, i);
string iname = strzone(substring(fname, 13, -5));
string dname = GetFirstLineComment(fname, iname);
iname = sprintf("exec \"%s\"", fname);
if (dname && !fr.findchildcmd(iname))
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');
c = search_getsize(fs);
for (i = 0; i < c; i++)
{
string fname = search_getfilename(fs, i);
string iname = strzone(substring(fname, 13, -5));
string dname = GetFirstLineComment(fname, iname);
iname = sprintf("exec \"%s\"", fname);
if (dname && !fr.findchildcmd(iname))
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)
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;
mitem_exmenu m;
float unsaved = FALSE;
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.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);
// 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;

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_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_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_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
@ -149,6 +149,20 @@ class mitem_servers : mitem
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 =
{
float displaysize;
@ -195,7 +209,7 @@ class mitem_servers : mitem
//connect on double clicks. because we can.
addr = gethostcachestring(gethostcacheindexforkey("cname"), server_selected);
if (addr)
localcmd(sprintf("m_pop;connect \"%s\"\n", addr));
localcmd(sprintf("m_pop;%sconnect \"%s\"\n", getgamedircmd(), addr));
}
else
server_selected = news;
@ -207,19 +221,19 @@ class mitem_servers : mitem
{ //connect normally
addr = gethostcachestring(gethostcacheindexforkey("cname"), server_selected);
if (addr)
localcmd(sprintf("m_pop;connect \"%s\"\n", addr));
localcmd(sprintf("m_pop;%sconnect \"%s\"\n", getgamedircmd(), addr));
}
else if (scan == 's')
{ //s = join as a spectator
addr = gethostcachestring(gethostcacheindexforkey("cname"), server_selected);
if (addr)
localcmd(sprintf("m_pop;observe \"%s\"\n", addr));
localcmd(sprintf("m_pop;%sobserve \"%s\"\n", getgamedircmd(), addr));
}
else if (scan == 'j')
{ //s = join as a spectator
addr = gethostcachestring(gethostcacheindexforkey("cname"), server_selected);
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)
{
@ -303,7 +317,10 @@ class mitem_servers_players : mitem
return;
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)
break;
tokenize(playerinfo);
@ -335,19 +352,23 @@ class mitem_servers_players : mitem
pos_x += 16*6;
y = 0;
}
// drawtextfield(opos, item_size, 3, gethostcachestring(gethostcacheindexforkey("serverinfo"), listing.server_selected));
m = tokenizebyseparator(gethostcachestring(gethostcacheindexforkey("serverinfo"), listing.server_selected), "\\");
for(player = 1; player <= m; player += 2)
{
drawtextfield(pos, '64 8', 6, argv(player));
drawtextfield(pos+'68 0', [32*8-40, 8], 3, argv(player+1));
pos_y += 8;
if (++y == 8)
if (checkbuiltin(drawtextfield))
{
// drawtextfield(opos, item_size, 3, gethostcachestring(gethostcacheindexforkey("serverinfo"), listing.server_selected));
m = tokenizebyseparator(gethostcachestring(gethostcacheindexforkey("serverinfo"), listing.server_selected), "\\");
for(player = 1; player <= m; player += 2)
{
y-= 8;
pos_y -= 8*8;
pos_x += 32*8;
drawtextfield(pos, '64 8', 6, argv(player));
drawtextfield(pos+'68 0', [32*8-40, 8], 3, argv(player+1));
pos_y += 8;
if (++y == 8)
{
y-= 8;
pos_y -= 8*8;
pos_x += 32*8;
}
}
}
};

View file

@ -1,6 +1,6 @@
#include "../menusys/mitem_grid.qc"
enum
enum : int
{
GPMI_NAME, //name of the package, for use with the pkg command.
GPMI_CATEGORY, //category text
@ -20,6 +20,7 @@ class mitem_updategrid : mitem_grid
{
virtual void(vector pos) item_draw =
{ //make sure we see any updates as they're detected...
__using getpackagemanagerinfo, ftoi;
if (getpackagemanagerinfo(grid_numchildren, GPMI_NAME))
{
grid_numchildren++;
@ -35,6 +36,7 @@ class mitem_updategrid : mitem_grid
};
void(vector pos, float idx) mitem_updategrid::grid_draw =
{
__using getpackagemanagerinfo, ftoi;
string text = getpackagemanagerinfo(idx, GPMI_TITLE);
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 =
{
__using getpackagemanagerinfo, ftoi;
string text;
if (!down)
return FALSE;
@ -136,6 +139,7 @@ class menu_updates : mitem_exmenu
virtual string(string key) get =
{
__using getpackagemanagerinfo, ftoi;
if (key == "info")
{
string text=__NULL__, tmp;
@ -157,6 +161,9 @@ void(mitem_desktop desktop) M_Menu_Updates =
mitem it;
float h = (480+240)/2;
if (!checkbuiltin(getpackagemanagerinfo))
return; //not supported in this engine...
localcmd("pkg update\n");
//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, "")
queryscreensize();
__using(loadfont, drawfont)
if (checkextension("DP_GFX_FONTS"))
{
//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 defined(CSQC) && defined(FTE_SPLITSCREEN)
if (numclientseats)
localcmd("in_forcesplitclient 0\n");
__using(numclientseats)
{
if (numclientseats)
cvar_set("in_forceseat", "0"); //disable it.
}
#endif
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 defined(CSQC) && defined(FTE_SPLITSCREEN)
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"));
else if (numclientseats > 1)
localcmd(strcat("in_forcesplitclient ", ftos(1 + floor(ui.mousepos[1]*numclientseats/ui.screensize[1])), "\n"));
else if (numclientseats)
localcmd("in_forcesplitclient 0\n");
__using(numclientseats)
{
if (numclientseats > 3)
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)
cvar_set("in_forceseat", ftos(1 + floor(ui.mousepos[1]*numclientseats/ui.screensize[1])));
else if (numclientseats)
cvar_set("in_forceseat", "0"); //disable it.
}
#endif
if (item_flags & IF_NOCURSOR)
{
@ -185,7 +192,7 @@ void(float seat, vector minpos, vector size) mitem_desktop::drawgame_helper =
clearscene();
addentities(MASK_ENGINE|MASK_VIEWMODEL);
}
else
else __using(VF_VIEWENTITY, VF_LPLAYER)
{
setviewprop(VF_LPLAYER, seat);
setproperty(VF_VIEWENTITY, player_localentnum);
@ -220,6 +227,7 @@ void(vector pos) mitem_desktop::item_draw =
else if (this.drawgame != __NULL__)
{
#ifdef FTE_SPLITSCREEN
__using numclientseats, VF_LPLAYER;
if (numclientseats > 3)
{
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...
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;
orgbias = '0 0 0';
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_z += zbias;
@ -137,8 +145,13 @@ class mitem_spinnymodel : mitem
// return;
}
precache_model(item_text);
setmodel(this, item_text); //use the size information from the engine, woo for unreliability.
#ifndef CSQC
if (checkbuiltin(precache_model) && checkbuiltin(setmodel))
{
precache_model(item_text);
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.
frame = firstframe;
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])
{
ui.setcliparea(ui.drawrectmin[0], ui.drawrectmin[1], ui.drawrectmax[0] - ui.drawrectmin[0], ui.drawrectmax[1] - ui.drawrectmin[1]);
clientsize[1] = drawtextfield(textpos, clientsize, fl, text) * item_scale;
if (checkbuiltin(drawtextfield))
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);
if (vslider)