djcev.com

//

Git Repos / fte_dogmode / commit 1de5850

Commit: 1de5850fad8e5b8687b3fe3adf431d30cca2283c
Parent: 88eaf44e792f9eb40e2150a1c6e82cb289861e08
Author: Cameron Vanderzanden, 2023-11-06 11:03
Committer: Cameron Vanderzanden, 2023-11-06 11:03

Commit Message

First draft client prediction, pmove changes, misc

CSQC Client movement prediction & interpolation based on FTE's CSQCTest
and a guide written by Eukara. Many things still need to be implemented:
powerup screen effects, intermission handling, more things I'm not
remembering. There's also a significant prediction error that happens
every time the player jumps, some kind of tracking disagreement between
the client and server. Having said all of that, it's a working first
draft.

There's also a new SlideMove/FlyMove clone brought in from the
Nuclide SDK for FTE, published / written by Vera Visions LLC (and
presumably Eukara). This new NuclideMove will hopefully run faster
and be more consistent than my previous implementations of Q3 SlideMove
and Q1 FlyMove.

In addition to all of that I've also started to reformat and move
around some of the Progs Dump 3 code, both to clean up the look
of the text and as an excuse to read & try to understand it.
Significant features are now in their own files (triggers_teleport.qc,
etc.). I'm not sure I'll keep it this way, it's probably a bad idea,
but for now it's nice to look at.

This took forever to do.

Change List

Diff qc/client.qc

diff --git a/qc/client.qc b/qc/client.qc
index 448eb2b..b25d531 100644
--- a/qc/client.qc
+++ b/qc/client.qc
@@ -3,7 +3,7 @@
==============================================================================*/

// prototypes
-void () W_WeaponFrame;
+void() W_WeaponFrame;
void() W_SetCurrentAmmo;
void(entity attacker, float damage) player_pain;
void() player_stand1;
@@ -11,7 +11,6 @@ void() player_stand1;
void (vector org, entity death_owner) spawn_tdeath;

float modelindex_eyes, modelindex_player;
-void() SUB_CheckWaiting; // in triggers.qc

void() SetChangeParms =
{
@@ -223,6 +222,26 @@ entity() SelectSpawnPoint =
return spot;
};

+// TODO CEV
+float(entity to, float fl) SendPlayer =
+{
+ WriteByte (MSG_ENTITY, CLASS_PLAYER);
+ WriteByte (MSG_ENTITY, self.frame);
+ WriteShort (MSG_ENTITY, self.angles_x * 32767 / 360);
+ WriteShort (MSG_ENTITY, self.angles_y * 32767 / 360);
+ WriteShort (MSG_ENTITY, self.angles_z * 32767 / 360);
+ WriteCoord (MSG_ENTITY, self.origin_x);
+ WriteCoord (MSG_ENTITY, self.origin_y);
+ WriteCoord (MSG_ENTITY, self.origin_z);
+ WriteShort (MSG_ENTITY, self.velocity_x);
+ WriteShort (MSG_ENTITY, self.velocity_y);
+ WriteShort (MSG_ENTITY, self.velocity_z);
+ WriteFloat (MSG_ENTITY, self.flags);
+ WriteFloat (MSG_ENTITY, self.pmove_flags);
+ WriteFloat (MSG_ENTITY, self.movetype);
+ return TRUE;
+};
+
//======================================================================
// PutClientInServer
// called each time a player is spawned
@@ -323,6 +342,10 @@ void() PutClientInServer =
self.velocity = '0 0 0';
// 1998-07-21 Player moves after respawn fix by Xian

+ // TODO CEV
+ self.SendEntity = SendPlayer;
+ self.SendFlags = FULLSEND;
+
player_stand1 ();

if (deathmatch || coop)
@@ -542,13 +565,66 @@ void() PlayerDeathThink =
};

//======================================================================
+// PlayerJump
+//----------------------------------------------------------------------
+void() PlayerJump =
+{
+ if (self.flags & FL_WATERJUMP)
+ return;
+
+ if (self.waterlevel >= 2)
+ {
+ // pmove code predicts this
+ // if (self.watertype == CONTENT_WATER)
+ // self.velocity_z = 100;
+ // else if (self.watertype == CONTENT_SLIME)
+ // self.velocity_z = 80;
+ // else
+ // self.velocity_z = 50;
+
+ if (self.swim_flag < time)
+ {
+ // play swimming sound
+ self.swim_flag = time + 1;
+ if (random() < 0.5)
+ sound (self, CHAN_BODY, "misc/water1.wav",
+ 1, ATTN_NORM);
+ else
+ sound (self, CHAN_BODY, "misc/water2.wav",
+ 1, ATTN_NORM);
+ }
+
+ return;
+ }
+
+ if (!(self.flags & FL_ONGROUND))
+ return;
+
+ if (!(self.flags & FL_JUMPRELEASED))
+ // don't pogo stick
+ return;
+
+ self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
+
+ // don't stairwalk (not yet anyway)
+ self.flags = self.flags - FL_ONGROUND;
+
+ self.button2 = 0;
+ // player jumping sound
+ sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
+
+ // pmove code predicts this
+ // self.velocity_z = self.velocity_z + 270;
+};
+
+//======================================================================
// PlayerClimb
// johnfitz
//======================================================================
void() PlayerClimb =
{
self.velocity = '0 0 160';
-}
+};

//======================================================================
// WaterMove
@@ -657,7 +733,8 @@ void() WaterMove =
void() CheckWaterJump =
{
// from Copper -- dumptruck_ds
- if (self.movetype == MOVETYPE_NOCLIP) return;
+ if (self.movetype == MOVETYPE_NOCLIP)
+ return;

local vector start, end;

@@ -680,6 +757,8 @@ void() CheckWaterJump =
{
// open at eye level
self.flags |= FL_WATERJUMP;
+ // TODO CEV
+ self.pmove_flags |= PMF_WATERJUMP;
self.velocity_z = 225;
// self.flags -= self.flags & FL_JUMPRELEASED;
self.flags &~= FL_JUMPRELEASED;
@@ -739,7 +818,8 @@ void() PlayerPreThink =
CheckRules ();
WaterMove ();

- if (self.waterlevel == 2) CheckWaterJump ();
+ if (self.waterlevel == 2)
+ CheckWaterJump ();

if (self.deadflag >= DEAD_DEAD)
{
@@ -751,11 +831,6 @@ void() PlayerPreThink =
// dying, so do nothing
return;

- // save velocity + speed here before running engine-side physics -- CEV
- self.primal_velocity = self.velocity;
- self.primal_velocity_z = 0;
- self.primal_speed = vlen (self.primal_velocity);
-
// johnfitz ladder conditions, added from Rubicon2 -- dumptruck_ds
if (do_ladder_physics)
{
@@ -784,14 +859,18 @@ void() PlayerPreThink =
self.velocity_z = 0;
}
}
+ else
+ {
+ if (self.button2)
+ PlayerJump ();
+ else
+ self.flags = self.flags | FL_JUMPRELEASED;
+ }

// teleporters can force a non-moving pause time
if (time < self.pausetime)
self.velocity = '0 0 0';

- // save Z velocity here for later -- CEV
- self.primal_velocity_z = self.velocity_z;
-
if (time > self.attack_finished
&& self.currentammo == 0
&& self.weapon != IT_AXE)
@@ -971,6 +1050,15 @@ void() CheckPowerups =
//======================================================================
void() PlayerPostThink =
{
+ // from Copper -- dumptruck_ds
+ if (self.movetype != MOVETYPE_NOCLIP)
+ {
+ self.flags = not(self.flags, FL_FLY);
+ }
+
+ // TODO CEV
+ self.SendFlags = FULLSEND;
+
if (self.view_ofs == '0 0 0')
// intermission or finale
return;
@@ -1018,12 +1106,6 @@ void() PlayerPostThink =
}

CheckPowerups ();
-
- // from Copper -- dumptruck_ds
- if (self.movetype != MOVETYPE_NOCLIP)
- {
- self.flags = not(self.flags, FL_FLY);
- }
};

//======================================================================

Return to the top of this page or return to the overview of this repo.

Diff qc/csqc/csqc_defs.qc

diff --git a/qc/csqc/csqc_defs.qc b/qc/csqc/csqc_defs.qc
index 7172e91..27d74b9 100644
--- a/qc/csqc/csqc_defs.qc
+++ b/qc/csqc/csqc_defs.qc
@@ -51,9 +51,6 @@ const float CLIENT_CKEYSKIN1 = 55; // self.ckeyskin1
const float CLIENT_CKEYSKIN2 = 56; // self.ckeyskin2
const float CLIENT_CKEYSKIN3 = 57; // self.ckeyskin3
const float CLIENT_CKEYSKIN4 = 58; // self.ckeyskin4
-// CEV
-const float CLIENT_VELOCITY_X = 64;
-const float CLIENT_VELOCITY_Y = 65;

//----------------------------------------------------------------------
// Duplicate of IT_ references in defs.qc
@@ -103,296 +100,3 @@ const float EV_FUNCTION = 6;
const float EV_POINTER = 7;
const float EV_INTEGER = 8;

-// ======================================================================
-// This is a merge of three (DP/FTE/QSS) engine def files
-// dpextensions+csprogsdefs from SVN ICCULUS site (DP trunk)
-// fteexentions from triptohell website
-// qsextensions from QSS devkit on triptohell website
-//
-// CSQC range #300-#399
-// ======================================================================
-
-// ----------------------------------------------------------------------
-// DP/FTE extensions ONLY
-// ----------------------------------------------------------------------
-// Forgets all rentities, polygons, and temporary dlights.
-// Resets all view properties to their default values.
-void() clearscene = #300;
-void(float mask) addentities = #301;
-// Copies the entity fields into a new rentity for
-// later rendering via addscene
-void(entity ent) addentity = #302;
-// Allows you to override default view properties like
-// viewport, fov, and whether the engine hud will be drawn.
-// Different VF_ values have slightly different arguments,
-// some are vectors, some floats.
-float(float property, ...) setproperty = #303;
-// Draws all entities, polygons, and particles on the rentity list
-// (which were added via addentities or addentity), using the various
-// view properties set via setproperty. There is no ordering dependancy.
-// The scene must generally be cleared again before more entities
-// are added, as entities will persist even over to the next frame.
-// You may call this builtin multiple times per frame, but should
-// only be called from CSQC_UpdateView.
-void() renderscene = #304;
-// Adds a temporary dlight, ready to be drawn via addscene.
-// Cubemap orientation will be read from v_forward/v_right/v_up.
-void(vector org, float radius, vector lightcolours) adddynamiclight = #305;
-void(vector org, float radius, vector lightcolours, float style, string cubemapname, float pflags) adddynamiclight2 = #305;
-// Specifies the shader to use for the following polygons, along
-// with optional flags.
-// If is2d, the polygon will be drawn as soon as the EndPolygon
-// call is made, rather than waiting for renderscene. This allows
-// complex 2d effects.
-// FTE = void(string texturename, optional float flags, optional float is2d) R_BeginPolygon = #306;
-void(string texturename, float flag, ...) R_BeginPolygon = #306;
-// Specifies a polygon vertex with its various properties
-void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex = #307;
-// Ends the current polygon. At least 3 verticies must have been
-// specified. You do not need to call beginpolygon if you wish to
-// draw another polygon with the same shader
-void() R_EndPolygon = #308;
-// Retrieve a currently-set (typically view) property, allowing you
-// to read the current viewport or other things. Due to cheat protection,
-// certain values may be unretrievable
-// define = FTE version of DP version
-#define getviewprop getproperty
-float(float property) getproperty = #309;
-vector(float property) getpropertyvec = #309;
-// Transform a 2d screen-space point (with depth) into a 3d world-space
-// point, according the various origin+angle+fov etc settings set via
-// setproperty
-vector (vector v) cs_unproject = #310;
-// Transform a 3d world-space point into a 2d screen-space point,
-// according the various origin+angle+fov etc settings set via
-// setproperty
-vector (vector v) cs_project = #311;
-// Draws a 2d line between the two 2d points
-void(float width, vector pos1, vector pos2, vector rgb, float alpha, float flag) drawline = #315;
-// Tells the engine that the image is no longer needed.
-// The image will appear to be new the next time its needed
-void(string name) freepic = #319;
-// Draws the specified string without using any markup at all,
-// even in engines that support it.
-// If UTF-8 is globally enabled in the engine, then that encoding
-// is used (without additional markup), otherwise it is raw quake chars.
-// Software engines may assume a size of '8 8 0', rgb='1 1 1',
-// alpha=1, flag&3=0, but it is not an error to draw out of the screen.
-float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring = #321;
-// 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.
-string(float stnum) getstats = #332;
-// Retrieves the name of the model based upon a precache index.
-// This can be used to reduce csqc network traffic by enabling
-// model matching
-string(float mdlindex) modelnameforindex = #334;
-// Looks up a named font slot. Matches the actual font name as a last resort.
-// find font by fontname and return it's index
-float findfont(string s) = #356;
-float loadfont(string fontname, string fontmaps, string sizes, float slot, float fix_scale, float fix_voffset) = #357;
-
-// ----------------------------------------------------------------------
-// QSS (CSQC Lit) + DP/FTE extensions
-// ----------------------------------------------------------------------
-// Checks to see if the image is currently loaded.
-// Engines might lie, or cache between maps.
-float(string name) iscachedpic = #316;
-// Forces the engine to load the named image. If trywad is specified,
-// the specified name must any lack path and extension.
-string(string name, optional float trywad) precache_pic = #317;
-// Returns the dimensions of the named image. Images specified
-// with .lmp should give the original .lmp's dimensions even if
-// texture replacements use a different resolution.
-// define = FTE version of DP version
-#define drawgetimagesize draw_getimagesize
-vector(string picname) draw_getimagesize = #318;
-// Draw the given quake character at the given position.
-// If flag&4, the function will consider the char to be a unicode
-// char instead (or display as a ? if outside the 32-127 range).
-// size should normally be something like '8 8 0'.
-// rgb should normally be '1 1 1' and alpha normally 1.
-// Software engines may assume the named defaults.
-// Note that ALL text may be rescaled on the X axis due to
-// variable width fonts. The X axis may even be ignored completely.
-float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter = #320;
-// Draws an shader within the given 2d screen box. Software engines
-// may omit support for rgb+alpha, but must support rescaling,
-// and must clip to the screen without crashing
-// flag = draw method; 0=normal, 1=additive, 2=modulate, 3=modulate2
-float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic = #322;
-// Draws a solid block over the given 2d box, with given colour,
-// alpha, and blend mode (specified via flags).
-// flags&3=0 simple blend flags&3=1 additive blend
-float(vector position, vector size, vector rgb, float alpha, float flag) drawfill = #323;
-// Specifies a 2d clipping region (aka: scissor test).
-// 2d draw calls will all be clipped to this 2d box,
-// the area outside will not be modified by any
-// 2d draw call (even 2d polygons).
-void(float x, float y, float width, float height) drawsetcliparea = #324;
-// Reverts the scissor/clip area to the whole screen
-void(void) drawresetcliparea = #325;
-// Draws a string, interpreting markup and recolouring as appropriate
-// QSS/FTE = drawstring, DP = drawcolorcodedstring/drawcolorcodedstring2
-// float(vector position, string text, vector size, vector rgb, float alpha, float drawflag) drawstring = #326;
-float(vector position, string text, vector scale, float alpha, float flag) drawcolorcodedstring = #326;
-vector(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawcolorcodedstring2 = #326;
-// Calculates the width of the screen in virtual pixels.
-// If usecolours is 1, markup that does not affect the string
-// width will be ignored. Will always be decoded as UTF-8 if
-// UTF-8 is globally enabled.
-// If the char size is not specified, '8 8 0' will be assumed
-// float(string text, float usecolours, optional vector fontsize) stringwidth = #327;
-// QSS/FTE = float(string text, float usecolours, optional vector fontsize) stringwidth = #327;
-float(string text, float allowColorCodes, vector size) stringwidth = #327;
-// Draws a rescaled subsection of an image to the screen
-// QSS/FTE = void(vector pos, vector sz, string pic, vector srcpos, vector srcsz, vector rgb, float alpha, optional float drawflag) drawsubpic = #328;
-float(vector position, vector size, string pic, vector srcPosition, vector srcSize, vector rgb, float alpha, float flag) drawsubpic = #328;
-// Nasty convoluted DP extension. Typically returns deltas instead
-// of positions. Use CSQC_InputEvent for such things in csqc mods
-vector() getmousepos = #344;
-// Looks up an input frame from the log, setting the input_*
-// globals accordingly.
-// The sequence number range used for prediction should normally
-// be servercommandframe < sequence <= clientcommandframe.
-// The sequence equal to clientcommandframe will change between
-// input frames
-float(float framenum) getinputstate = #345;
-// Perform the engine's standard player movement prediction upon
-// the given entity using the input_* globals to describe movement
-// this may or may not take a player ent
-void(...) runstandardplayerphysics = #347;
-// Sets the position of the view, as far as the audio subsystem is
-// concerned. This should be called once per CSQC_UpdateView as it
-// will otherwise revert to default. For reverbtype,
-// see setup_reverb or treat as 'underwater'
-// FTE = void(vector origin, vector forward, vector right, vector up, optional float reverbtype) SetListener = #351;
-void(vector origin, vector forward, vector right, vector up) SetListener = #351;
-
-// ----------------------------------------------------------------------
-// This is a bit of mess with DP (below) and FTE/QSS (further below)
-// Going in different directions with the CSQC standard
-// This is all about #330 returning an INT instead of a FLOAT
-// As getstatf has optional parameters it will still work fine with DP
-// Going with the FTE/QSS direction as it still works for DP
-// ----------------------------------------------------------------------
-//float(float stnum) getstatf = #330;
-// Can optionally take first bit and count
-//float(float stnum, ...) getstati = #331;
-
-// 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
-#define getstati_punf(stnum) (float)(__variant)getstati(stnum)
-int(float stnum) getstati = #330;
-#define getstatbits getstatf
-float(float stnum, optional float firstbit, optional float bitcount) getstatf = #331;
-
-// ----------------------------------------------------------------------
-// QSS (CSQC Lit) + DP/FTE extensions
-// ----------------------------------------------------------------------
-// Sets a model by precache index instead of by name.
-// Otherwise identical to setmodel.
-void(entity e, float mdlindex) setmodelindex = #333;
-// Part of DP_ENT_TRAILEFFECTNUM, FTE_SV_POINTPARTICLES
-// Precaches the named particle effect. If your effect name is of
-// the form 'foo.bar' then particles/foo.cfg will be loaded by the
-// client if foo.bar was not already defined.
-// Different engines will have different particle systems, this
-// specifies the QC API only
-float(string effectname) particleeffectnum = #335;
-// Part of FTE_SV_POINTPARTICLES
-// Draws the given effect between the two named points. If ent is
-// not world, distances will be cached in the entity in order to
-// avoid framerate dependancies. The entity is not otherwise used
-void(float effectnum, entity ent, vector start, vector end) trailparticles = #336;
-// Part of FTE_SV_POINTPARTICLES
-// Spawn a load of particles from the given effect at the given
-// point traveling or aiming along the direction specified.
-// The number of particles are scaled by the count argument.
-// For regular particles, the dir vector is multiplied by the
-// 'veladd' property (while orgadd will push the particles along it).
-// Decals will use it as a hint to align to the correct surface.
-// In both cases, it should normally be a unit vector, but other
-// lengths will still work. If it has length 0 then FTE will
-// assume downwards
-void(float effectnum, vector origin, optional vector dir, optional float count) pointparticles = #337;
-
-// conflicts with void(entity client, string s1) centerprint = #73;
-void(string s, ...) csqc_centerprint = #338;
-// Print into the center of the screen just as ssqc's centerprint
-// would appear
-void(string s, ...) cprint = #338;
-// This is identical to dprint except that it always prints
-// regardless of the developer cvar. Same number as in EXT_CSQC
-// Unconditionally print on the local system's console, even in
-// ssqc (doesn't care about the value of the developer cvar)
-void(string s, ...) print = #339;
-// Returns a hunam-readable name for the given keycode, as a tempstring
-string(float keynum) keynumtostring = #340;
-// Looks up the key name in the same way that the bind command would,
-// returning the keycode for that key
-float(string keyname) stringtokeynum = #341;
-// Returns the current binding for the given key (returning only the
-// command executed when no modifiers are pressed)
-string(float key, float bindmap) getkeybind_bindmap = #342;
-string(float keynum) getkeybind = #342;
-// Pass TRUE if you want the engine to release the mouse cursor
-// (absolute input events + touchscreen mode). Pass FALSE if you
-// want the engine to grab the cursor (relative input
-// events + standard looking). If the image name is specified,
-// the engine will use that image for a cursor (use an empty
-// string to clear it again), in a way that will not conflict
-// with the console. Images specified this way will be hardware
-// accelerated, if supported by the platform/port
-// QSS/FTE = void(float usecursor, optional string cursorimage, optional vector hotspot, optional float scale) setcursormode = #343;
-void(float usecursor) setcursormode = #343;
-// Reports the cursor mode this module previously attempted to use.
-// If 'effective' is true, reports the cursor mode currently active
-// (if was overriden by a different module which has precidence,
-// for instance, or if there is only a touchscreen and no mouse)
-float(float effective) getcursormode = #0;
-// Temporarily scales the player's mouse sensitivity based upon
-// something like zoom, avoiding potential cvar saving and thus
-// corruption
-void(float sens) setsensitivityscale = #346;
-// Look up a player's userinfo, to discover things like their name,
-// topcolor, bottomcolor, skin, team, *ver.
-// Also includes scoreboard info like frags, ping, pl, userid,
-// entertime, as well as voipspeaking and voiploudness
-string(float playernum, string keyname) getplayerkeyvalue = #348;
-// Cheaper version of getplayerkeyvalue that avoids the need for
-// so many tempstrings
-float(float playernum, string keyname, optional float assumevalue) getplayerkeyfloat = #0;
-// Returns if the client is currently playing a demo or not
-float() isdemo = #349;
-// Returns if the client is acting as the server (aka: listen server)
-float() isserver = #350;
-// Register the given console command, for easy console use.
-// Console commands that are later used will invoke CSQC_ConsoleCommand
-void(string cmdname) registercommand = #352;
-// Quickly check to see if the entity is currently free. This
-// function is only valid during the two-second non-reuse window,
-// after that it may give bad results. Try one second to make it
-// more robust.
-float(entity ent) wasfreed = #353;
-// Look up a key in the server's public serverinfo string
-string(string key) serverkey = #354;
-// Version of serverkey that returns the value as a float
-// (which avoids tempstrings)
-float(string key, optional float assumevalue) serverkeyfloat = #0;
-// Use proper case; refer to the id1 Write* functions!
-float() ReadByte = #360;
-float() ReadChar = #361;
-float() ReadShort = #362;
-float() ReadLong = #363;
-float() ReadCoord = #364;
-float() ReadAngle = #365;
-string() ReadString = #366;
-float() ReadFloat = #367;
-float() readentitynum = #368;
-// Replaces the title of the game window, as seen when
-// task switching or just running in windowed mode
-void(string newcaption) setwindowcaption = #0;
-

Return to the top of this page or return to the overview of this repo.

Diff qc/csqc/csqc_defsbuiltins.qc

diff --git a/qc/csqc/csqc_defsbuiltins.qc b/qc/csqc/csqc_defsbuiltins.qc
new file mode 100644
index 0000000..c1c7d0d
--- /dev/null
+++ b/qc/csqc/csqc_defsbuiltins.qc
@@ -0,0 +1,881 @@
+/*==============================================================================
+ BUILTIN FUNCTIONS (CSQC)
+==============================================================================*/
+
+//======================================================================
+// Portions of this have been copied from Arcane Dimensions' CSQC by Sock
+// (Simon OCallaghan). Rest has been sourced from fteextensions.qc as
+// needed. -- CEV
+//======================================================================
+
+// Custom types redefined as accessors
+// need to do this here as some of it is referenced below -- CEV
+#ifdef _ACCESSORS
+accessor strbuf:float;
+accessor searchhandle:float;
+accessor hashtable:float;
+accessor infostring:string;
+accessor filestream:float;
+#else
+#define strbuf float
+#define searchhandle float
+#define hashtable float
+#define infostring string
+#define filestream float
+#endif
+
+//----------------------------------------------------------------------
+// Vanilla Builtin list (reduced, so as to avoid conflicts)
+//----------------------------------------------------------------------
+void(vector) makevectors = #1;
+void(entity,vector) setorigin = #2;
+void(entity,string) setmodel = #3;
+void(entity,vector,vector) setsize = #4;
+float() random = #7;
+vector(vector) normalize = #9;
+void(string e) error = #10;
+void(string n) objerror = #11;
+float(vector) vlen = #12;
+entity() spawn = #14;
+void(entity e) remove = #15;
+// Precaches a model, making it known to clients and loading it from disk
+// if it has a .bsp extension. This builtin (strongly) should be called
+// during spawn functions. This must be called for each model name before
+// setmodel may use that model name.
+// Modelindicies precached in SSQC will always be positive. CSQC precaches
+// will be negative if they are not also on the server.
+string(string s) precache_model = #20;
+void(string,...) dprint = #25;
+string(float) ftos = #26;
+string(vector) vtos = #27;
+float(float n) rint = #36;
+float(float n) floor = #37;
+float(float n) ceil = #38;
+// Checks the given point to see what is there. Returns one of the SOLID_*
+// constants. Just because a spot is empty does not mean that the player
+// can stand there due to the size of the player - use tracebox for such tests.
+float(vector pos) pointcontents = #41;
+float(float n) fabs = #43;
+float(string) cvar = #45;
+void(string,...) localcmd = #46;
+entity(entity) nextent = #47;
+// Returns the angles (+x=UP) required to orient an entity to look in the
+// given direction. The 'up' argument is required if you wish to set a roll
+// angle, otherwise it will be limited to just monster-style turning.
+vector(vector fwd, optional vector up) vectoangles = #51;
+void(string var, string val) cvar_set = #72;
+
+//----------------------------------------------------------------------
+// Builtin list
+//----------------------------------------------------------------------
+
+// Returns the angles (+x=UP) required to orient an entity to look in the
+// given direction. The 'up' argument is required if you wish to set a roll
+// angle, otherwise it will be limited to just monster-style turning.
+vector(vector fwd, optional vector up) vectoangles2 = #51;
+float(float angle) sin = #60;
+float(float angle) cos = #61;
+float(float value) sqrt = #62;
+void(entity ent, entity ignore) tracetoss = #64;
+string(entity ent) etos = #65;
+// If e is world, returns the field 'key' from either the serverinfo or the
+// localinfo. If e is a player, returns the value of 'key' from the player's
+// userinfo string. There are a few special exceptions, like 'ip' which is not
+// technically part of the userinfo.
+string(entity e, string key) infokey = #80;
+// Identical to regular infokey, but returns it as a float instead of
+// creating new tempstrings.
+float(entity e, string key) infokeyf = #0;
+float(string) stof = #81;
+#define unicast(pl,reli) do{msg_entity = pl; multicast('0 0 0', reli?MULITCAST_ONE_R:MULTICAST_ONE);}while(0)
+// Once the MSG_MULTICAST network message buffer has been filled with data,
+// this builtin is used to dispatch it to the given target, filtering by pvs
+// for reduced network bandwidth.
+void(vector where, float set) multicast = #82;
+// Exactly like traceline, but a box instead of a uselessly thin point.
+// Acceptable sizes are limited by bsp format, q1bsp has strict acceptable
+// size values.
+void(vector start, vector mins, vector maxs, vector end,
+ float nomonsters, entity ent) tracebox = #90;
+
+// Returns a vector with random values. Each axis is independantly a value
+// between -1 and 1 inclusive.
+vector() randomvec = #91;
+vector(vector org) getlight = #92;
+// Creates a new cvar on the fly. If it does not already exist, it will be
+// given the specified value. If it does exist, this is a no-op.
+// This builtin has the limitation that it does not apply to configs or
+// commandlines. Such configs will need to use the set or seta commandx
+// causing this builtin to be a noop.
+// In engines that support it, you will generally find the autocvar feature
+// easier and more efficient to use.
+float(string cvarname, string defaultvalue) registercvar = #93;
+
+// Returns the lowest value of its arguments.
+float(float a, float b, ...) min = #94;
+
+// Returns the highest value of its arguments.
+float(float a, float b, ...) max = #95;
+
+// Returns val, unless minimum is higher, or maximum is less.
+float(float minimum, float val, float maximum) bound = #96;
+
+float(float value, float exp) pow = #97;
+
+
+// Equivelent to the find builtin, but instead of comparing strings
+// contents, this builtin compares the raw values. This builtin requires
+// multiple calls in order to scan all entities - set start to the previous
+// call's return value. world is returned when there are no more entities.
+#define findentity findfloat
+entity(entity start, .__variant fld, __variant match) findfloat = #98;
+
+// Checks for an extension by its name (eg: checkextension("FRIK_FILE")
+// says that its okay to go ahead and use strcat). Use
+// cvar("pr_checkextension") to see if this builtin exists.
+float(string extname) checkextension = #99;
+
+// Checks to see if the specified builtin is supported/mapped. This is
+// intended as a way to check for #0 functions, allowing for simple
+// single-builtin functions.
+float(__variant funcref) checkbuiltin = #0;
+
+//----------------------------------------------------------------------
+// 100-199 Range
+//----------------------------------------------------------------------
+
+// Looks to see if the named builtin is valid, and returns the builtin
+// number it exists at.
+float(string builtinname) builtin_find = #100;
+
+float(float value) anglemod = #102;
+
+// Opens a file, typically prefixed with "data/", for either read or
+// write access.
+filestream(string filename, float mode, optional float mmapminsize) fopen = #110;
+
+void(filestream fhandle) fclose = #111;
+// Reads a single line out of the file. The new line character is not
+// returned as part of the string. Returns the null string on EOF (use
+// if not(string) to easily test for this, which distinguishes it from
+// the empty string which is returned if the line being read is blank
+string(filestream fhandle) fgets = #112;
+
+// Writes the given string(s) into the file. For compatibility with fgets,
+// you should ensure that the string is terminated with a \n - this will
+// not otherwise be done for you. It is up to the engine whether dos or
+// unix line endings are actually written.
+void(filestream fhandle, string s, optional string s2, optional string s3,
+ optional string s4, optional string s5, optional string s6,
+ optional string s7) fputs = #113;
+
+// Changes the current position of the file, if specified.
+// Returns prior position, in bytes.
+#define ftell fseek // c-compat
+int(filestream fhandle, optional int newoffset) fseek = #0;
+
+float(string s) strlen = #114;
+string(string s1, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7, optional string s8) strcat = #115;
+string(string s, float start, float length) substring = #116;
+vector(string s) stov = #117;
+
+// Create a semi-permanent copy of a string that only becomes invalid
+// once strunzone is called on the string (instead of when the engine
+// assumes your string has left scope).
+string(string s, ...) strzone = #118;
+
+// Destroys a string that was allocated by strunzone. Further references
+// to the string MAY crash the game.
+void(string s) strunzone = #119;
+
+//----------------------------------------------------------------------
+// 200-299 FTE Range
+//----------------------------------------------------------------------
+float(float number, float quantity) bitshift = #218;
+void(vector org) te_lightningblood = #219;
+// Returns the 0-based offset of sub within the s1 string, or -1 if sub
+// is not in s1. If startidx is set, this builtin will ignore matches
+// before that 0-based offset.
+float(string s1, string sub, optional float startidx) strstrofs = #221;
+
+// Retrieves the character value at offset 'index'.
+float(string str, float index) str2chr = #222;
+
+// The input floats are considered character values, and are concatenated.
+string(float chr, ...) chr2str = #223;
+
+/* Converts quake chars in the input string amongst different representations.
+ * ccase specifies the new case for letters.
+ * 0: not changed.
+ * 1: forced to lower case.
+ * 2: forced to upper case.
+ * redalpha and redchars switch between colour ranges.
+ * 0: no change.
+ * 1: Forced white.
+ * 2: Forced red.
+ * 3: Forced gold(low) (numbers only).
+ * 4: Forced gold (high) (numbers only).
+ * 5+6: Forced to white and red alternately.
+ * You should not use this builtin in combination with UTF-8.
+ */
+string(float ccase, float redalpha, float redchars,
+ string str, ...) strconv = #224;
+
+// 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(float pad, string str1, ...) strpad = #225;
+
+// 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 old, string key, string value) infoadd = #226;
+
+// Reads a named value from an infostring. The returned value is a tempstring
+string(infostring info, string key) infoget = #227;
+
+// Compares up to 'len' chars in the two strings. s1ofs allows you to
+// treat s2 as a substring to compare against, or should be 0. Returns 0
+// if the two strings are equal, a negative value if s1 appears numerically
+// lower, and positive if s1 appears numerically higher.
+#define strcmp strncmp
+float(string s1, string s2, optional float len, optional float s1ofs,
+ optional float s2ofs) strncmp = #228;
+
+// Compares the two strings without case sensitivity. Returns 0 if they
+// are equal. The sign of the return value may be significant, but should
+// not be depended upon.
+float(string s1, string s2) strcasecmp = #229;
+
+// Compares up to 'len' chars in the two strings without case sensitivity.
+// s1ofs allows you to treat s2 as a substring to compare against, or should
+// be 0. Returns 0 if they are equal. The sign of the return value may be
+// significant, but should not be depended upon.
+float(string s1, string s2, float len, optional float s1ofs,
+ optional float s2ofs) strncasecmp = #230;
+
+// Trims the whitespace from the start+end of the string.
+string(string s) strtrim = #0;
+
+// Specifies what data to use in order to send various stats, in a
+// client-specific way. 'num' should be a value between 32 and 127,
+// other values are reserved. 'type' must be set to one of the EV_*
+// constants, one of EV_FLOAT, EV_STRING, EV_INTEGER, EV_ENTITY.
+// fld must be a reference to the field used, each player will be
+// sent only their own copy of these fields.
+void(float num, float type, .__variant fld) clientstat = #232;
+
+// Specifies what data to use in order to send various stats, in a
+// non-client-specific way. num and type are as in clientstat, name
+// however, is the name of the global to read in the form of a
+// string (pass "foo").
+void(float num, float type, string name) globalstat = #233;
+
+// Specifies what data to use in order to send various stats, in a
+// non-client-specific way. num and type are as in clientstat, address
+// however, is the address of the variable you would like to use (pass &foo).
+void(float num, float type, __variant *address) pointerstat = #0;
+
+// Returns if the given player's network buffer will take multiple network
+// frames in order to clear. If this builtin returns non-zero, you should
+// delay or reduce the amount of reliable (and also unreliable) data that
+// you are sending to that client.
+float(entity player) isbackbuffered = #234;
+
+void(vector org, float count) te_bloodqw = #239;
+float(float a, float n) mod = #245;
+
+// Converts the given string into a true integer. Base 8, 10, or 16 is
+// determined based upon the format of the string.
+int(string) stoi = #259;
+
+// Converts the passed true integer into a base10 string.
+string(int) itos = #260;
+
+// Reads a base-16 string (with or without 0x prefix) as an integer. Bugs
+// out if given a base 8 or base 10 string. :P
+int(string) stoh = #261;
+
+// Formats an integer as a base16 string, with leading 0s and no prefix.
+// Always returns 8 characters.
+string(int) htos = #262;
+
+// Converts the given float into a true integer without depending on
+// extended qcvm instructions.
+int(float) ftoi = #0;
+
+// Converts the given true integer into a float without depending on
+// extended qcvm instructions.
+float(int) itof = #0;
+
+#ifndef dotproduct
+#define dotproduct(v1,v2) ((vector)(v1)*(vector)(v2))
+#endif
+
+// Small helper function to calculate the crossproduct of two vectors.
+vector(vector v1, vector v2) crossproduct = #0;
+
+// Looks up a framegroup from a model by name, avoiding the need for
+// hardcoding. Returns -1 on error.
+float(float modidx, string framename) frameforname = #276;
+
+// Retrieves the duration (in seconds) of the specified framegroup.
+float(float modidx, float framenum) frameduration = #277;
+
+// Triggers a touch events between self and every SOLID_TRIGGER entity that
+// it is in contact with. This should typically just be the triggers touch
+// functions. Also optionally updates the origin of the moved entity.
+void(optional entity ent, optional vector neworigin) touchtriggers = #279;
+
+void(float buf, float fl) WriteFloat = #280;
+string(float modidx, float framenum) frametoname = #284;
+
+// Checks to see if the supplied name is a valid command, cvar, or
+// alias. Returns 0 if it does not exist.
+float(string name) checkcommand = #294;
+
+//======================================================================
+// This is a merge of three (DP/FTE/QSS) engine def files
+// dpextensions+csprogsdefs from SVN ICCULUS site (DP trunk)
+// fteexentions from triptohell website
+// qsextensions from QSS devkit on triptohell website
+//
+// CSQC range #300-#399
+//======================================================================
+
+//----------------------------------------------------------------------
+// DP/FTE extensions ONLY
+//----------------------------------------------------------------------
+// Forgets all rentities, polygons, and temporary dlights.
+// Resets all view properties to their default values.
+void() clearscene = #300;
+void(float mask) addentities = #301;
+// Copies the entity fields into a new rentity for
+// later rendering via addscene
+void(entity ent) addentity = #302;
+// Allows you to override default view properties like
+// viewport, fov, and whether the engine hud will be drawn.
+// Different VF_ values have slightly different arguments,
+// some are vectors, some floats.
+float(float property, ...) setproperty = #303;
+// Draws all entities, polygons, and particles on the rentity list
+// (which were added via addentities or addentity), using the various
+// view properties set via setproperty. There is no ordering dependancy.
+// The scene must generally be cleared again before more entities
+// are added, as entities will persist even over to the next frame.
+// You may call this builtin multiple times per frame, but should
+// only be called from CSQC_UpdateView.
+void() renderscene = #304;
+// Adds a temporary dlight, ready to be drawn via addscene.
+// Cubemap orientation will be read from v_forward/v_right/v_up.
+void(vector org, float radius, vector lightcolours) adddynamiclight = #305;
+void(vector org, float radius, vector lightcolours, float style,
+ string cubemapname, float pflags) adddynamiclight2 = #305;
+// Specifies the shader to use for the following polygons, along
+// with optional flags.
+// If is2d, the polygon will be drawn as soon as the EndPolygon
+// call is made, rather than waiting for renderscene. This allows
+// complex 2d effects.
+// FTE = void(string texturename, optional float flags,
+// optional float is2d) R_BeginPolygon = #306;
+void(string texturename, float flag, ...) R_BeginPolygon = #306;
+// Specifies a polygon vertex with its various properties
+void(vector org, vector texcoords, vector rgb,
+ float alpha) R_PolygonVertex = #307;
+// Ends the current polygon. At least 3 verticies must have been
+// specified. You do not need to call beginpolygon if you wish to
+// draw another polygon with the same shader
+void() R_EndPolygon = #308;
+// Retrieve a currently-set (typically view) property, allowing you
+// to read the current viewport or other things. Due to cheat protection,
+// certain values may be unretrievable
+// define = FTE version of DP version
+#define getviewprop getproperty
+float(float property) getproperty = #309;
+vector(float property) getpropertyvec = #309;
+// Transform a 2d screen-space point (with depth) into a 3d world-space
+// point, according the various origin+angle+fov etc settings set via
+// setproperty
+vector (vector v) cs_unproject = #310;
+// Transform a 3d world-space point into a 2d screen-space point,
+// according the various origin+angle+fov etc settings set via
+// setproperty
+vector (vector v) cs_project = #311;
+// Draws a 2d line between the two 2d points
+void(float width, vector pos1, vector pos2, vector rgb, float alpha,
+ float flag) drawline = #315;
+// Tells the engine that the image is no longer needed.
+// The image will appear to be new the next time its needed
+void(string name) freepic = #319;
+// Draws the specified string without using any markup at all,
+// even in engines that support it.
+// If UTF-8 is globally enabled in the engine, then that encoding
+// is used (without additional markup), otherwise it is raw quake chars.
+// Software engines may assume a size of '8 8 0', rgb='1 1 1',
+// alpha=1, flag&3=0, but it is not an error to draw out of the screen.
+float(vector position, string text, vector scale, vector rgb,
+ float alpha, float flag) drawstring = #321;
+// 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.
+string(float stnum) getstats = #332;
+// Retrieves the name of the model based upon a precache index.
+// This can be used to reduce csqc network traffic by enabling
+// model matching
+string(float mdlindex) modelnameforindex = #334;
+// Looks up a named font slot. Matches the actual font name as a last resort.
+// find font by fontname and return it's index
+float findfont(string s) = #356;
+float loadfont(string fontname, string fontmaps, string sizes, float slot, float fix_scale, float fix_voffset) = #357;
+
+//----------------------------------------------------------------------
+// QSS (CSQC Lit) + DP/FTE extensions
+//----------------------------------------------------------------------
+// Checks to see if the image is currently loaded.
+// Engines might lie, or cache between maps.
+float(string name) iscachedpic = #316;
+// Forces the engine to load the named image. If trywad is specified,
+// the specified name must any lack path and extension.
+string(string name, optional float trywad) precache_pic = #317;
+// Returns the dimensions of the named image. Images specified
+// with .lmp should give the original .lmp's dimensions even if
+// texture replacements use a different resolution.
+// define = FTE version of DP version
+#define drawgetimagesize draw_getimagesize
+vector(string picname) draw_getimagesize = #318;
+// Draw the given quake character at the given position.
+// If flag&4, the function will consider the char to be a unicode
+// char instead (or display as a ? if outside the 32-127 range).
+// size should normally be something like '8 8 0'.
+// rgb should normally be '1 1 1' and alpha normally 1.
+// Software engines may assume the named defaults.
+// Note that ALL text may be rescaled on the X axis due to
+// variable width fonts. The X axis may even be ignored completely.
+float(vector position, float character, vector scale, vector rgb,
+ float alpha, float flag) drawcharacter = #320;
+// Draws an shader within the given 2d screen box. Software engines
+// may omit support for rgb+alpha, but must support rescaling,
+// and must clip to the screen without crashing
+// flag = draw method; 0=normal, 1=additive, 2=modulate, 3=modulate2
+float(vector position, string pic, vector size, vector rgb,
+ float alpha, float flag) drawpic = #322;
+// Draws a solid block over the given 2d box, with given colour,
+// alpha, and blend mode (specified via flags).
+// flags&3=0 simple blend flags&3=1 additive blend
+float(vector position, vector size, vector rgb,
+ float alpha, float flag) drawfill = #323;
+// Specifies a 2d clipping region (aka: scissor test).
+// 2d draw calls will all be clipped to this 2d box,
+// the area outside will not be modified by any
+// 2d draw call (even 2d polygons).
+void(float x, float y, float width, float height) drawsetcliparea = #324;
+// Reverts the scissor/clip area to the whole screen
+void(void) drawresetcliparea = #325;
+// Draws a string, interpreting markup and recolouring as appropriate
+// QSS/FTE = drawstring, DP = drawcolorcodedstring/drawcolorcodedstring2
+// float(vector position, string text, vector size, vector rgb, float alpha, float drawflag) drawstring = #326;
+float(vector position, string text, vector scale,
+ float alpha, float flag) drawcolorcodedstring = #326;
+vector(vector position, string text, vector scale, vector rgb,
+ float alpha, float flag) drawcolorcodedstring2 = #326;
+// Calculates the width of the screen in virtual pixels.
+// If usecolours is 1, markup that does not affect the string
+// width will be ignored. Will always be decoded as UTF-8 if
+// UTF-8 is globally enabled.
+// If the char size is not specified, '8 8 0' will be assumed
+// float(string text, float usecolours, optional vector fontsize) stringwidth = #327;
+// QSS/FTE = float(string text, float usecolours, optional vector fontsize) stringwidth = #327;
+float(string text, float allowColorCodes, vector size) stringwidth = #327;
+// Draws a rescaled subsection of an image to the screen
+// QSS/FTE = void(vector pos, vector sz, string pic, vector srcpos, vector srcsz, vector rgb, float alpha, optional float drawflag) drawsubpic = #328;
+float(vector position, vector size, string pic, vector srcPosition,
+ vector srcSize, vector rgb, float alpha, float flag) drawsubpic = #328;
+// Nasty convoluted DP extension. Typically returns deltas instead
+// of positions. Use CSQC_InputEvent for such things in csqc mods
+vector() getmousepos = #344;
+// Looks up an input frame from the log, setting the input_*
+// globals accordingly.
+// The sequence number range used for prediction should normally
+// be servercommandframe < sequence <= clientcommandframe.
+// The sequence equal to clientcommandframe will change between
+// input frames
+float(float framenum) getinputstate = #345;
+// Perform the engine's standard player movement prediction upon
+// the given entity using the input_* globals to describe movement
+// this may or may not take a player ent
+void(...) runstandardplayerphysics = #347;
+// Sets the position of the view, as far as the audio subsystem is
+// concerned. This should be called once per CSQC_UpdateView as it
+// will otherwise revert to default. For reverbtype,
+// see setup_reverb or treat as 'underwater'
+// FTE = void(vector origin, vector forward, vector right, vector up,
+// optional float reverbtype) SetListener = #351;
+void(vector origin, vector forward, vector right, vector up) SetListener = #351;
+
+//----------------------------------------------------------------------
+// This is a bit of mess with DP (below) and FTE/QSS (further below)
+// Going in different directions with the CSQC standard
+// This is all about #330 returning an INT instead of a FLOAT
+// As getstatf has optional parameters it will still work fine with DP
+// Going with the FTE/QSS direction as it still works for DP
+//----------------------------------------------------------------------
+//float(float stnum) getstatf = #330;
+// Can optionally take first bit and count
+//float(float stnum, ...) getstati = #331;
+
+// 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
+#define getstati_punf(stnum) (float)(__variant)getstati(stnum)
+int(float stnum) getstati = #330;
+#define getstatbits getstatf
+float(float stnum, optional float firstbit,
+ optional float bitcount) getstatf = #331;
+
+//----------------------------------------------------------------------
+// QSS (CSQC Lit) + DP/FTE extensions
+//----------------------------------------------------------------------
+// Sets a model by precache index instead of by name.
+// Otherwise identical to setmodel.
+void(entity e, float mdlindex) setmodelindex = #333;
+// Part of DP_ENT_TRAILEFFECTNUM, FTE_SV_POINTPARTICLES
+// Precaches the named particle effect. If your effect name is of
+// the form 'foo.bar' then particles/foo.cfg will be loaded by the
+// client if foo.bar was not already defined.
+// Different engines will have different particle systems, this
+// specifies the QC API only
+float(string effectname) particleeffectnum = #335;
+// Part of FTE_SV_POINTPARTICLES
+// Draws the given effect between the two named points. If ent is
+// not world, distances will be cached in the entity in order to
+// avoid framerate dependancies. The entity is not otherwise used
+void(float effectnum, entity ent, vector start, vector end)
+ trailparticles = #336;
+// Part of FTE_SV_POINTPARTICLES
+// Spawn a load of particles from the given effect at the given
+// point traveling or aiming along the direction specified.
+// The number of particles are scaled by the count argument.
+// For regular particles, the dir vector is multiplied by the
+// 'veladd' property (while orgadd will push the particles along it).
+// Decals will use it as a hint to align to the correct surface.
+// In both cases, it should normally be a unit vector, but other
+// lengths will still work. If it has length 0 then FTE will
+// assume downwards
+void(float effectnum, vector origin,
+ optional vector dir, optional float count) pointparticles = #337;
+
+// conflicts with void(entity client, string s1) centerprint = #73;
+void(string s, ...) csqc_centerprint = #338;
+// Print into the center of the screen just as ssqc's centerprint
+// would appear
+void(string s, ...) cprint = #338;
+// This is identical to dprint except that it always prints
+// regardless of the developer cvar. Same number as in EXT_CSQC
+// Unconditionally print on the local system's console, even in
+// ssqc (doesn't care about the value of the developer cvar)
+void(string s, ...) print = #339;
+// Returns a hunam-readable name for the given keycode, as a tempstring
+string(float keynum) keynumtostring = #340;
+// Looks up the key name in the same way that the bind command would,
+// returning the keycode for that key
+float(string keyname) stringtokeynum = #341;
+// Returns the current binding for the given key (returning only the
+// command executed when no modifiers are pressed)
+string(float key, float bindmap) getkeybind_bindmap = #342;
+string(float keynum) getkeybind = #342;
+// Pass TRUE if you want the engine to release the mouse cursor
+// (absolute input events + touchscreen mode). Pass FALSE if you
+// want the engine to grab the cursor (relative input
+// events + standard looking). If the image name is specified,
+// the engine will use that image for a cursor (use an empty
+// string to clear it again), in a way that will not conflict
+// with the console. Images specified this way will be hardware
+// accelerated, if supported by the platform/port
+// QSS/FTE = void(float usecursor, optional string cursorimage,
+// optional vector hotspot, optional float scale) setcursormode = #343;
+void(float usecursor) setcursormode = #343;
+// Reports the cursor mode this module previously attempted to use.
+// If 'effective' is true, reports the cursor mode currently active
+// (if was overriden by a different module which has precidence,
+// for instance, or if there is only a touchscreen and no mouse)
+float(float effective) getcursormode = #0;
+// Temporarily scales the player's mouse sensitivity based upon
+// something like zoom, avoiding potential cvar saving and thus
+// corruption
+void(float sens) setsensitivityscale = #346;
+// Look up a player's userinfo, to discover things like their name,
+// topcolor, bottomcolor, skin, team, *ver.
+// Also includes scoreboard info like frags, ping, pl, userid,
+// entertime, as well as voipspeaking and voiploudness
+string(float playernum, string keyname) getplayerkeyvalue = #348;
+// Cheaper version of getplayerkeyvalue that avoids the need for
+// so many tempstrings
+float(float playernum, string keyname,
+ optional float assumevalue) getplayerkeyfloat = #0;
+// Returns if the client is currently playing a demo or not
+float() isdemo = #349;
+// Returns if the client is acting as the server (aka: listen server)
+float() isserver = #350;
+// Register the given console command, for easy console use.
+// Console commands that are later used will invoke CSQC_ConsoleCommand
+void(string cmdname) registercommand = #352;
+// Quickly check to see if the entity is currently free. This
+// function is only valid during the two-second non-reuse window,
+// after that it may give bad results. Try one second to make it
+// more robust.
+float(entity ent) wasfreed = #353;
+// Look up a key in the server's public serverinfo string
+string(string key) serverkey = #354;
+// Version of serverkey that returns the value as a float
+// (which avoids tempstrings)
+float(string key, optional float assumevalue) serverkeyfloat = #0;
+// Use proper case; refer to the id1 Write* functions!
+float() ReadByte = #360;
+float() ReadChar = #361;
+float() ReadShort = #362;
+float() ReadLong = #363;
+float() ReadCoord = #364;
+float() ReadAngle = #365;
+string() ReadString = #366;
+float() ReadFloat = #367;
+float() readentitynum = #368;
+// Reads a 32bit int without any conversions to float, otherwise
+// interchangable with readlong.
+int() ReadInt = #0:readint;
+
+// Replaces the title of the game window, as seen when
+// task switching or just running in windowed mode
+void(string newcaption) setwindowcaption = #0;
+
+// Specifies a per-modelindex callback to listen for engine-networking
+// entity updates. Such entities are automatically interpolated by the
+// engine (unless flags specifies not to).
+// The various standard entity fields will be overwritten each frame
+// before the updatecallback function is called.
+float(string modelname, float(float isnew) updatecallback, float flags) deltalisten = #371;
+
+//----------------------------------------------------------------------
+// 400-499 DP Range
+//----------------------------------------------------------------------
+// Copies all fields from one entity to another.
+entity(entity from, optional entity to) copyentity = #400;
+
+// Changes a player's colours. The bits 0-3 are the lower/trouser colour,
+// bits 4-7 are the upper/shirt colours.
+void(entity ent, float colours) setcolors = #401;
+
+entity(.string field, string match) findchain = #402;
+entity(.float fld, float match) findchainfloat = #403;
+void(vector org, vector dir, float count) te_blood = #405;
+void(vector mincorner, vector maxcorner, vector vel,
+ float howmany, float color) te_particlerain = #409;
+void(vector mincorner, vector maxcorner, vector vel,
+ float howmany, float color) te_particlesnow = #410;
+void(vector org, optional float count) te_gunshot = #418;
+void(vector org) te_spike = #419;
+void(vector org) te_superspike = #420;
+void(vector org) te_explosion = #421;
+void(vector org) te_tarexplosion = #422;
+void(vector org) te_wizspike = #423;
+void(vector org) te_knightspike = #424;
+void(vector org) te_lavasplash = #425;
+void(vector org) te_teleport = #426;
+void(vector org, float color, float colorlength) te_explosion2 = #427;
+void(entity own, vector start, vector end) te_lightning1 = #428;
+void(entity own, vector start, vector end) te_lightning2 = #429;
+void(entity own, vector start, vector end) te_lightning3 = #430;
+void(entity own, vector start, vector end) te_beam = #431;
+void(vector dir) vectorvectors = #432;
+float(entity e, float s) getsurfacenumpoints = #434;
+vector(entity e, float s, float n) getsurfacepoint = #435;
+vector(entity e, float s) getsurfacenormal = #436;
+string(entity e, float s) getsurfacetexture = #437;
+float(entity e, vector p) getsurfacenearpoint = #438;
+vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
+void(entity e, string s) clientcommand = #440;
+float(string s) tokenize = #441;
+string(float n) argv = #442;
+float() argc = #0;
+void(entity e, entity tagentity, string tagname) setattachment = #443;
+
+// initiate a filesystem scan based upon filenames. Be sure to call
+// search_end on the returned handle.
+searchhandle(string pattern, optional float caseinsensitive,
+ optional float quiet) search_begin = #444;
+
+void(searchhandle handle) search_end = #445;
+
+// Retrieves the number of files that were found.
+float(searchhandle handle) search_getsize = #446;
+
+// Retrieves name of one of the files that was found by the initial search.
+string(searchhandle handle, float num) search_getfilename = #447;
+
+// Retrieves the size of one of the files that was found by the initial search.
+float(searchhandle handle, float num) search_getfilesize = #0;
+
+// Retrieves modification time of one of the files in %Y-%m-%d %H:%M:%S format.
+string(searchhandle handle, float num) search_getfilemtime = #0;
+
+string(string cvarname) cvar_string = #448;
+entity(entity start, .float fld, float match) findflags = #449;
+entity(.float fld, float match) findchainflags = #450;
+void(entity player) dropclient = #453;
+
+// Spawns a dummy player entity.
+// Note that such dummy players will be carried from one map to the next.
+// Warning: DP_SV_CLIENTCOLORS DP_SV_CLIENTNAME are not implemented in
+// quakespasm, so use KRIMZON_SV_PARSECLIENTCOMMAND's clientcommand builtin
+// to change the bot's name/colours/skin/team/etc, in the same way that
+// clients would ask.
+entity() spawnclient = #454;
+
+float(entity client) clienttype = #455;
+void(float target, string str) WriteUnterminatedString = #456;
+entity(float entnum) edict_num = #459;
+strbuf() buf_create = #460;
+void(strbuf bufhandle) buf_del = #461;
+float(strbuf bufhandle) buf_getsize = #462;
+void(strbuf bufhandle_from, strbuf bufhandle_to) buf_copy = #463;
+void(strbuf bufhandle, float sortprefixlen, float backward) buf_sort = #464;
+string(strbuf bufhandle, string glue) buf_implode = #465;
+string(strbuf bufhandle, float string_index) bufstr_get = #466;
+void(strbuf bufhandle, float string_index, string str) bufstr_set = #467;
+float(strbuf bufhandle, string str, float order) bufstr_add = #468;
+void(strbuf bufhandle, float string_index) bufstr_free = #469;
+float(float s) asin = #471;
+float(float c) acos = #472;
+float(float t) atan = #473;
+float(float c, float s) atan2 = #474;
+float(float a) tan = #475;
+
+// Returns the number of characters in the string after any colour codes
+// or other markup has been parsed.
+float(string s) strlennocol = #476;
+
+// Flattens any markup/colours, removing them from the string.
+string(string s) strdecolorize = #477;
+
+string(float uselocaltime, string format, ...) strftime = #478;
+float(string s, string separator1, ...) tokenizebyseparator = #479;
+string(string s) strtolower = #480;
+string(string s) strtoupper = #481;
+string(string s) cvar_defstring = #482;
+void(vector origin, string sample, float volume,
+ float attenuation) pointsound = #483;
+string(string search, string replace, string subject) strreplace = #484;
+string(string search, string replace, string subject) strireplace = #485;
+vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
+float(float caseinsensitive, string s, ...) crc16 = #494;
+float(string name) cvar_type = #495;
+
+// Gives the number of named entity fields. Note that this is not the size
+// of an entity, but rather just the number of unique names (ie: vectors
+// use 4 names rather than 3).
+float() numentityfields = #496;
+
+// Find a field index by name.
+float(string fieldname) findentityfield = #0;
+
+// Returns a field value that can be directly used to read entity fields.
+// Be sure to validate the type with entityfieldtype before using.
+typedef .__variant field_t;
+field_t(float fieldnum) entityfieldref = #0;
+
+// Retrieves the name of the given entity field.
+string(float fieldnum) entityfieldname = #497;
+
+// Provides information about the type of the field specified by the field num.
+// Returns one of the EV_ values.
+float(float fieldnum) entityfieldtype = #498;
+
+string(float fieldnum, entity ent) getentityfieldstring = #499;
+
+//----------------------------------------------------------------------
+// 500-599 Range
+//----------------------------------------------------------------------
+float(float fieldnum, entity ent, string s) putentityfieldstring = #500;
+
+// Returns the pak file name that contains the file specified.
+// progs/player.mdl will generally return something like 'pak0.pak'.
+// If makereferenced is true, clients will automatically be told that
+// the returned package should be pre-downloaded and used, even if
+// allow_download_refpackages is not set.
+string(string filename, optional float makereferenced) whichpack = #503;
+
+string(string in) uri_escape = #510;
+string(string in) uri_unescape = #511;
+float(entity ent) num_for_edict = #512;
+
+// Tokenize a string exactly as the console's tokenizer would do so.
+// The regular tokenize builtin became bastardized for convienient
+// string parsing, which resulted in a large disparity that can be
+// exploited to bypass checks implemented in a naive
+// SV_ParseClientCommand function, therefore you can use this builtin
+// to make sure it exactly matches.
+float(string str) tokenize_console = #514;
+
+// Returns the character index that the tokenized arg started at.
+float(float idx) argv_start_index = #515;
+
+// Returns the character index that the tokenized arg stopped at.
+float(float idx) argv_end_index = #516;
+
+// Retrieves the description of a cvar, which might be useful for tooltips
+// or help files. This may still not be useful.
+string(string cvarname) cvar_description = #518;
+
+float(optional float timetype) gettime = #519;
+
+// Returns a list of keycodes that perform the given console command in a
+// format that can only be parsed via tokenize (NOT tokenize_console).
+// This always returns at least two values - if only one key is actually
+// bound, -1 will be returned. The bindmap argument is listed for
+// compatibility with dp-specific defs, but is ignored in FTE.
+string(string command, optional float bindmap) findkeysforcommand = #521;
+
+// Returns a list of key bindings in keyname format instead of keynums.
+// Use tokenize to parse. This list may contain modifiers. May return
+// large numbers of keys.
+string(string command, optional float bindmap) findkeysforcommandex = #0;
+
+// Determines the logarithm of the input value according to the specified base.
+// This can be used to calculate how much something was shifted by.
+float(float v, optional float base) log = #532;
+
+// Appends the named file into a string buffer (which must have been
+// created in advance). The return value merely says whether the file
+// was readable.
+float(string filename, strbuf bufhandle) buf_loadfile = #535;
+
+// Writes the contents of a string buffer onto the end of the supplied
+// filehandle (you must have already used fopen). Additional optional
+// arguments permit you to constrain the writes to a subsection of the
+// stringbuffer.
+float(filestream filehandle, strbuf bufhandle, optional float startpos,
+ optional float numstrings) buf_writefile = #536;
+
+//----------------------------------------------------------------------
+// 600-699 Range
+//----------------------------------------------------------------------
+
+// Invokes the named function. The function name is always passed as the
+// last parameter and must always be present. The others are passed to
+// the named function as-is
+void(.../*, string funcname*/) callfunction = #605;
+
+// Returns true if the named function exists and can be called with the
+// callfunction builtin.
+float(string s) isfunction = #607;
+
+// Reads a single entity's fields into an already-spawned entity.
+// s should contain field pairs like in a saved game: {"foo1" "bar" "foo2" "5"}.
+// Returns <=0 on failure, otherwise returns the offset in the string that
+// was read to.
+float(entity e, string s, optional float offset) parseentitydata = #613;
+
+string(string fmt, ...) sprintf = #627;
+float(entity e, float s) getsurfacenumtriangles = #628;
+vector(entity e, float s, float n) getsurfacetriangle = #629;
+

Return to the top of this page or return to the overview of this repo.

Diff qc/csqc/csqc_defsclient.qc

diff --git a/qc/csqc/csqc_defsclient.qc b/qc/csqc/csqc_defsclient.qc
index 23e7f4b..ed9344b 100644
--- a/qc/csqc/csqc_defsclient.qc
+++ b/qc/csqc/csqc_defsclient.qc
@@ -7,79 +7,6 @@
// Requires csqc_defs.qc file for 300-399 range commands
//
//======================================================================
-// Some extra defs (csqc/csqc_simple)
-#ifndef CSQC
-#define CSQC
-#endif
-#ifndef CSQC_SIMPLE
-#define CSQC_SIMPLE
-#endif
-// Suppress reference errors
-#pragma noref 1
-
-//----------------------------------------------------------------------
-// Mostly stuff from GLOBALVARS_T C STRUCTURE
-//----------------------------------------------------------------------
-entity self,other,world;
-float time,frametime,force_retouch;
-string mapname;
-float deathmatch,coop,teamplay,serverflags,total_secrets,total_monsters,found_secrets,killed_monsters,parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8, parm9, parm10, parm11, parm12, parm13, parm14, parm15, parm16;
-vector v_forward, v_up, v_right;
-float trace_allsolid,trace_startsolid,trace_fraction;
-vector trace_endpos,trace_plane_normal;
-float trace_plane_dist;
-entity trace_ent;
-float trace_inopen,trace_inwater;
-entity msg_entity;
-void() main,StartFrame,PlayerPreThink,PlayerPostThink,ClientKill,ClientConnect,PutClientInServer,ClientDisconnect,SetNewParms,SetChangeParms;
-void end_sys_globals;
-.float modelindex;
-.vector absmin, absmax;
-.float ltime,movetype,solid;
-.vector origin,oldorigin,velocity,angles,avelocity,punchangle;
-.string classname,model;
-.float frame,skin,effects;
-.vector mins, maxs,size;
-.void() touch,use,think,blocked;
-.float nextthink;
-.entity groundentity;
-.float health,frags,weapon;
-.string weaponmodel;
-.float weaponframe,currentammo,ammo_shells,ammo_nails,ammo_rockets,ammo_cells,items,takedamage;
-.entity chain;
-.float deadflag;
-.vector view_ofs;
-.float button0,button1,button2,impulse,fixangle;
-.vector v_angle;
-.float idealpitch;
-.string netname;
-.entity enemy;
-.float flags,colormap,team,max_health,teleport_time,armortype,armorvalue,waterlevel,watertype,ideal_yaw,yaw_speed;
-.entity aiment,goalentity;
-.float spawnflags;
-.string target,targetname;
-.float dmg_take,dmg_save;
-.entity dmg_inflictor,owner;
-.vector movedir;
-.string message;
-.float sounds;
-.string noise, noise1, noise2, noise3;
-void end_sys_fields;
-
-// Custom types redefined as accessors
-#ifdef _ACCESSORS
-accessor strbuf:float;
-accessor searchhandle:float;
-accessor hashtable:float;
-accessor infostring:string;
-accessor filestream:float;
-#else
-#define strbuf float
-#define searchhandle float
-#define hashtable float
-#define infostring string
-#define filestream float
-#endif

void(string cmd) SV_ParseClientCommand;
void() EndFrame;
@@ -92,29 +19,89 @@ float(float evtype, float scanx, float chary, float devid) CSQC_InputEvent;
float(float save, float take, vector dir) CSQC_Parse_Damage;
float(string cmdstr) CSQC_ConsoleCommand;
void() CSQC_Parse_Event;
+void(float isnew) CSQC_Ent_Update;

-float player_localnum; // Player slot that is assigned to us
+// globals
+float nocsqc; // CSQC State (0=on, 1=off)
+float detectDP; // Detect DP engine (using wrapper)
+float sitems; // CSQC copy of .items
+float sitems2; // CSQC copy of .items2 (or serverflags)
+float sweapon; // CSQC copy of .weapon
+float shealth; // CSQC copy of .health

-const float FALSE = 0;
-const float TRUE = 1;
-const float IE_KEYDOWN = 0;
-const float IE_KEYUP = 1;
-const float IE_MOUSEDELTA = 2;
-const float IE_MOUSEABS = 3;
-const float IE_JOYAXIS = 6;
+float painfinishtime; // Track player damage for hud face
+
+float intermission; // in intermission
+float intermission_time; // when the intermission started
+
+float numclientseats; // coop or splitscreen?
+float maxclients; // maximum players possible on this server
+float cltime; // increases regardless of pause or game speed
+
+float player_localnum; // Player slot that is assigned to us
+float player_localentnum; // Entity number that csqc is attached to
+
+float sb_showscores; // Show lower tab scores
+
+// This is the input-frame sequence. frames < clientcommandframe have been
+// sent to the server. frame==clientcommandframe is still being generated
+// and can still change.
+float clientcommandframe;
+// This is the input-frame that was last acknowledged by the server.
+// Input frames greater than this should be applied to the player's entity.
+float servercommandframe;
+
+string CSQC_PING = "csqcping"; // Test command to check if CSCQ alive
+
+float input_timelength; // from fteextensions.qc -- CEV
+vector input_angles; /* +x=DOWN */
+vector input_movevalues;
+float input_buttons;
+float input_impulse;
+
+vector VEC_ORIGIN = '0 0 0';
+vector VEC_HULL_MIN = '-16 -16 -24';
+vector VEC_HULL_MAX = '16 16 32';
+
+vector VEC_HULL2_MIN = '-32 -32 -24';
+vector VEC_HULL2_MAX = '32 32 64';
+
+entity viewentity; // camera -- CEV
+vector vieworg; // origin for viewentity -- CEV
+vector view_angles; // +x=DOWN
+
+entity player_local; // handle to the local player entity
+float player_localentnum;
+
+vector player_org; // prediction globals; from CSQCTest -- CEV
+vector player_vel;
+float player_pmflags;
+float player_sequence;
+float player_step;
+float player_steptime;
+float player_step_oldz;
+vector pmove_error;
+float pmove_errortime;
+float pmove_frame;

//----------------------------------------------------------------------
// Extra fields
//----------------------------------------------------------------------
.float gravity;
-//.float items2; /*if defined, overrides serverflags for displaying runes on the hud*/
-.float traileffectnum; /*can also be set with 'traileffect' from a map editor*/
-.float emiteffectnum; /*can also be set with 'traileffect' from a map editor*/
-.vector movement; /*describes which forward/right/up keys the player is holidng*/
-.entity viewmodelforclient; /*attaches this entity to the specified player's view. invisible to other players*/
-.float scale; /*rescales the etntiy*/
-.float alpha; /*entity opacity*/
-.vector colormod; /*tints the entity's colours*/
+// if defined, overrides serverflags for displaying runes on the hud
+//.float items2;
+// can also be set with 'traileffect' from a map editor
+//.float traileffectnum;
+// can also be set with 'traileffect' from a map editor
+.float emiteffectnum;
+// describes which forward/right/up keys the player is holidng
+.vector movement;
+// attaches this entity to the specified player's view.
+// invisible to other players
+.entity viewmodelforclient;
+.float scale; // rescales the etntiy
+.float alpha; // entity opacity
+.vector colormod; // tints the entity's colours
.entity tag_entity;
.float tag_index;
.float button3;
@@ -123,456 +110,208 @@ const float IE_JOYAXIS = 6;
.float button6;
.float button7;
.float button8;
-.float viewzoom; /*rescales the user's fov*/
-.float modelflags; /*provides additional modelflags to use (effects&EF_NOMODELFLAGS to replace the original model's)*/
+.float viewzoom; // rescales the user's fov
+
+// provides additional modelflags to use (effects&EF_NOMODELFLAGS to replace
+// the original model's)
+.float modelflags;
+
+.float pmove_flags; // custom movement flags -- CEV
+.float jump_time; // last time the player jumped -- CEV
+.float land_time; // last time the player landed onground -- CEV
+.vector primal_velocity; // velocity before engine physics -- CEV
+.float primal_speed; // speed before engine physics -- CEV
+.float boost_time; // time to simulate low friction -- CEV
+.void() customphysics;
+
+.float ext_csqc; // Client Server Quake C HUD alive!
+
+.float entnum; // The entity number as its known on the server
+
+// Called by addentities after the filter and before the entity is actually
+// drawn. Do your interpolation and animation in here. Should return one of
+// the PREDRAW_* constants.
+.float() predraw;
+
+.float renderflags;
+
+// The model name that was set via setmodel, in theory. Often, this is
+// cleared to null to prevent the engine from being seen by clients
+// while not changing modelindex. This behaviour allows inline models
+// to remain solid yet be invisible.
+.string model;
+// The current frame the entity is meant to be displayed in. In CSQC,
+// note the lerpfrac and frame2 fields as well. if it specifies a
+// framegroup, the framegroup will autoanimate in ssqc, but not in csqc.
+.float frame;
+// The absolute time into the animation/framegroup specified by .frame.
+.float frame1time;
+// The alternative frame. Visible only when lerpfrac is set to 1.
+.float frame2;
+// The absolute time into the animation/framegroup specified by .frame2.
+.float frame2time;
+.float frameold;
+// If 0, use frame1 only. If 1, use frame2 only.
+// Mix them together for values between.
+.float lerpfrac;
+.float lerptime;
+
+// .float oldframe;
+
+.void() removefunc;
+.string oldskin;
+
+.float drawmask; // Acts as a filter in the addentities call.

//----------------------------------------------------------------------
-// Supported Extension Constants
+// Constants
//----------------------------------------------------------------------
-const float MOVETYPE_FOLLOW = 12;
-const float SOLID_CORPSE = 5;
-const float CLIENTTYPE_DISCONNECT = 0;
-const float CLIENTTYPE_REAL = 1;
-const float CLIENTTYPE_BOT = 2;
-const float CLIENTTYPE_NOTCLIENT = 3;
-const float EF_NOSHADOW = 0x1000;
-const float EF_NOMODELFLAGS = 0x800000; /*the standard modelflags from the model are ignored*/
-const float MF_ROCKET = 0x1;
-const float MF_GRENADE = 0x2;
-const float MF_GIB = 0x4;
-const float MF_ROTATE = 0x8;
-const float MF_TRACER = 0x10;
-const float MF_ZOMGIB = 0x20;
-const float MF_TRACER2 = 0x40;
-const float MF_TRACER3 = 0x80;
-const float MSG_MULTICAST = 4;
-const float MULTICAST_ALL = 0;
-const float MULTICAST_PVS = 2;
-const float MULTICAST_ONE = 6;
-const float MULTICAST_ALL_R = 3;
-const float MULTICAST_PVS_R = 5;
-const float MULTICAST_ONE_R = 7;
-const float MULTICAST_INIT = 8;
-const float FILE_READ = 0;
-const float FILE_APPEND = 1;
-const float FILE_WRITE = 2;

-//----------------------------------------------------------------------
-// Vanilla Builtin list (reduced, so as to avoid conflicts)
-//----------------------------------------------------------------------
-void(vector) makevectors = #1;
-void(entity,vector) setorigin = #2;
-void(entity,string) setmodel = #3;
-void(entity,vector,vector) setsize = #4;
-float() random = #7;
-vector(vector) normalize = #9;
-void(string e) error = #10;
-void(string n) objerror = #11;
-float(vector) vlen = #12;
-entity() spawn = #14;
-void(entity e) remove = #15;
-void(string,...) dprint = #25;
-string(float) ftos = #26;
-string(vector) vtos = #27;
-float(float n) rint = #36;
-float(float n) floor = #37;
-float(float n) ceil = #38;
-float(float n) fabs = #43;
-float(string) cvar = #45;
-void(string,...) localcmd = #46;
-entity(entity) nextent = #47;
-void(string var, string val) cvar_set = #72;
+const float FALSE = 0;
+const float TRUE = 1;
+
+const float IE_KEYDOWN = 0;
+const float IE_KEYUP = 1;
+const float IE_MOUSEDELTA = 2;
+const float IE_MOUSEABS = 3;
+const float IE_JOYAXIS = 6;
+
+#define ERRORTIME 20
+#define STEPTIME 8
+
+#define STAT_HEALTH 0
+#define STAT_WEAPONMODEL 2 // weapon model idx as evalutated by server code
+#define STAT_AMMO 3
+#define STAT_ARMOR 4
+#define STAT_WEAPONFRAME 5
+#define STAT_SHELLS 6
+#define STAT_NAILS 7
+#define STAT_ROCKETS 8
+#define STAT_CELLS 9
+#define STAT_ACTIVEWEAPON 10 // the one shown on the hud
+#define STAT_TOTALSECRETS 11
+#define STAT_TOTALMONSTERS 12
+#define STAT_FOUNDSECRETS 13
+#define STAT_KILLEDMONSTERS 14
+#define STAT_ITEMS 15
+#define STAT_VIEWHEIGHT 16 // player.view_ofs_z
+
+enumflags {
+ RF_VIEWMODEL,
+ RF_EXTERNALMODEL,
+ RF_DEPTHHACK,
+ RF_ADDATIVE,
+ RF_USEAXIS
+};
+
+const float CLASS_PLAYER = 77; // TODO CEV
+
+// edict.flags
+const float FL_FLY = 1;
+const float FL_SWIM = 2;
+const float FL_CLIENT = 8; // set for all client edicts
+const float FL_INWATER = 16; // for enter / leave water splash
+const float FL_MONSTER = 32;
+const float FL_GODMODE = 64; // player cheat
+const float FL_NOTARGET = 128; // player cheat
+const float FL_ITEM = 256; // extra wide size for bonus items
+const float FL_ONGROUND = 512; // standing on something
+const float FL_PARTIALGROUND = 1024; // not all corners are valid
+const float FL_WATERJUMP = 2048; // player jumping out of water
+const float FL_JUMPRELEASED = 4096; // for jump debouncing
+const float FL_DOUBLEJUMPED = 8192; // player has doublejumped
+const float FL_WALLJUMP = 16384; // player has jumped off a wall
+const float FL_NOCENTERPRINT = 65536; // don't centerprint entity's message
+ // field when its targets are used
+// edict.movetype values
+const float MOVETYPE_NONE = 0; // never moves
+// const float MOVETYPE_ANGLENOCLIP = 1;
+// const float MOVETYPE_ANGLECLIP = 2;
+const float MOVETYPE_WALK = 3; // players only
+const float MOVETYPE_STEP = 4; // discrete, not real time unless fall
+const float MOVETYPE_FLY = 5;
+const float MOVETYPE_TOSS = 6; // gravity
+const float MOVETYPE_PUSH = 7; // no clip to world, push and crush
+const float MOVETYPE_NOCLIP = 8;
+const float MOVETYPE_FLYMISSILE = 9; // fly with extra size against monsters
+const float MOVETYPE_BOUNCE = 10;
+const float MOVETYPE_BOUNCEMISSILE = 11;// bounce with extra size
+const float MOVETYPE_FOLLOW = 12; // supported extension
+
+// edict.solid values
+const float SOLID_NOT = 0; // no interaction with other objects
+const float SOLID_TRIGGER = 1; // touch on edge, but not blocking
+const float SOLID_BBOX = 2; // touch on edge, block
+const float SOLID_SLIDEBOX = 3; // touch on edge, but not an onground
+const float SOLID_BSP = 4; // bsp clip, touch on edge, block
+const float SOLID_CORPSE = 5; // supported extension
+
+// point content values
+const float CONTENT_EMPTY = -1;
+const float CONTENT_SOLID = -2;
+const float CONTENT_WATER = -3;
+const float CONTENT_SLIME = -4;
+const float CONTENT_LAVA = -5;
+const float CONTENT_SKY = -6;

//----------------------------------------------------------------------
-// Builtin list
+// Valid as a return value from the predraw function. Returning this will
+// simply move on to the next entity without the autoadd behaviour, so can
+// be used for particle/invisible/special entites, or entities that were
+// explicitly drawn with addentity.
//----------------------------------------------------------------------
-vector(vector fwd, optional vector up) vectoangles2 = #51; /*
- Returns the angles (+x=UP) required to orient an entity to look in the given direction. The 'up' argument is required if you wish to set a roll angle, otherwise it will be limited to just monster-style turning. */
-
-float(float angle) sin = #60;
-float(float angle) cos = #61;
-float(float value) sqrt = #62;
-void(entity ent, entity ignore) tracetoss = #64;
-string(entity ent) etos = #65;
-string(entity e, string key) infokey = #80; /*
- If e is world, returns the field 'key' from either the serverinfo or the localinfo. If e is a player, returns the value of 'key' from the player's userinfo string. There are a few special exceptions, like 'ip' which is not technically part of the userinfo. */
-
-float(entity e, string key) infokeyf = #0; /*
- Identical to regular infokey, but returns it as a float instead of creating new tempstrings. */
-
-float(string) stof = #81;
-#define unicast(pl,reli) do{msg_entity = pl; multicast('0 0 0', reli?MULITCAST_ONE_R:MULTICAST_ONE);}while(0)
-void(vector where, float set) multicast = #82; /*
- Once the MSG_MULTICAST network message buffer has been filled with data, this builtin is used to dispatch it to the given target, filtering by pvs for reduced network bandwidth. */
-
-void(vector start, vector mins, vector maxs, vector end, float nomonsters, entity ent) tracebox = #90; /*
- Exactly like traceline, but a box instead of a uselessly thin point. Acceptable sizes are limited by bsp format, q1bsp has strict acceptable size values. */
-
-vector() randomvec = #91; /*
- Returns a vector with random values. Each axis is independantly a value between -1 and 1 inclusive. */
-
-vector(vector org) getlight = #92;
-float(string cvarname, string defaultvalue) registercvar = #93; /*
- Creates a new cvar on the fly. If it does not already exist, it will be given the specified value. If it does exist, this is a no-op.
- This builtin has the limitation that it does not apply to configs or commandlines. Such configs will need to use the set or seta command causing this builtin to be a noop.
- In engines that support it, you will generally find the autocvar feature easier and more efficient to use. */
-
-float(float a, float b, ...) min = #94; /*
- Returns the lowest value of its arguments. */
-
-float(float a, float b, ...) max = #95; /*
- Returns the highest value of its arguments. */
-
-float(float minimum, float val, float maximum) bound = #96; /*
- Returns val, unless minimum is higher, or maximum is less. */
-
-float(float value, float exp) pow = #97;
-#define findentity findfloat
-entity(entity start, .__variant fld, __variant match) findfloat = #98; /*
- Equivelent to the find builtin, but instead of comparing strings contents, this builtin compares the raw values. This builtin requires multiple calls in order to scan all entities - set start to the previous call's return value.
- world is returned when there are no more entities. */
-
-float(string extname) checkextension = #99; /*
- Checks for an extension by its name (eg: checkextension("FRIK_FILE") says that its okay to go ahead and use strcat).
- Use cvar("pr_checkextension") to see if this builtin exists. */
-
-float(__variant funcref) checkbuiltin = #0; /*
- Checks to see if the specified builtin is supported/mapped. This is intended as a way to check for #0 functions, allowing for simple single-builtin functions. */
+const float PREDRAW_NEXT = 1;

//----------------------------------------------------------------------
-// 100-199 Range
+// These constants are only used in CSQC_UpdateView
//----------------------------------------------------------------------
-float(string builtinname) builtin_find = #100; /*
- Looks to see if the named builtin is valid, and returns the builtin number it exists at. */
-
-float(float value) anglemod = #102;
-filestream(string filename, float mode, optional float mmapminsize) fopen = #110; /*
- Opens a file, typically prefixed with "data/", for either read or write access. */
-
-void(filestream fhandle) fclose = #111;
-string(filestream fhandle) fgets = #112; /*
- Reads a single line out of the file. The new line character is not returned as part of the string. Returns the null string on EOF (use if not(string) to easily test for this, which distinguishes it from the empty string which is returned if the line being read is blank */
-
-void(filestream fhandle, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7) fputs = #113; /*
- Writes the given string(s) into the file. For compatibility with fgets, you should ensure that the string is terminated with a \n - this will not otherwise be done for you. It is up to the engine whether dos or unix line endings are actually written. */
-
-#define ftell fseek //c-compat
-int(filestream fhandle, optional int newoffset) fseek = #0; /*
- Changes the current position of the file, if specified. Returns prior position, in bytes. */
-
-float(string s) strlen = #114;
-string(string s1, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7, optional string s8) strcat = #115;
-string(string s, float start, float length) substring = #116;
-vector(string s) stov = #117;
-string(string s, ...) strzone = #118; /*
- Create a semi-permanent copy of a string that only becomes invalid once strunzone is called on the string (instead of when the engine assumes your string has left scope). */
-
-void(string s) strunzone = #119; /*
- Destroys a string that was allocated by strunzone. Further references to the string MAY crash the game. */
+const float MASK_ENGINE = 1;
+const float MASK_VIEWMODEL = 2;
+const float MASK_NORMAL = 4;

//----------------------------------------------------------------------
-// 200-299 FTE Range
-//----------------------------------------------------------------------
-float(float number, float quantity) bitshift = #218;
-void(vector org) te_lightningblood = #219;
-float(string s1, string sub, optional float startidx) strstrofs = #221; /*
- Returns the 0-based offset of sub within the s1 string, or -1 if sub is not in s1.
- If startidx is set, this builtin will ignore matches before that 0-based offset. */
-
-float(string str, float index) str2chr = #222; /*
- Retrieves the character value at offset 'index'. */
-
-string(float chr, ...) chr2str = #223; /*
- The input floats are considered character values, and are concatenated. */
-
-string(float ccase, float redalpha, float redchars, string str, ...) strconv = #224; /*
- Converts quake chars in the input string amongst different representations.
- ccase specifies the new case for letters.
- 0: not changed.
- 1: forced to lower case.
- 2: forced to upper case.
- redalpha and redchars switch between colour ranges.
- 0: no change.
- 1: Forced white.
- 2: Forced red.
- 3: Forced gold(low) (numbers only).
- 4: Forced gold (high) (numbers only).
- 5+6: Forced to white and red alternately.
- You should not use this builtin in combination with UTF-8. */
-
-string(float pad, string str1, ...) strpad = #225; /*
- 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; /*
- 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; /*
- Reads a named value from an infostring. The returned value is a tempstring */
-
-#define strcmp strncmp
-float(string s1, string s2, optional float len, optional float s1ofs, optional float s2ofs) strncmp = #228; /*
- Compares up to 'len' chars in the two strings. s1ofs allows you to treat s2 as a substring to compare against, or should be 0.
- Returns 0 if the two strings are equal, a negative value if s1 appears numerically lower, and positive if s1 appears numerically higher. */
-
-float(string s1, string s2) strcasecmp = #229; /*
- Compares the two strings without case sensitivity.
- Returns 0 if they are equal. The sign of the return value may be significant, but should not be depended upon. */
-
-float(string s1, string s2, float len, optional float s1ofs, optional float s2ofs) strncasecmp = #230; /*
- Compares up to 'len' chars in the two strings without case sensitivity. s1ofs allows you to treat s2 as a substring to compare against, or should be 0.
- Returns 0 if they are equal. The sign of the return value may be significant, but should not be depended upon. */
-
-string(string s) strtrim = #0; /*
- Trims the whitespace from the start+end of the string. */
-
-void(float num, float type, .__variant fld) clientstat = #232; /*
- Specifies what data to use in order to send various stats, in a client-specific way.
- 'num' should be a value between 32 and 127, other values are reserved.
- 'type' must be set to one of the EV_* constants, one of EV_FLOAT, EV_STRING, EV_INTEGER, EV_ENTITY.
- fld must be a reference to the field used, each player will be sent only their own copy of these fields. */
-
-void(float num, float type, string name) globalstat = #233; /*
- Specifies what data to use in order to send various stats, in a non-client-specific way. num and type are as in clientstat, name however, is the name of the global to read in the form of a string (pass "foo"). */
-
-void(float num, float type, __variant *address) pointerstat = #0; /*
- Specifies what data to use in order to send various stats, in a non-client-specific way. num and type are as in clientstat, address however, is the address of the variable you would like to use (pass &foo). */
-
-float(entity player) isbackbuffered = #234; /*
- Returns if the given player's network buffer will take multiple network frames in order to clear. If this builtin returns non-zero, you should delay or reduce the amount of reliable (and also unreliable) data that you are sending to that client. */
-
-void(vector org, float count) te_bloodqw = #239;
-float(float a, float n) mod = #245;
-int(string) stoi = #259; /*
- Converts the given string into a true integer. Base 8, 10, or 16 is determined based upon the format of the string. */
-
-string(int) itos = #260; /*
- Converts the passed true integer into a base10 string. */
-
-int(string) stoh = #261; /*
- Reads a base-16 string (with or without 0x prefix) as an integer. Bugs out if given a base 8 or base 10 string. :P */
-
-string(int) htos = #262; /*
- Formats an integer as a base16 string, with leading 0s and no prefix. Always returns 8 characters. */
-
-int(float) ftoi = #0; /*
- Converts the given float into a true integer without depending on extended qcvm instructions. */
-
-float(int) itof = #0; /*
- Converts the given true integer into a float without depending on extended qcvm instructions. */
-
-#ifndef dotproduct
-#define dotproduct(v1,v2) ((vector)(v1)*(vector)(v2))
-#endif
-vector(vector v1, vector v2) crossproduct = #0; /*
- Small helper function to calculate the crossproduct of two vectors. */
-
-float(float modidx, string framename) frameforname = #276; /*
- Looks up a framegroup from a model by name, avoiding the need for hardcoding. Returns -1 on error. */
-
-float(float modidx, float framenum) frameduration = #277; /*
- Retrieves the duration (in seconds) of the specified framegroup. */
-
-void(float buf, float fl) WriteFloat = #280;
-string(float modidx, float framenum) frametoname = #284;
-float(string name) checkcommand = #294; /*
- Checks to see if the supplied name is a valid command, cvar, or alias. Returns 0 if it does not exist. */
-
-// ----------------------------------------------------------------------
-// 300-399 Range - Moved to CSQC DEFS file
-// ----------------------------------------------------------------------
-
-//----------------------------------------------------------------------
-// 400-499 DP Range
-//----------------------------------------------------------------------
-entity(entity from, optional entity to) copyentity = #400; /*
- Copies all fields from one entity to another. */
-
-void(entity ent, float colours) setcolors = #401; /*
- Changes a player's colours. The bits 0-3 are the lower/trouser colour, bits 4-7 are the upper/shirt colours. */
-
-entity(.string field, string match) findchain = #402;
-entity(.float fld, float match) findchainfloat = #403;
-void(vector org, vector dir, float count) te_blood = #405;
-void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain = #409;
-void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow = #410;
-void(vector org, optional float count) te_gunshot = #418;
-void(vector org) te_spike = #419;
-void(vector org) te_superspike = #420;
-void(vector org) te_explosion = #421;
-void(vector org) te_tarexplosion = #422;
-void(vector org) te_wizspike = #423;
-void(vector org) te_knightspike = #424;
-void(vector org) te_lavasplash = #425;
-void(vector org) te_teleport = #426;
-void(vector org, float color, float colorlength) te_explosion2 = #427;
-void(entity own, vector start, vector end) te_lightning1 = #428;
-void(entity own, vector start, vector end) te_lightning2 = #429;
-void(entity own, vector start, vector end) te_lightning3 = #430;
-void(entity own, vector start, vector end) te_beam = #431;
-void(vector dir) vectorvectors = #432;
-float(entity e, float s) getsurfacenumpoints = #434;
-vector(entity e, float s, float n) getsurfacepoint = #435;
-vector(entity e, float s) getsurfacenormal = #436;
-string(entity e, float s) getsurfacetexture = #437;
-float(entity e, vector p) getsurfacenearpoint = #438;
-vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
-void(entity e, string s) clientcommand = #440;
-float(string s) tokenize = #441;
-string(float n) argv = #442;
-float() argc = #0;
-void(entity e, entity tagentity, string tagname) setattachment = #443; /* */
-
-searchhandle(string pattern, optional float caseinsensitive, optional float quiet) search_begin = #444; /*
- initiate a filesystem scan based upon filenames. Be sure to call search_end on the returned handle. */
-
-void(searchhandle handle) search_end = #445; /* */
-
-float(searchhandle handle) search_getsize = #446; /*
- Retrieves the number of files that were found. */
-
-string(searchhandle handle, float num) search_getfilename = #447; /*
- Retrieves name of one of the files that was found by the initial search. */
-
-float(searchhandle handle, float num) search_getfilesize = #0; /*
- Retrieves the size of one of the files that was found by the initial search. */
-
-string(searchhandle handle, float num) search_getfilemtime = #0; /*
- Retrieves modification time of one of the files in %Y-%m-%d %H:%M:%S format. */
-
-string(string cvarname) cvar_string = #448;
-entity(entity start, .float fld, float match) findflags = #449;
-entity(.float fld, float match) findchainflags = #450;
-void(entity player) dropclient = #453;
-entity() spawnclient = #454; /*
- Spawns a dummy player entity.
- Note that such dummy players will be carried from one map to the next.
- Warning: DP_SV_CLIENTCOLORS DP_SV_CLIENTNAME are not implemented in quakespasm, so use KRIMZON_SV_PARSECLIENTCOMMAND's clientcommand builtin to change the bot's name/colours/skin/team/etc, in the same way that clients would ask. */
-
-float(entity client) clienttype = #455;
-void(float target, string str) WriteUnterminatedString = #456;
-entity(float entnum) edict_num = #459;
-strbuf() buf_create = #460;
-void(strbuf bufhandle) buf_del = #461;
-float(strbuf bufhandle) buf_getsize = #462;
-void(strbuf bufhandle_from, strbuf bufhandle_to) buf_copy = #463;
-void(strbuf bufhandle, float sortprefixlen, float backward) buf_sort = #464;
-string(strbuf bufhandle, string glue) buf_implode = #465;
-string(strbuf bufhandle, float string_index) bufstr_get = #466;
-void(strbuf bufhandle, float string_index, string str) bufstr_set = #467;
-float(strbuf bufhandle, string str, float order) bufstr_add = #468;
-void(strbuf bufhandle, float string_index) bufstr_free = #469;
-float(float s) asin = #471;
-float(float c) acos = #472;
-float(float t) atan = #473;
-float(float c, float s) atan2 = #474;
-float(float a) tan = #475;
-float(string s) strlennocol = #476; /*
- Returns the number of characters in the string after any colour codes or other markup has been parsed. */
-
-string(string s) strdecolorize = #477; /*
- Flattens any markup/colours, removing them from the string. */
-
-string(float uselocaltime, string format, ...) strftime = #478;
-float(string s, string separator1, ...) tokenizebyseparator = #479;
-string(string s) strtolower = #480;
-string(string s) strtoupper = #481;
-string(string s) cvar_defstring = #482;
-void(vector origin, string sample, float volume, float attenuation) pointsound = #483;
-string(string search, string replace, string subject) strreplace = #484;
-string(string search, string replace, string subject) strireplace = #485;
-vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
-float(float caseinsensitive, string s, ...) crc16 = #494;
-float(string name) cvar_type = #495;
-float() numentityfields = #496; /*
- Gives the number of named entity fields. Note that this is not the size of an entity, but rather just the number of unique names (ie: vectors use 4 names rather than 3). */
-
-float(string fieldname) findentityfield = #0; /*
- Find a field index by name. */
-
-typedef .__variant field_t;
-field_t(float fieldnum) entityfieldref = #0; /*
- Returns a field value that can be directly used to read entity fields. Be sure to validate the type with entityfieldtype before using. */
-
-string(float fieldnum) entityfieldname = #497; /*
- Retrieves the name of the given entity field. */
-
-float(float fieldnum) entityfieldtype = #498; /*
- Provides information about the type of the field specified by the field num. Returns one of the EV_ values. */
-
-string(float fieldnum, entity ent) getentityfieldstring = #499;
-
-//----------------------------------------------------------------------
-// 500-599 Range
-//----------------------------------------------------------------------
-float(float fieldnum, entity ent, string s) putentityfieldstring = #500;
-string(string filename, optional float makereferenced) whichpack = #503; /*
- Returns the pak file name that contains the file specified. progs/player.mdl will generally return something like 'pak0.pak'. If makereferenced is true, clients will automatically be told that the returned package should be pre-downloaded and used, even if allow_download_refpackages is not set. */
-
-string(string in) uri_escape = #510;
-string(string in) uri_unescape = #511;
-float(entity ent) num_for_edict = #512;
-float(string str) tokenize_console = #514; /*
- Tokenize a string exactly as the console's tokenizer would do so. The regular tokenize builtin became bastardized for convienient string parsing, which resulted in a large disparity that can be exploited to bypass checks implemented in a naive SV_ParseClientCommand function, therefore you can use this builtin to make sure it exactly matches. */
-
-float(float idx) argv_start_index = #515; /*
- Returns the character index that the tokenized arg started at. */
-
-float(float idx) argv_end_index = #516; /*
- Returns the character index that the tokenized arg stopped at. */
-
-string(string cvarname) cvar_description = #518; /*
- Retrieves the description of a cvar, which might be useful for tooltips or help files. This may still not be useful. */
-
-float(optional float timetype) gettime = #519;
-string(string command, optional float bindmap) findkeysforcommand = #521; /*
- Returns a list of keycodes that perform the given console command in a format that can only be parsed via tokenize (NOT tokenize_console). This always returns at least two values - if only one key is actually bound, -1 will be returned. The bindmap argument is listed for compatibility with dp-specific defs, but is ignored in FTE. */
-
-string(string command, optional float bindmap) findkeysforcommandex = #0; /*
- Returns a list of key bindings in keyname format instead of keynums. Use tokenize to parse. This list may contain modifiers. May return large numbers of keys. */
-
-float(float v, optional float base) log = #532; /*
- Determines the logarithm of the input value according to the specified base. This can be used to calculate how much something was shifted by. */
-
-float(string filename, strbuf bufhandle) buf_loadfile = #535; /*
- Appends the named file into a string buffer (which must have been created in advance). The return value merely says whether the file was readable. */
-
-float(filestream filehandle, strbuf bufhandle, optional float startpos, optional float numstrings) buf_writefile = #536; /*
- Writes the contents of a string buffer onto the end of the supplied filehandle (you must have already used fopen). Additional optional arguments permit you to constrain the writes to a subsection of the stringbuffer. */
-
-//----------------------------------------------------------------------
-// 600-699 Range
-//----------------------------------------------------------------------
-void(.../*, string funcname*/) callfunction = #605; /*
- Invokes the named function. The function name is always passed as the last parameter and must always be present. The others are passed to the named function as-is */
-
-float(string s) isfunction = #607; /*
- Returns true if the named function exists and can be called with the callfunction builtin. */
-
-float(entity e, string s, optional float offset) parseentitydata = #613; /*
- Reads a single entity's fields into an already-spawned entity. s should contain field pairs like in a saved game: {"foo1" "bar" "foo2" "5"}. Returns <=0 on failure, otherwise returns the offset in the string that was read to. */
-
-string(string fmt, ...) sprintf = #627;
-float(entity e, float s) getsurfacenumtriangles = #628;
-vector(entity e, float s, float n) getsurfacetriangle = #629;
+const float VF_MIN = 1;
+const float VF_SIZE = 4;
+const float VF_ORIGIN = 11;
+const float VF_ORIGIN_X = 12;
+const float VF_ORIGIN_Y = 13;
+const float VF_ORIGIN_Z = 14;
+const float VF_ANGLES = 15;
+const float VF_ANGLES_X = 16;
+const float VF_ANGLES_Y = 17;
+const float VF_ANGLES_Z = 18;
+const float VF_DRAWENGINESBAR = 20;
+const float VF_DRAWCROSSHAIR = 21;

//----------------------------------------------------------------------
-//Builtin Stubs List - present for simpler compatibility
-// Not properly supported in QuakeSpasm at this time
+// Supported Extension Constants
//----------------------------------------------------------------------
-/*
-void(vector org, string modelname, float startframe, float endframe, float framerate) effect = #404;
-void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower = #406;
-void(vector org, vector color) te_explosionrgb = #407;
-void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube = #408;
-void(vector org, vector vel, float howmany) te_spark = #411;
-void(vector org) te_gunshotquad = #412;
-void(vector org) te_spikequad = #413;
-void(vector org) te_superspikequad = #414;
-void(vector org) te_explosionquad = #415;
-void(vector org) te_smallflash = #416;
-void(vector org, float radius, float lifetime, vector color) te_customflash = #417;
-void(vector org) te_plasmaburn = #433;
-*/
+const float CLIENTTYPE_DISCONNECT = 0;
+const float CLIENTTYPE_REAL = 1;
+const float CLIENTTYPE_BOT = 2;
+const float CLIENTTYPE_NOTCLIENT = 3;
+const float EF_NOSHADOW = 0x1000;
+// the standard modelflags from the model are ignored
+const float EF_NOMODELFLAGS = 0x800000;
+const float MF_ROCKET = 0x1;
+const float MF_GRENADE = 0x2;
+const float MF_GIB = 0x4;
+const float MF_ROTATE = 0x8;
+const float MF_TRACER = 0x10;
+const float MF_ZOMGIB = 0x20;
+const float MF_TRACER2 = 0x40;
+const float MF_TRACER3 = 0x80;
+const float MSG_MULTICAST = 4;
+const float MULTICAST_ALL = 0;
+const float MULTICAST_PVS = 2;
+const float MULTICAST_ONE = 6;
+const float MULTICAST_ALL_R = 3;
+const float MULTICAST_PVS_R = 5;
+const float MULTICAST_ONE_R = 7;
+const float MULTICAST_INIT = 8;
+const float FILE_READ = 0;
+const float FILE_APPEND = 1;
+const float FILE_WRITE = 2;

//----------------------------------------------------------------------
// Keyboard input values
@@ -679,81 +418,3 @@ const float K_LTRIGGER = 830;
const float K_RTRIGGER = 831;
const float K_PAUSE = 153;

-//----------------------------------------------------------------------
-// Reset suppression of ref errors
-#pragma noref 0
-
-//----------------------------------------------------------------------
-// List of advertised extensions (not used, reference only)
-//----------------------------------------------------------------------
-//DP_CON_SET
-//DP_CON_SETA
-//DP_EF_NOSHADOW
-//DP_ENT_ALPHA
-//DP_ENT_COLORMOD
-//DP_ENT_SCALE
-//DP_ENT_TRAILEFFECTNUM
-//DP_INPUTBUTTONS
-//DP_QC_AUTOCVARS
-//DP_QC_ASINACOSATANATAN2TAN
-//DP_QC_COPYENTITY
-//DP_QC_CRC16
-//DP_QC_CVAR_DEFSTRING
-//DP_QC_CVAR_STRING
-//DP_QC_CVAR_TYPE
-//DP_QC_EDICT_NUM
-//DP_QC_ENTITYDATA
-//DP_QC_ETOS
-//DP_QC_FINDCHAIN
-//DP_QC_FINDCHAINFLAGS
-//DP_QC_FINDCHAINFLOAT
-//DP_QC_FINDFLAGS
-//DP_QC_FINDFLOAT
-//DP_QC_GETLIGHT
-//DP_QC_GETSURFACE
-//DP_QC_GETSURFACETRIANGLE
-//DP_QC_GETSURFACEPOINTATTRIBUTE
-//DP_QC_MINMAXBOUND
-//DP_QC_MULTIPLETEMPSTRINGS
-//DP_QC_RANDOMVEC
-//DP_QC_SINCOSSQRTPOW
-//DP_QC_SPRINTF
-//DP_QC_STRFTIME
-//DP_QC_STRING_CASE_FUNCTIONS
-//DP_QC_STRINGBUFFERS
-//DP_QC_STRINGCOLORFUNCTIONS
-//DP_QC_STRREPLACE
-//DP_QC_TOKENIZEBYSEPARATOR
-//DP_QC_TRACEBOX
-//DP_QC_TRACETOSS
-//DP_QC_TRACE_MOVETYPES
-//DP_QC_URI_ESCAPE
-//DP_QC_VECTOANGLES_WITH_ROLL
-//DP_QC_VECTORVECTORS
-//DP_QC_WHICHPACK
-//DP_VIEWZOOM
-//DP_REGISTERCVAR
-//DP_SV_BOTCLIENT
-//DP_SV_DROPCLIENT
-//DP_SV_POINTSOUND
-//DP_SV_PRINT
-//DP_SV_SETCOLOR
-//DP_SV_SPAWNFUNC_PREFIX
-//DP_SV_WRITEUNTERMINATEDSTRING
-//DP_TE_PARTICLERAIN
-//DP_TE_PARTICLESNOW
-//DP_TE_STANDARDEFFECTBUILTINS
-//EXT_BITSHIFT
-//FRIK_FILE
-//FTE_PART_SCRIPT
-//FTE_PART_NAMESPACES
-//FTE_PART_NAMESPACE_EFFECTINFO
-//FTE_QC_CHECKCOMMAND
-//FTE_QC_CROSSPRODUCT
-//FTE_QC_INFOKEY
-//FTE_QC_INTCONV
-//FTE_QC_MULTICAST
-//FTE_STRINGS
-//FTE_SV_POINTPARTICLES
-//KRIMZON_SV_PARSECLIENTCOMMAND
-//ZQ_QC_STRINGS

Return to the top of this page or return to the overview of this repo.

Diff qc/csqc/csqc_entrypoints.qc

diff --git a/qc/csqc/csqc_entrypoints.qc b/qc/csqc/csqc_entrypoints.qc
new file mode 100644
index 0000000..eac9683
--- /dev/null
+++ b/qc/csqc/csqc_entrypoints.qc
@@ -0,0 +1,334 @@
+//==============================================================================
+// CSQC_ENTRYPOINTS
+//==============================================================================
+void(float isnew) PlayerUpdate;
+
+//----------------------------------------------------------------------
+// Stubs for extra CSQC functions (not all supported)
+//----------------------------------------------------------------------
+
+// Can query or check anything types on the console here
+float(string str) CSQC_ConsoleCommand =
+{
+ tokenize_console (str);
+ return FALSE;
+};
+
+// Can query/check keyboard/mouse/joystick input with this function
+// For key events, scanx is one of the KEY_* values
+// chary is the character code (chr2str to shove it into a string)
+// For mouse events then x+y are the mouse delta/position values
+/*
+float(float evtype, float scanx, float chary, float devid) CSQC_InputEvent =
+{
+ return FALSE;
+};
+*/
+
+// This is linked to client dmg_take / dmg_save / dmg_inflictor fields
+// returning TRUE will block the red flash damage stuff
+float(float save, float take, vector dir) CSQC_Parse_Damage =
+{
+ painfinishtime = time + 0.2;
+ return FALSE;
+};
+
+// Can query/check server MSG events
+// CSQC_Parse_Event is called when the client sees a
+// #define svcfte_cgamepacket (83) message from the server
+// Not supported for DP, is called from only QSS/FTE
+// void() CSQC_Parse_Event = { };
+
+// Can intercept printed messages from the server (top of screen)
+// printlvl (text filtering) 0=low, 1=medium, 2=high, 3=chat
+// con_notifytime = amount of time the text remains on screen
+// ONLY define this function, if doing something with the text!!
+void(string printmsg, float printlvl) CSQC_Parse_Print =
+{
+ print (printmsg);
+};
+
+// Running on the Server side of CSQC listening for commands back
+// This is never called on the client side of the progs
+void(string str) SV_ParseClientCommand =
+{
+ local string ostr, cmd;
+ // Save command string for later
+ ostr = str;
+ // Search for tokens in string
+ tokenize_console (str);
+ // Find the first argument of the command
+ cmd = argv (0);
+ // Is this my (AD CSQC) command?
+ if (cmd == CSQC_PING)
+ self.ext_csqc = TRUE;
+ else
+ // Pass through original command
+ clientcommand (self, ostr);
+};
+
+//----------------------------------------------------------------------
+// TODO CEV
+//----------------------------------------------------------------------
+void(entity ent) CSQC_DrawViewModel =
+{
+ float newframe, newmodel;
+
+ newframe = getstatf (STAT_WEAPONFRAME);
+ newmodel = getstatf (STAT_WEAPONMODEL);
+
+ if (newmodel != ent.modelindex)
+ {
+ // changed entirely
+ ent.modelindex = newmodel;
+ ent.frame2 = ent.frame = newframe;
+ ent.lerptime = time;
+ }
+ else if (newframe != ent.frame)
+ {
+ ent.frame2 = ent.frame;
+ ent.frame = newframe;
+ ent.lerptime = time;
+ }
+
+ ent.lerpfrac = 1 - (time - ent.lerptime) * 10;
+
+ ent.origin = '0 0 0';
+ ent.angles = '0 0 0';
+
+ addentity (ent);
+};
+
+//----------------------------------------------------------------------
+void(float vwidth, float vheight, float notmenu) CSQC_UpdateView =
+{
+ local vector ssize;
+ ssize_x = vwidth; ssize_y = vheight; ssize_z = 0;
+
+ // Is the CSQC functionality enabled/disabled?
+ nocsqc = cvar ("cl_nocsqc");
+
+ clearscene ();
+
+ // TODO CEV
+ // addentities (MASK_ENGINE|MASK_VIEWMODEL);
+ addentities (MASK_NORMAL|MASK_ENGINE);
+ setproperty (VF_MIN, '0 0');
+ setproperty (VF_SIZE, ssize);
+
+ // If hud is disabled, draw engine hud instead
+ setproperty (VF_DRAWENGINESBAR, nocsqc);
+ setproperty (VF_DRAWCROSSHAIR, TRUE);
+
+ // TODO CEV
+ if (self.entnum == player_localentnum)
+ {
+ // read our smoothed & predicted view origin
+ setproperty (VF_ORIGIN, vieworg);
+ setproperty (VF_ANGLES, view_angles);
+
+ makevectors (view_angles);
+ SetListener (vieworg, v_forward, v_right, v_up);
+
+ CSQC_DrawViewModel (viewentity);
+ }
+ else
+ {
+ // engine didn't tell us about our player entity.
+ // that's not right...
+ dprint ("csqc UpdateView: no player_local\n");
+ addentities (MASK_VIEWMODEL);
+ }
+
+ renderscene ();
+
+ // Revert back to using engine HUD?
+ if (nocsqc > 0)
+ return;
+
+ // Required for DP engine
+ if (detectDP == TRUE)
+ {
+ ssize_x = cvar ("vid_conwidth");
+ ssize_y = cvar ("vid_conheight");
+ }
+
+ // Used on intermission screen later
+ if (!intermission)
+ intermission_time = time;
+
+ // Read deathmatch variable and create csprogs coop variable
+ // csprogs has no knowledge of the coop variable
+ deathmatch = stof (serverkey("deathmatch"));
+ coop = !deathmatch && maxclients > 1;
+
+ // Draw the HUDs and scoreboards
+ CSQC_DrawHud (ssize, sb_showscores);
+ CSQC_DrawScores (ssize, sb_showscores);
+};
+
+//----------------------------------------------------------------------
+// Handle SVC_TEMPENTITY data from the server -- CEV
+//
+// Based on code by PrimalLove found at:
+// https://forums.insideqc.com/viewtopic.php?p=55772#p55772
+//----------------------------------------------------------------------
+float CSQC_Parse_TempEntity()
+{
+ float handled, teid;
+ vector pos, end, vel;
+ float eid;
+ entity e;
+
+ handled = TRUE;
+ teid = ReadByte ();
+
+ switch(teid)
+ {
+ case 6:
+ eid = readentitynum ();
+ pos_x = ReadCoord ();
+ pos_y = ReadCoord ();
+ pos_z = ReadCoord ();
+ end_x = ReadCoord ();
+ end_y = ReadCoord ();
+ end_z = ReadCoord ();
+ // pointparticles (
+ // particleeffectnum("TE_LIGHTNING2"),
+ // pos, end, 1);
+ // te_lightning2 (player_local, pos, end);
+ te_lightning2 (viewentity, pos, end);
+ handled = TRUE;
+ break;
+ default:
+ handled = FALSE;
+ break;
+ }
+
+ return handled;
+};
+
+//----------------------------------------------------------------------
+// Handle incoming MSG_ENTITY data from the server -- CEV
+//----------------------------------------------------------------------
+void(float isnew) CSQC_Ent_Update =
+{
+ local float classtype;
+
+ classtype = ReadByte ();
+
+ if (classtype == CLASS_PLAYER)
+ {
+ PlayerUpdate (isnew);
+ }
+};
+
+//----------------------------------------------------------------------
+// Registers HUD gfx images (all setup in string arrays)
+//----------------------------------------------------------------------
+void(float apilevel, string enginename, float engineversion) CSQC_Init =
+{
+ local float i, wadonly;
+
+ // Is the CSQC functionality enabled/disabled?
+ nocsqc = cvar ("cl_nocsqc");
+ // Revert back to using engine HUD?
+ if (nocsqc > 0)
+ return;
+
+ // Send ping back to server that CSQC client is alive
+ // This can be used on the server side to detect CSQC
+ // and change functions for new features
+ localcmd (strcat("cmd ", CSQC_PING, "\n"));
+
+ // precache from gfx.wad ONLY!?!
+ wadonly = TRUE;
+
+ // Cache all string tables
+ for (i = 0; i < 14; i++)
+ {
+ // HUD background images (320 wide+)
+ if (i < backgrd.length)
+ precache_pic (backgrd[i], wadonly);
+ // Large 24x24 brown/red numbers
+ if (i < number.length)
+ {
+ precache_pic (number[i], wadonly);
+ precache_pic (anumber[i], wadonly);
+ }
+ // Large 24x24 extra font characters (intermission)
+ if (i < extrachar.length)
+ precache_pic (extrachar[i], wadonly);
+ // Large 24x24 player face
+ if (i < facetab.length)
+ precache_pic (facetab[i], wadonly);
+ // Large 24x24 icons
+ if (i < sbitems.length)
+ precache_pic (sbitems[i], wadonly);
+ // Small 16x16 icons
+ if (i < ibitems.length)
+ precache_pic (ibitems[i], wadonly);
+ // Special 8x16 runes
+ if (i < ibrunes.length)
+ precache_pic (ibrunes[i], wadonly);
+ // All weapon setups (on/off/flashing)
+ if (i < wpnnames.length)
+ {
+ precache_pic(strcat(wpnselect[0], wpnnames[i]),wadonly);
+ precache_pic(strcat(wpnselect[1], wpnnames[i]),wadonly);
+ precache_pic(strcat(wpnflash[0], wpnnames[i]), wadonly);
+ precache_pic(strcat(wpnflash[1], wpnnames[i]), wadonly);
+ precache_pic(strcat(wpnflash[2], wpnnames[i]), wadonly);
+ precache_pic(strcat(wpnflash[3], wpnnames[i]), wadonly);
+ precache_pic(strcat(wpnflash[4], wpnnames[i]), wadonly);
+ }
+ }
+
+ // TODO CEV
+ precache_model ("progs/player.mdl");
+
+ viewentity = spawn ();
+ viewentity.renderflags = RF_VIEWMODEL|RF_DEPTHHACK;
+};
+
+//----------------------------------------------------------------------
+// Wrapper for CSQC_Init to try and detect DP engine
+//----------------------------------------------------------------------
+__wrap void(float apilevel, string enginename, float engineversion) CSQC_Init =
+{
+ // Try to detect DP engine (needed for CSQC_UpdateView later)
+ if (!apilevel && !enginename && !engineversion)
+ detectDP = TRUE;
+
+ // Execute previous CSQC_Init function
+ prior (apilevel, enginename, engineversion);
+
+ registercommand ("+showscores");
+ registercommand ("+showscores");
+ registercommand ("+showteamscores");
+ registercommand ("+showteamscores");
+};
+
+//----------------------------------------------------------------------
+// Wrapper for CSQC_ConsoleCommand to show different scoreboards
+//----------------------------------------------------------------------
+__wrap float(string str) CSQC_ConsoleCommand =
+{
+ if (prior(str))
+ return TRUE;
+
+ string c = argv(0);
+
+ if (c == "+showscores")
+ sb_showscores |= 1;
+ else if (c == "-showscores")
+ sb_showscores &~= 1;
+ else if (c == "+showteamscores")
+ sb_showscores |= 2;
+ else if (c == "-showteamscores")
+ sb_showscores &~= 2;
+ else
+ return FALSE;
+
+ return TRUE;
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/csqc/csqc_fteopts.qc

diff --git a/qc/csqc/csqc_fteopts.qc b/qc/csqc/csqc_fteopts.qc
index 8f7324f..2fd08b0 100644
--- a/qc/csqc/csqc_fteopts.qc
+++ b/qc/csqc/csqc_fteopts.qc
@@ -1,2 +1,14 @@
#define FTE
#pragma TARGET FTE
+#ifndef CSQC
+#define CSQC
+#endif
+
+// Some extra defs (csqc/csqc_simple)
+#ifndef CSQC_SIMPLE
+#define CSQC_SIMPLE
+#endif
+// Suppress reference errors
+#pragma noref 1
+
+

Return to the top of this page or return to the overview of this repo.

Diff qc/csqc/csqc_hudvanilla.qc

diff --git a/qc/csqc/csqc_hudvanilla.qc b/qc/csqc/csqc_hudvanilla.qc
index c3b2ac9..c03b537 100644
--- a/qc/csqc/csqc_hudvanilla.qc
+++ b/qc/csqc/csqc_hudvanilla.qc
@@ -1,3 +1,7 @@
+//==============================================================================
+// CSQC_HUDVANILLA
+//==============================================================================
+
/*======================================================================
All CSQC functions (Vanilla ONLY version)

@@ -9,57 +13,28 @@
* Added loads of extra comments to show what is going on

======================================================================*/
-float nocsqc; // CSQC State (0=on, 1=off)
-float detectDP; // Detect DP engine (using wrapper)
-float sitems; // CSQC copy of .items
-float sitems2; // CSQC copy of .items2 (or serverflags)
-float sweapon; // CSQC copy of .weapon
-float shealth; // CSQC copy of .health
-
-float sb_showscores; // Show lower tab scores
-float painfinishtime; // Track player damage for hud face
-
-float intermission; // in intermission
-float intermission_time; // when the intermission started
-
-float player_localentnum; // Entity number that csqc is attached to
-float numclientseats; // coop or splitscreen?
-float maxclients; // maximum players possible on this server
-float cltime; // increases regardless of pause or game speed
-
-.float ext_csqc; // Client Server Quake C HUD alive!
-string CSQC_PING = "csqcping"; // Test command to check if CSCQ alive

// Default sizes for HUD elements
-vector HUDSIZE_320 = '320 24 0';// Background images
-vector HUDSIZE_24 = '24 24 0'; // Status Bar
-vector HUDSIZE_16 = '16 16 0'; // Inventory/Powerups
-vector HUDSIZE_816 = '8 16 0'; // Runes
-vector HUDSIZE_8 = '8 8 0'; // Ammo numbers
-vector HUDSIZE_C8 = '8 0 0'; // Character sizes
+vector HUDSIZE_320 = '320 24 0'; // Background images
+vector HUDSIZE_24 = '24 24 0'; // Status Bar
+vector HUDSIZE_16 = '16 16 0'; // Inventory/Powerups
+vector HUDSIZE_816 = '8 16 0'; // Runes
+vector HUDSIZE_8 = '8 8 0'; // Ammo numbers
+vector HUDSIZE_C8 = '8 0 0'; // Character sizes

// 8 pixel font table (index positions)
-float HUDFONT_WHITE = 0; // Default index = 48-57
-float HUDFONT_YELLOW = 1; // index = index - 30
-float HUDFONT_RED = 2; // index = index + 128
+float HUDFONT_WHITE = 0; // Default index = 48-57
+float HUDFONT_YELLOW = 1; // index = index - 30
+float HUDFONT_RED = 2; // index = index + 128

// Default sizes for weapons
-vector HUDWPN_48 = '48 16 0'; // Vanilla LG
-vector HUDWPN_32 = '32 16 0'; // AD/Hipnotic LG
-vector HUDWPN_24 = '24 16 0'; // Default
+vector HUDWPN_48 = '48 16 0'; // Vanilla LG
+vector HUDWPN_32 = '32 16 0'; // AD/Hipnotic LG
+vector HUDWPN_24 = '24 16 0'; // Default

vector HUDRGB_DEF = '1 1 1';
-float baralpha; // Read scr_sbaralpha variable
-float hudalpha; // All gfx on hud bars
-
-//----------------------------------------------------------------------
-// These constants are only used in CSQC_UpdateView
-float MASK_ENGINE = 1;
-float MASK_VIEWMODEL = 2;
-float VF_MIN = 1;
-float VF_SIZE = 4;
-float VF_DRAWENGINESBAR = 20;
-float VF_DRAWCROSSHAIR = 21;
+float baralpha; // Read scr_sbaralpha variable
+float hudalpha; // All gfx on hud bars

//----------------------------------------------------------------------
// Statue, Inventory and Score bars (All 320 x 24)
@@ -70,35 +45,41 @@ string backlmp[3] = { "gfx/ranking.lmp", "gfx/complete.lmp", "gfx/inter.lmp" };

//----------------------------------------------------------------------
// Regular (24x24) brown numbers
-string number[10] = {
+string number[10] =
+{
"gfx/num_0", "gfx/num_1", "gfx/num_2", "gfx/num_3", "gfx/num_4",
"gfx/num_5", "gfx/num_6", "gfx/num_7", "gfx/num_8", "gfx/num_9"
};
// Red (24x24) numbers for no armour, low HP (<25) and no ammo
-string anumber[10] = {
+string anumber[10] =
+{
"gfx/anum_0", "gfx/anum_1", "gfx/anum_2", "gfx/anum_3", "gfx/anum_4",
"gfx/anum_5", "gfx/anum_6", "gfx/anum_7", "gfx/anum_8", "gfx/anum_9"
};

// Regular (24x24) characters for intermission
-string extrachar[3] = {
+string extrachar[3] =
+{
"gfx/num_colon", "gfx/num_minus", "gfx/num_slash"
};

// 24x24 pixel icons for Status Bar
-string sbitems[8] = {
+string sbitems[8] =
+{
"gfx/sb_shells", "gfx/sb_nails", "gfx/sb_rocket", "gfx/sb_cells",
"gfx/sb_armor1", "gfx/sb_armor2", "gfx/sb_armor3", "gfx/disc"
};

// 16x16 pixel icons for Information Bar
-string ibitems[6] = {
+string ibitems[6] =
+{
"gfx/sb_key1", "gfx/sb_key2", "gfx/sb_invis", "gfx/sb_invuln",
"gfx/sb_suit", "gfx/sb_quad"
};

// 8x16 pixel runes for Information Bar
-string ibrunes[4] = {
+string ibrunes[4] =
+{
"gfx/sb_sigil1", "gfx/sb_sigil2", "gfx/sb_sigil3", "gfx/sb_sigil4"
};

@@ -116,14 +97,20 @@ float flashtime[WPN_ICONS];

// Shotgun, SuperShotgun, Nailgun, SuperNailGun, GrenadeLauncher
// RocketLauncher, LightningGun
-string wpnnames[WPN_ICONS] = {
+string wpnnames[WPN_ICONS] =
+{
"shotgun", "sshotgun", "nailgun", "snailgun", "rlaunch",
"srlaunch", "lightng"
};
+
// OFF / ON gfx (reflects active weapon)
string wpnselect[2] = { "gfx/inv_", "gfx/inv2_" };
+
// Special flash set for when the player gets weapon
-string wpnflash[5] = { "gfx/inva1_","gfx/inva2_","gfx/inva3_","gfx/inva4_","gfx/inva5_" };
+string wpnflash[5] =
+{
+ "gfx/inva1_","gfx/inva2_","gfx/inva3_","gfx/inva4_","gfx/inva5_"
+};

//----------------------------------------------------------------------
// Frame 00-04 : Regular HP 100/80/60/40/20
@@ -133,64 +120,14 @@ string wpnflash[5] = { "gfx/inva1_","gfx/inva2_","gfx/inva3_","gfx/inva4_","gfx/
// Frame 12 : Invisibility Ring
// Frame 13 : Pentagram (invulnerability)
//----------------------------------------------------------------------
-string facetab[14] = {
+string facetab[14] =
+{
"gfx/face5", "gfx/face4", "gfx/face3", "gfx/face2", "gfx/face1",
"gfx/face_p5", "gfx/face_p4", "gfx/face_p3", "gfx/face_p2",
"gfx/face_p1",
"gfx/face_inv2", "gfx/face_quad", "gfx/face_invis", "gfx/face_invul2"
};

-//----------------------------------------------------------------------
-// Stubs for extra CSQC functions (not all supported)
-//----------------------------------------------------------------------
-// Can query or check anything types on the console here
-float(string str) CSQC_ConsoleCommand = {
- tokenize_console(str);
- return FALSE;
-};
-// Can query/check keyboard/mouse/joystick input with this function
-// For key events, scanx is one of the KEY_* values
-// chary is the character code (chr2str to shove it into a string)
-// For mouse events then x+y are the mouse delta/position values
-float(float evtype, float scanx, float chary, float devid) CSQC_InputEvent = {
- return FALSE;
-};
-// This is linked to client dmg_take / dmg_save / dmg_inflictor fields
-// returning TRUE will block the red flash damage stuff
-float(float save, float take, vector dir) CSQC_Parse_Damage = {
- painfinishtime = time + 0.2;
- return FALSE;
-};
-// Can query/check server MSG events
-// CSQC_Parse_Event is called when the client sees a
-// #define svcfte_cgamepacket (83) message from the server
-// Not supported for DP, is called from only QSS/FTE
-void() CSQC_Parse_Event = { };
-
-// Can intercept printed messages from the server (top of screen)
-// printlvl (text filtering) 0=low, 1=medium, 2=high, 3=chat
-// con_notifytime = amount of time the text remains on screen
-// ONLY define this function, if doing something with the text!!
-void(string printmsg, float printlvl) CSQC_Parse_Print = {
- print(printmsg);
-};
-
-// Running on the Server side of CSQC listening for commands back
-// This is never called on the client side of the progs
-void(string str) SV_ParseClientCommand = {
- local string ostr, cmd;
- // Save command string for later
- ostr = str;
- // Search for tokens in string
- tokenize_console(str);
- // Find the first argument of the command
- cmd = argv(0);
- // Is this my (AD CSQC) command?
- if (cmd == CSQC_PING) self.ext_csqc = TRUE;
- // Pass through original command
- else clientcommand(self, ostr);
-};
-
//======================================================================
// Display 24pixel numbers to HUD (cope with red version)
//----------------------------------------------------------------------
@@ -200,31 +137,44 @@ void(vector pos, float value, float threshhold) Hud_DrawNoFont24 =
local float disp_col, disp_len, disp_no;

// Make sure value is within range
- if (value < 0) value = 0;
- else if (value > 999) value = 999;
+ if (value < 0)
+ value = 0;
+ else if (value > 999)
+ value = 999;
+
// Work out which number colour to use
- if (value <= threshhold) disp_col = TRUE;
+ if (value <= threshhold)
+ disp_col = TRUE;

// Round number down (floor) and work out length
- val_str = ftos(floor(value));
- disp_len = strlen(val_str);
+ val_str = ftos (floor(value));
+ disp_len = strlen (val_str);
// Move to the lowest digit position first
pos_x = pos_x + (3 * HUDSIZE_24_x);

- while (disp_len > 0) {
+ while (disp_len > 0)
+ {
// Countdown early (range is 0-2, strlen returns 1-3)
disp_len = disp_len - 1;
+
// Move backward to display a digit
pos_x = pos_x - HUDSIZE_24_x;
+
// Convert str character to font index numbers
- disp_no = (str2chr(val_str, disp_len) - '0');
+ disp_no = (str2chr (val_str, disp_len) - '0');
+
// Double check for any wierd range issues
- if (disp_no < 0 || disp_no > 9) disp_no = 0;
+ if (disp_no < 0 || disp_no > 9)
+ disp_no = 0;
+
// Work out which number colour to use
- if (disp_col) disp_str = anumber[disp_no];
- else disp_str = number[disp_no];
+ if (disp_col)
+ disp_str = anumber[disp_no];
+ else
+ disp_str = number[disp_no];
+
// Draw number in correct (right-justified) position
- drawpic(pos, disp_str, HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos, disp_str, HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
}
};

@@ -236,23 +186,31 @@ void(vector pos, string num) Hud_DrawCharFont24 =
float i, c;
// Endless loop until end of string
// Keep moving draw pos forward (pos_x)
- for(i = 0; ; i++, pos_x += HUDSIZE_24_x) {
+ for (i = 0; ; i++, pos_x += HUDSIZE_24_x)
+ {
// Read next character from string
- c = str2chr(num, i);
+ c = str2chr (num, i);
// End of string found?
- if (!c) break;
+ if (!c)
+ break;
// Check for special characters
else if (c == ':' || c == '.')
- drawpic(pos, extrachar[0], HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos, extrachar[0], HUDSIZE_24, HUDRGB_DEF,
+ hudalpha, 0);
else if (c == '-')
- drawpic(pos, extrachar[1], HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos, extrachar[1], HUDSIZE_24, HUDRGB_DEF,
+ hudalpha, 0);
else if (c == '/')
- drawpic(pos, extrachar[2], HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos, extrachar[2], HUDSIZE_24, HUDRGB_DEF,
+ hudalpha, 0);
// Draw rest of the numbers
- else if (c >= '0' && c <= '9') {
+ else if (c >= '0' && c <= '9')
+ {
// Sanity check, make sure within range of array
- c = c - 48; if (c<0 || c>9) c=0;
- drawpic(pos, number[c], HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
+ c = c - 48;
+ if (c < 0 || c > 9) c = 0;
+ drawpic (pos, number[c], HUDSIZE_24, HUDRGB_DEF,
+ hudalpha, 0);
}
}
};
@@ -260,46 +218,57 @@ void(vector pos, string num) Hud_DrawCharFont24 =
//----------------------------------------------------------------------
// Draws small 8 pixel numbers to HUD (white/yellow/red text options)
//----------------------------------------------------------------------
-void(vector pos, float value, float digit, float zerofill, float fontcol) Hud_DrawNoFont8 =
+void(vector pos, float value, float digit, float zerofill, float fontcol)
+ Hud_DrawNoFont8 =
{
local string val_str;
local float disp_len, disp_no;

// Make sure value is within range
- if (value < 0) value = 0;
+ if (value < 0)
+ value = 0;
// Check max range against max digits
- else if (value > 999 && digit >= 3) value = 999;
- else if (value > 99 && digit == 2) value = 99;
- else if (value > 9 && digit <= 1) value = 9;
+ else if (value > 999 && digit >= 3)
+ value = 999;
+ else if (value > 99 && digit == 2)
+ value = 99;
+ else if (value > 9 && digit <= 1)
+ value = 9;

// Round number down (floor) and work out length
- val_str = ftos(floor(value));
- disp_len = strlen(val_str);
+ val_str = ftos (floor(value));
+ disp_len = strlen (val_str);

// Zero fill number?
- if (zerofill) {
- while (disp_len < digit) {
+ if (zerofill)
+ {
+ while (disp_len < digit)
+ {
// Keep adding more zero's
- val_str = strcat("0", val_str);
+ val_str = strcat ("0", val_str);
// Exit condition?
- disp_len = strlen(val_str);
+ disp_len = strlen (val_str);
}
}

// Move to the lowest digit position first
pos_x = pos_x + (digit * HUDSIZE_8_x);

- while (disp_len > 0) {
+ while (disp_len > 0)
+ {
// Countdown first (digit positions = 0-2)
disp_len = disp_len - 1;
// Move backward to display a digit
pos_x = pos_x - HUDSIZE_8_x;
// Convert character to number (font table index 48-57)
- disp_no = str2chr(val_str, disp_len);
- if (fontcol == HUDFONT_YELLOW) disp_no = disp_no - 30;
- else if (fontcol == HUDFONT_RED) disp_no = disp_no + 128;
+ disp_no = str2chr (val_str, disp_len);
+ if (fontcol == HUDFONT_YELLOW)
+ disp_no = disp_no - 30;
+ else if (fontcol == HUDFONT_RED)
+ disp_no = disp_no + 128;
// Draw character from ascii font table (right-justified)
- drawcharacter(pos, disp_no, HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ drawcharacter (pos, disp_no, HUDSIZE_8, HUDRGB_DEF,
+ hudalpha, 0);
}
};

@@ -312,31 +281,47 @@ void(vector pos) Hud_DrawFace =
local float hpframe;

// Start with InvRing as it has two states
- if (sitems & CSQC_INVISIBILITY) {
- // InvRing + Pentagram!?! WTF!?! SandyP E4 design!
- if (sitems & CSQC_INVULNERABILITY) face = facetab[10];
- // Just InvRing only
- else face = facetab[12];
+ if (sitems & CSQC_INVISIBILITY)
+ {
+ if (sitems & CSQC_INVULNERABILITY)
+ // InvRing + Pentagram!?! WTF!?! SandyP E4 design!
+ face = facetab[10];
+ else
+ // Just InvRing only
+ face = facetab[12];
}
- // Quad only
- else if (sitems & CSQC_QUAD) face = facetab[11];
- // Pentagram only
- else if (sitems & CSQC_INVULNERABILITY) face = facetab[13];
- // Regular face
- else {
+ else if (sitems & CSQC_QUAD)
+ {
+ // Quad only
+ face = facetab[11];
+ }
+ else if (sitems & CSQC_INVULNERABILITY)
+ {
+ // Pentagram only
+ face = facetab[13];
+ }
+ else
+ {
+ // Regular face
// Work out face based on HP (100/80/60/40/20)
- hpframe = floor(shealth / 20);
+ hpframe = floor (shealth / 20);
+
// Check for negative and upper (MegaHP) limits
- if (hpframe < 0) hpframe = 0;
- else if (hpframe > 4) hpframe = 4;
+ if (hpframe < 0)
+ hpframe = 0;
+ else if (hpframe > 4)
+ hpframe = 4;
+
// Check for any pain/flinch updates
- if (painfinishtime > time) hpframe = hpframe + 5;
+ if (painfinishtime > time)
+ hpframe = hpframe + 5;
+
// Final HP face
face = facetab[hpframe];
}

// Draw face - always 24x24 size, full rgb/alpha
- drawpic(pos, face, HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos, face, HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
};

//----------------------------------------------------------------------
@@ -352,35 +337,46 @@ static void(float num, vector pos) Hud_DrawWeapon =
// When the player gets a new weapon the time is reset
// This function will count the time difference for flashing
// Convert the flash time to a 0-10+ range
- flash = (time - flashtime[num])*10;
+ flash = (time - flashtime[num]) * 10;

// Has the flash happened twice? (finished)
- if (flash >= 10) {
+ if (flash >= 10)
+ {
// Work out if this weapon is currently selected
- if (sweapon == (1<<num)) prefix = wpnselect[1];
+ if (sweapon == (1 << num))
+ prefix = wpnselect[1];
// Default is no highlight
- else prefix = wpnselect[0];
+ else
+ prefix = wpnselect[0];
}
- // Flashing!
- else {
+ else
+ {
+ // Flashing!
// Is the flash into second phase?
- if (flash < 0) flash = 0;
- else if (flash >= 5) flash = flash - 5;
+ if (flash < 0)
+ flash = 0;
+ else if (flash >= 5)
+ flash = flash - 5;
+
// flash is only 0-4 frames
prefix = wpnflash[flash];
}
+
// Merge prefix type (defined above) to weapon filename
// Without string (str) functions this would involve a giant table
// This sorta assumes that CSQC is running on an advanced engine
// QSS/FTE/DP all support FTE_STRINGS extra str functions
- file_str = strcat(prefix, wpnnames[num]);
+ file_str = strcat (prefix, wpnnames[num]);

// Most weapons are 24 pixels wide (half of ammo above)
// As always there is an exception (lightning gun)
- if (num == WPN_WIDTHLG) gfx_size = HUDWPN_48;
- else gfx_size = HUDWPN_24;
+ if (num == WPN_WIDTHLG)
+ gfx_size = HUDWPN_48;
+ else
+ gfx_size = HUDWPN_24;
+
// Show weapon GFX (active/deactive/flashing)
- drawpic(pos, file_str, gfx_size, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos, file_str, gfx_size, HUDRGB_DEF, hudalpha, 0);
};

//======================================================================
@@ -389,42 +385,52 @@ static void(float num, vector pos) Hud_DrawWeapon =
void (vector pos, vector virtsize) Hud_DrawSBar =
{
// Draw primary HUD bar (Armour/Face/Health/Ammo)
- drawpic(pos, backgrd[0], HUDSIZE_320, HUDRGB_DEF, baralpha, 0);
+ drawpic (pos, backgrd[0], HUDSIZE_320, HUDRGB_DEF, baralpha, 0);

// Deal with Pentagram first, its a simple test/update
- if (sitems & CSQC_INVULNERABILITY) {
+ if (sitems & CSQC_INVULNERABILITY)
+ {
// Make sure 666 is in 24 pixel giant red numbers!
- Hud_DrawNoFont24(pos+[24,0], 666, 666);
+ Hud_DrawNoFont24 (pos + [24, 0], 666, 666);
// Draw a pentagram symbol in the armour HUD slot
- drawpic(pos, sbitems[7], HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos, sbitems[7], HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
}
- else {
+ else
+ {
// Show armour type/quantity active
- Hud_DrawNoFont24(pos+'24 0 0', getstatf(CLIENT_ARMOR), 25);
+ Hud_DrawNoFont24 (pos + '24 0 0', getstatf(CLIENT_ARMOR), 25);
// Only 3 armour types (green/yellow/red)
if (sitems & CSQC_ARMOR1)
- drawpic(pos, sbitems[4], HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos, sbitems[4], HUDSIZE_24, HUDRGB_DEF,
+ hudalpha, 0);
else if (sitems & CSQC_ARMOR2)
- drawpic(pos, sbitems[5], HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos, sbitems[5], HUDSIZE_24, HUDRGB_DEF,
+ hudalpha, 0);
else if (sitems & CSQC_ARMOR3)
- drawpic(pos, sbitems[6], HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos, sbitems[6], HUDSIZE_24, HUDRGB_DEF,
+ hudalpha, 0);
}

// Draw face + HP value
- Hud_DrawFace(pos+[112,0]);
- Hud_DrawNoFont24(pos+[136,0], shealth, 25);
+ Hud_DrawFace (pos + [112, 0]);
+ Hud_DrawNoFont24 (pos + [136, 0], shealth, 25);

// Only update ammo type/quantity if not using axe!
- if (sweapon != CSQC_AXE) {
- Hud_DrawNoFont24(pos+[248,0], getstatf(CLIENT_AMMO), 10);
+ if (sweapon != CSQC_AXE)
+ {
+ Hud_DrawNoFont24 (pos + [248, 0], getstatf(CLIENT_AMMO), 10);
if (sitems & CSQC_SHELLS)
- drawpic(pos+[224,0], sbitems[0], HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos + [224, 0], sbitems[0], HUDSIZE_24,
+ HUDRGB_DEF, hudalpha, 0);
else if (sitems & CSQC_NAILS)
- drawpic(pos+[224,0], sbitems[1], HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos + [224, 0], sbitems[1], HUDSIZE_24,
+ HUDRGB_DEF, hudalpha, 0);
else if (sitems & CSQC_ROCKETS)
- drawpic(pos+[224,0], sbitems[2], HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos + [224, 0], sbitems[2], HUDSIZE_24,
+ HUDRGB_DEF, hudalpha, 0);
else if (sitems & CSQC_CELLS)
- drawpic(pos+[224,0], sbitems[3], HUDSIZE_24, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos + [224, 0], sbitems[3], HUDSIZE_24,
+ HUDRGB_DEF, hudalpha, 0);
}
};

@@ -437,74 +443,109 @@ void (vector pos, vector br) Hud_DrawIBar =
local string player_frags;

// Draw background bar using scr_sbaralpha default
- drawpic(pos, backgrd[1], HUDSIZE_320, HUDRGB_DEF, baralpha, 0);
+ drawpic (pos, backgrd[1], HUDSIZE_320, HUDRGB_DEF, baralpha, 0);

// Always draw ammo scores
- Hud_DrawNoFont8(pos + [10,0], getstatf(CLIENT_SHELLS), 3, FALSE, HUDFONT_YELLOW);
- Hud_DrawNoFont8(pos + [58,0], getstatf(CLIENT_NAILS), 3, FALSE, HUDFONT_YELLOW);
- Hud_DrawNoFont8(pos + [106,0], getstatf(CLIENT_ROCKETS), 3, FALSE, HUDFONT_YELLOW);
- Hud_DrawNoFont8(pos + [154,0], getstatf(CLIENT_CELLS), 3, FALSE, HUDFONT_YELLOW);
+ Hud_DrawNoFont8 (pos + [10, 0], getstatf(CLIENT_SHELLS), 3,
+ FALSE, HUDFONT_YELLOW);
+ Hud_DrawNoFont8 (pos + [58, 0], getstatf(CLIENT_NAILS), 3,
+ FALSE, HUDFONT_YELLOW);
+ Hud_DrawNoFont8 (pos + [106, 0], getstatf(CLIENT_ROCKETS), 3,
+ FALSE, HUDFONT_YELLOW);
+ Hud_DrawNoFont8 (pos + [154, 0], getstatf(CLIENT_CELLS), 3,
+ FALSE, HUDFONT_YELLOW);

// Draw weapons and highlight current one
- if (sitems & CSQC_SHOTGUN) Hud_DrawWeapon(0, pos+[24*0,8]);
- if (sitems & CSQC_SUPER_SHOTGUN) Hud_DrawWeapon(1, pos+[24*1,8]);
- if (sitems & CSQC_NAILGUN) Hud_DrawWeapon(2, pos+[24*2,8]);
- if (sitems & CSQC_SUPER_NAILGUN) Hud_DrawWeapon(3, pos+[24*3,8]);
- if (sitems & CSQC_GRENADE_LAUNCHER) Hud_DrawWeapon(4, pos+[24*4,8]);
- if (sitems & CSQC_ROCKET_LAUNCHER) Hud_DrawWeapon(5, pos+[24*5,8]);
- if (sitems & CSQC_LIGHTNING) Hud_DrawWeapon(6, pos+[24*6,8]);
+ if (sitems & CSQC_SHOTGUN)
+ Hud_DrawWeapon (0, pos + [24 * 0, 8]);
+ if (sitems & CSQC_SUPER_SHOTGUN)
+ Hud_DrawWeapon (1, pos + [24 * 1, 8]);
+ if (sitems & CSQC_NAILGUN)
+ Hud_DrawWeapon (2, pos + [24 * 2, 8]);
+ if (sitems & CSQC_SUPER_NAILGUN)
+ Hud_DrawWeapon (3, pos + [24 * 3, 8]);
+ if (sitems & CSQC_GRENADE_LAUNCHER)
+ Hud_DrawWeapon (4, pos + [24 * 4, 8]);
+ if (sitems & CSQC_ROCKET_LAUNCHER)
+ Hud_DrawWeapon (5, pos + [24 * 5, 8]);
+ if (sitems & CSQC_LIGHTNING)
+ Hud_DrawWeapon (6, pos + [24 * 6, 8]);

// Draw inventory items
if (sitems & CSQC_KEY1)
- drawpic(pos+[192,8], ibitems[0], HUDSIZE_16, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos + [192, 8], ibitems[0], HUDSIZE_16, HUDRGB_DEF,
+ hudalpha, 0);
if (sitems & CSQC_KEY2)
- drawpic(pos+[208,8], ibitems[1], HUDSIZE_16, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos + [208, 8], ibitems[1], HUDSIZE_16, HUDRGB_DEF,
+ hudalpha, 0);
if (sitems & CSQC_INVISIBILITY)
- drawpic(pos+[224,8], ibitems[2], HUDSIZE_16, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos + [224, 8], ibitems[2], HUDSIZE_16, HUDRGB_DEF,
+ hudalpha, 0);
if (sitems & CSQC_INVULNERABILITY)
- drawpic(pos+[240,8], ibitems[3], HUDSIZE_16, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos + [240, 8], ibitems[3], HUDSIZE_16, HUDRGB_DEF,
+ hudalpha, 0);
if (sitems & CSQC_SUIT)
- drawpic(pos+[256,8], ibitems[4], HUDSIZE_16, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos + [256, 8], ibitems[4], HUDSIZE_16, HUDRGB_DEF,
+ hudalpha, 0);
if (sitems & CSQC_QUAD)
- drawpic(pos+[272,8], ibitems[5], HUDSIZE_16, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos + [272, 8], ibitems[5], HUDSIZE_16, HUDRGB_DEF,
+ hudalpha, 0);

// Draw Runes (special size + location)
if (sitems2 & CSQC_RUNE1)
- drawpic(pos+[288,8], ibrunes[0], HUDSIZE_816, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos + [288, 8], ibrunes[0], HUDSIZE_816, HUDRGB_DEF,
+ hudalpha, 0);
if (sitems2 & CSQC_RUNE2)
- drawpic(pos+[296,8], ibrunes[1], HUDSIZE_816, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos + [296, 8], ibrunes[1], HUDSIZE_816, HUDRGB_DEF,
+ hudalpha, 0);
if (sitems2 & CSQC_RUNE3)
- drawpic(pos+[304,8], ibrunes[2], HUDSIZE_816, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos + [304, 8], ibrunes[2], HUDSIZE_816, HUDRGB_DEF,
+ hudalpha, 0);
if (sitems2 & CSQC_RUNE4)
- drawpic(pos+[312,8], ibrunes[3], HUDSIZE_816, HUDRGB_DEF, hudalpha, 0);
+ drawpic (pos + [312, 8], ibrunes[3], HUDSIZE_816, HUDRGB_DEF,
+ hudalpha, 0);

//should probably show team scores, but this mimics vanilla
- if (deathmatch) {
+ if (deathmatch)
+ {
// Move to space above powerups
pos_x += 194;

// Loop through 4 players
- for (float i = -1; i >= -4; i--) {
+ for (float i = -1; i >= -4; i--)
+ {
// Read frag score of next player
- player_frags = getplayerkeyvalue(i, "frags");
+ player_frags = getplayerkeyvalue (i, "frags");
+
// No frags? stop loop
- if (player_frags == "") break;
+ if (player_frags == "")
+ break;
+
// Read deathmatch player top/bottom skin colours
- topcol = stov(getplayerkeyvalue(i, "topcolor_rgb"));
- botcol = stov(getplayerkeyvalue(i, "bottomcolor_rgb"));
+ topcol = stov (getplayerkeyvalue(i, "topcolor_rgb"));
+ botcol = stov (getplayerkeyvalue(i, "bottomcolor_rgb"));
+
// Draw skin colours (alpha was 0.75 hardcoded)
- drawfill(pos+[0,1], [28,3], topcol, 0.75, 0);
- drawfill(pos+[0,4], [28,4], botcol, 0.75, 0);
+ drawfill (pos + [0, 1], [28, 3], topcol, 0.75, 0);
+ drawfill (pos + [0, 4], [28, 4], botcol, 0.75, 0);
+
// Draw frag score (New global small font function)
- Hud_DrawNoFont8(pos + '2 0 0', stof(player_frags), 3, FALSE, HUDFONT_WHITE);
+ Hud_DrawNoFont8 (pos + '2 0 0', stof(player_frags), 3,
+ FALSE, HUDFONT_WHITE);
+
// Find player entity attached to this HUD
- if (player_localentnum == stof(getplayerkeyvalue(i, "viewentity"))) {
+ if (player_localentnum == stof(getplayerkeyvalue(
+ i, "viewentity")))
+ {
// special characters = []
- drawcharacter(pos+[-4,0], 0xe010, HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
- drawcharacter(pos+[24,0], 0xe011, HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ drawcharacter (pos + [-4, 0], 0xe010,
+ HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ drawcharacter (pos + [24, 0], 0xe011,
+ HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
}
+
// Move forward to next hud space
- pos_x += 8*4;
+ pos_x += 8 * 4;
}
}
};
@@ -512,35 +553,46 @@ void (vector pos, vector br) Hud_DrawIBar =
//======================================================================
// Scoreboard Bar (shows monster/secret quantities and map info)
//----------------------------------------------------------------------
-void(vector pos, float bx, float by, float bwidth, float bheight, float pixelspeed, string draw_str) Hud_ScrollTextBox =
+void(vector pos, float bx, float by, float bwidth, float bheight,
+ float pixelspeed, string draw_str) Hud_ScrollTextBox =
{
local float str_width, str_double, str_speed;
local string wide_str;

// draw debug visual box to show area on screen
- //drawfill( pos+[bx,by], [bwidth,bheight], HUDRGB_DEF, 0.1, 0);
+ //drawfill (pos + [bx, by], [bwidth, bheight], HUDRGB_DEF, 0.1, 0);

// Find out width of string in pixels (using font 8)
- str_width = stringwidth( draw_str, TRUE, HUDSIZE_8);
+ str_width = stringwidth (draw_str, TRUE, HUDSIZE_8);
+
// String less than window width?
- if (str_width < bwidth) {
+ if (str_width < bwidth)
+ {
// Center the map name string in the box area
str_double = (bwidth - str_width) / 2;
+
// Display string normally (no scrolling required)
- drawstring( pos+[bx+str_double, by], draw_str, HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ drawstring (pos + [bx + str_double, by], draw_str, HUDSIZE_8,
+ HUDRGB_DEF, hudalpha, 0);
}
- else {
+ else
+ {
// Create double length string with boundary marker
- wide_str = strcat(draw_str, " /// ", draw_str);
+ wide_str = strcat (draw_str, " /// ", draw_str);
+
// Setup clip (scissor) area for exclusive drawing
- drawsetcliparea( pos_x + bx, pos_y + by, bwidth, bheight);
- str_double = stringwidth( wide_str, TRUE, HUDSIZE_8);
+ drawsetcliparea (pos_x + bx, pos_y + by, bwidth, bheight);
+ str_double = stringwidth (wide_str, TRUE, HUDSIZE_8);
+
// create offset of string to make it look like its scrolling
- str_speed = mod(cltime * pixelspeed, (str_double - str_width));
+ str_speed = mod (cltime * pixelspeed, (str_double - str_width));
+
// draw string (with offset) inside of clip (scissor) area only
- drawstring( pos+[bx - str_speed, by], wide_str, HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ drawstring (pos + [bx - str_speed, by], wide_str, HUDSIZE_8,
+ HUDRGB_DEF, hudalpha, 0);
+
// Reset clip string area to default
- drawresetcliparea();
+ drawresetcliparea ();
}
};

@@ -553,27 +605,42 @@ void(vector pos) Hud_QSScores_SBar =
local float digit;

// Clear status bar ready for map info/scores
- drawpic(pos, backgrd[2], HUDSIZE_320, HUDRGB_DEF, baralpha, 0);
+ drawpic (pos, backgrd[2], HUDSIZE_320, HUDRGB_DEF, baralpha, 0);
+
// Display headings
- drawstring(pos+[8,12], "Kills:", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
- drawstring(pos+[80,12], "/", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
- drawstring(pos+[132,12], "Skill ", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
- drawstring(pos+[208,12], "Secrets:", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
- drawstring(pos+[288,12], "/", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ drawstring (pos + [8, 12], "Kills:", HUDSIZE_8, HUDRGB_DEF,
+ hudalpha, 0);
+ drawstring (pos + [80, 12], "/", HUDSIZE_8, HUDRGB_DEF,
+ hudalpha, 0);
+ drawstring (pos + [132, 12], "Skill ", HUDSIZE_8, HUDRGB_DEF,
+ hudalpha, 0);
+ drawstring (pos + [208, 12], "Secrets:", HUDSIZE_8, HUDRGB_DEF,
+ hudalpha, 0);
+ drawstring (pos + [288, 12], "/", HUDSIZE_8, HUDRGB_DEF,
+ hudalpha, 0);
+
// Display monster/secret totals
- Hud_DrawNoFont8(pos+[56,12], getstatf(CLIENT_KILLEDMONSTERS), 3, FALSE, HUDFONT_WHITE);
- if (getstatf(CLIENT_TOTALMONSTERS) < 100) digit = 2;
- else digit = 3;
- Hud_DrawNoFont8(pos+[88,12], getstatf(CLIENT_TOTALMONSTERS), digit, FALSE, HUDFONT_WHITE);
- Hud_DrawNoFont8(pos+[272,12], getstatf(CLIENT_FOUNDSECRETS), 2, FALSE, HUDFONT_WHITE);
- Hud_DrawNoFont8(pos+[296,12], getstatf(CLIENT_TOTALSECRETS), 2, FALSE, HUDFONT_WHITE);
+ Hud_DrawNoFont8 (pos + [56, 12], getstatf(CLIENT_KILLEDMONSTERS), 3,
+ FALSE, HUDFONT_WHITE);
+ if (getstatf(CLIENT_TOTALMONSTERS) < 100)
+ digit = 2;
+ else
+ digit = 3;
+ Hud_DrawNoFont8 (pos + [88, 12], getstatf(CLIENT_TOTALMONSTERS), digit,
+ FALSE, HUDFONT_WHITE);
+ Hud_DrawNoFont8 (pos + [272, 12], getstatf(CLIENT_FOUNDSECRETS), 2,
+ FALSE, HUDFONT_WHITE);
+ Hud_DrawNoFont8 (pos + [296, 12], getstatf(CLIENT_TOTALSECRETS), 2,
+ FALSE, HUDFONT_WHITE);
+
// Display map skill level
- skill_str = autocvar(skill, "1");
- drawstring(pos+[180,12], skill_str, HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ skill_str = autocvar (skill, "1");
+ drawstring (pos + [180, 12], skill_str, HUDSIZE_8, HUDRGB_DEF,
+ hudalpha, 0);

// Level designers Map name + File name
- map_str = strcat(world.message, " (", mapname, ")");
- Hud_ScrollTextBox(pos, 8, 4, 304, 8, 16, map_str);
+ map_str = strcat (world.message, " (", mapname, ")");
+ Hud_ScrollTextBox (pos, 8, 4, 304, 8, 16, map_str);
};

//----------------------------------------------------------------------
@@ -584,26 +651,30 @@ void(vector pos) Hud_IDScores_SBar =
local float nsecs, nmins;

// Clear status bar ready for map info/scores
- drawpic(pos, backgrd[2], HUDSIZE_320, HUDRGB_DEF, baralpha, 0);
+ drawpic (pos, backgrd[2], HUDSIZE_320, HUDRGB_DEF, baralpha, 0);
// Display headings
- drawstring(pos+[8,4], "Monsters:", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
- drawstring(pos+[104,4], "/", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
- drawstring(pos+[8,12], "Secrets :", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
- drawstring(pos+[104,12], "/", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
- drawstring(pos+[184,4], "Time :", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
- drawstring(pos+[256,4], ":", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ drawstring (pos+[8,4], "Monsters:", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ drawstring (pos+[104,4], "/", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ drawstring (pos+[8,12], "Secrets :", HUDSIZE_8, HUDRGB_DEF, hudalpha,0);
+ drawstring (pos+[104,12], "/", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ drawstring (pos+[184,4], "Time :", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ drawstring (pos+[256,4], ":", HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
// Display monster/secret totals
- Hud_DrawNoFont8(pos+[80,4], getstatf(CLIENT_KILLEDMONSTERS), 3, FALSE, HUDFONT_WHITE);
- Hud_DrawNoFont8(pos+[112,4], getstatf(CLIENT_TOTALMONSTERS), 3, FALSE, HUDFONT_WHITE);
- Hud_DrawNoFont8(pos+[80,12], getstatf(CLIENT_FOUNDSECRETS), 3, FALSE, HUDFONT_WHITE);
- Hud_DrawNoFont8(pos+[112,12], getstatf(CLIENT_TOTALSECRETS), 3, FALSE, HUDFONT_WHITE);
+ Hud_DrawNoFont8 (pos + [80, 4], getstatf(CLIENT_KILLEDMONSTERS), 3,
+ FALSE, HUDFONT_WHITE);
+ Hud_DrawNoFont8 (pos + [112, 4], getstatf(CLIENT_TOTALMONSTERS), 3,
+ FALSE, HUDFONT_WHITE);
+ Hud_DrawNoFont8 (pos + [80, 12], getstatf(CLIENT_FOUNDSECRETS), 3,
+ FALSE, HUDFONT_WHITE);
+ Hud_DrawNoFont8 (pos + [112, 12], getstatf(CLIENT_TOTALSECRETS), 3,
+ FALSE, HUDFONT_WHITE);
// Work out time passed
- nmins = floor(time/60);
- nsecs = floor(time - nmins*60);
- Hud_DrawNoFont8(pos+[232,4], nmins, 3, FALSE, HUDFONT_WHITE);
- Hud_DrawNoFont8(pos+[264,4], nsecs, 2, TRUE, HUDFONT_WHITE);
+ nmins = floor (time / 60);
+ nsecs = floor (time - nmins * 60);
+ Hud_DrawNoFont8 (pos + [232, 4], nmins, 3, FALSE, HUDFONT_WHITE);
+ Hud_DrawNoFont8 (pos + [264, 4], nsecs, 2, TRUE, HUDFONT_WHITE);
// Level designers Map name
- Hud_ScrollTextBox(pos, 140, 12, 176, 8, 16, world.message);
+ Hud_ScrollTextBox (pos, 140, 12, 176, 8, 16, world.message);
};

//======================================================================
@@ -612,17 +683,17 @@ void(vector pos) Hud_IDScores_SBar =
vector(string picname, float height) Hud_AspectSize =
{
local vector sz;
- sz = drawgetimagesize(picname);
- return [sz_x * height/sz_y, height];
+ sz = drawgetimagesize (picname);
+ return [sz_x * height / sz_y, height];
};

//----------------------------------------------------------------------
-void(string picname, float screenwidth, vector pos, float height) Hud_CentrePic =
+void(string picname, float scrwidth, vector pos, float height) Hud_CentrePic =
{
local vector sz;
- sz = Hud_AspectSize(picname, height);
- pos_x += (screenwidth-sz_x)/2;
- drawpic(pos, picname, sz, HUDRGB_DEF, hudalpha, 0);
+ sz = Hud_AspectSize (picname, height);
+ pos_x += (scrwidth - sz_x) / 2;
+ drawpic (pos, picname, sz, HUDRGB_DEF, hudalpha, 0);
};

//----------------------------------------------------------------------
@@ -636,63 +707,78 @@ void(vector virtmin, vector virtsize) Hud_DMScoreboard =
pos = virtmin;

// Check for 16 players?
- player_name = getplayerkeyvalue(-16, "name");
- if (player_name == "") pos_y += (virtsize_y-200)/2;
+ player_name = getplayerkeyvalue (-16, "name");
+ if (player_name == "")
+ pos_y += (virtsize_y - 200) / 2;

// Only draw the header when its not a really big game
- player_name = getplayerkeyvalue(-24, "name");
- if (player_name == "") {
+ player_name = getplayerkeyvalue (-24, "name");
+ if (player_name == "")
+ {
pos_y += 8;
// Display header (ranking.lmp) gfx for DM scoreboard
- Hud_CentrePic(backlmp[0], virtsize_x, pos, 24);
+ Hud_CentrePic (backlmp[0], virtsize_x, pos, 24);
// A double update of Y, only spike knows why!?!
- pos_y += 24; pos_y += 10;
+ pos_y += 24;
+ pos_y += 10;
}

// Another double X update, no idea why!
- pos_x += (virtsize_x-320)/2;
+ pos_x += (virtsize_x - 320) / 2;
pos_x += 80;

- //negative numbers are players sorted by frags.
- for (float i = -1; ; i--, pos_y += 10) {
+ // negative numbers are players sorted by frags.
+ for (float i = -1; ; i--, pos_y += 10)
+ {
// Check for next player name
- player_name = getplayerkeyvalue(i, "name");
+ player_name = getplayerkeyvalue (i, "name");
// No more in list, end loop
- if (player_name == "") break;
+ if (player_name == "")
+ break;

// Read player stats (frag/ping)
- isspec = stof(getplayerkeyvalue(i, "*spectator"));
- player_frags = getplayerkeyvalue(i, "frags");
- player_ping = getplayerkeyvalue(i, "ping");
+ isspec = stof (getplayerkeyvalue(i, "*spectator"));
+ player_frags = getplayerkeyvalue (i, "frags");
+ player_ping = getplayerkeyvalue (i, "ping");
// Read deathmatch player top/bottom skin colours
- topcol = stov(getplayerkeyvalue(i, "topcolor_rgb"));
- botcol = stov(getplayerkeyvalue(i, "bottomcolor_rgb"));
+ topcol = stov (getplayerkeyvalue(i, "topcolor_rgb"));
+ botcol = stov (getplayerkeyvalue(i, "bottomcolor_rgb"));

// Re-format the player name (no case conversion, force red)
- player_name = strconv(0,2,2, player_name);
+ player_name = strconv (0,2,2, player_name);
// Draw frag score (New global small font function)
- Hud_DrawNoFont8(pos-[8*5,0], stof(player_ping), 3, FALSE, HUDFONT_WHITE);
+ Hud_DrawNoFont8 (pos - [8 * 5, 0], stof(player_ping), 3,
+ FALSE, HUDFONT_WHITE);

// Which type of player? Spectator or Active?
if (isspec)
- drawstring(pos+[4,0], "spec", [8,8], HUDRGB_DEF, hudalpha, 0);
+ {
+ drawstring (pos + [4, 0], "spec", [8, 8],
+ HUDRGB_DEF, hudalpha, 0);
+ }
else
{
// Draw skin colours (alpha was 0.75 hardcoded)
- drawfill(pos+[0,0], [40,4], topcol, 0.75, 0);
- drawfill(pos+[0,4], [40,4], botcol, 0.75, 0);
+ drawfill (pos + [0, 0], [40, 4], topcol, 0.75, 0);
+ drawfill (pos + [0, 4], [40, 4], botcol, 0.75, 0);

// Draw frag score (New global small font function)
- Hud_DrawNoFont8(pos+[8,0], stof(player_frags), 3, FALSE, HUDFONT_WHITE);
+ Hud_DrawNoFont8 (pos + [8, 0], stof(player_frags), 3,
+ FALSE, HUDFONT_WHITE);
// Find player entity attached to this HUD
- if (player_localentnum == stof(getplayerkeyvalue(i, "viewentity"))) {
+ if (player_localentnum == stof(getplayerkeyvalue(i,
+ "viewentity")))
+ {
// special characters = []
- drawcharacter(pos+[0,0], 0xe010, HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
- drawcharacter(pos+[32,0], 0xe011, HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ drawcharacter (pos + [0, 0], 0xe010,
+ HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ drawcharacter (pos + [32, 0], 0xe011,
+ HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
}
}
// Finally draw player name
- drawstring(pos+[64,0], player_name, HUDSIZE_8, HUDRGB_DEF, hudalpha, 0);
+ drawstring (pos + [64, 0], player_name, HUDSIZE_8,
+ HUDRGB_DEF, hudalpha, 0);
}
};

@@ -703,33 +789,42 @@ void(vector virtmin, vector virtsize) Hud_Intermission =
{
local vector pos;
// Create positions based on virtual screen
- pos = virtmin + (virtsize-[320,200])/2;
+ pos = virtmin + (virtsize - [320, 200]) / 2;

// Draw Intermission title and table info (Time/secret/kill)
- Hud_CentrePic(backlmp[1], 320, pos+[0,24], 24);
- drawpic(pos+[0,56], backlmp[2], [160,144], HUDRGB_DEF, hudalpha, 0);
+ Hud_CentrePic (backlmp[1], 320, pos + [0, 24], 24);
+ drawpic (pos + [0,56], backlmp[2], [160,144], HUDRGB_DEF, hudalpha, 0);

// Generate complete string and then draw 1 character at time
// Uses Sprintf function to feed values into final string
// This function should be supported by Advanced engines
- Hud_DrawCharFont24(pos+[144, 64], sprintf("%3.0f:%02.0f", intermission_time/60, intermission_time%60));
- Hud_DrawCharFont24(pos+[144, 104], sprintf("%3.0f/%.0f", getstatf(CLIENT_FOUNDSECRETS), getstatf(CLIENT_TOTALSECRETS)));
- Hud_DrawCharFont24(pos+[144, 144], sprintf("%3.0f/%.0f", getstatf(CLIENT_KILLEDMONSTERS), getstatf(CLIENT_TOTALMONSTERS)));
+ Hud_DrawCharFont24 (pos + [144, 64], sprintf("%3.0f:%02.0f",
+ intermission_time / 60, intermission_time % 60));
+ Hud_DrawCharFont24 (pos + [144, 104],
+ sprintf ("%3.0f/%.0f",
+ getstatf (CLIENT_FOUNDSECRETS),
+ getstatf (CLIENT_TOTALSECRETS)
+ )
+ );
+ Hud_DrawCharFont24 (pos + [144, 144],
+ sprintf ("%3.0f/%.0f",
+ getstatf (CLIENT_KILLEDMONSTERS),
+ getstatf (CLIENT_TOTALMONSTERS)
+ )
+ );
};

//======================================================================
-// Speedometer CEV
+// Speedometer -- CEV
//----------------------------------------------------------------------
void(vector pos) Hud_Speedometer =
{
local vector v;

- // requires support in ssqc WorldSpawn
- v_x = getstatf(CLIENT_VELOCITY_X);
- v_y = getstatf(CLIENT_VELOCITY_Y);
- v_z = 0;
+ // fancy -- CEV
+ v = [player_local.velocity_x, player_local.velocity_y, 0];

- Hud_DrawNoFont8(pos, vlen (v), 3, FALSE, HUDFONT_WHITE);
+ Hud_DrawNoFont8 (pos, vlen(v), 3, FALSE, HUDFONT_WHITE);
};

//======================================================================
@@ -748,34 +843,39 @@ void(vector virtsize, float showscores) CSQC_DrawHud =
// progs and csprogs as they are not connected in VM space
// By default CSQC has 30 (most commonly used) parameters setup
// Unfortunately some of them need to be converted (bitswapped)
- // to make them reaable again (I blame spike for this mess)
+ // to make them readable again (I blame spike for this mess)
// The downside to this bitswapping mess is that the serverflags
// is not passed to CSQC completely, only the first 4bits (runes)
//------------------------------------------------------------------
- sitems = getstatbits(CLIENT_ITEMS, 0, 23);
- sitems2 = getstatbits(CLIENT_ITEMS, 23, 9);
- sweapon = getstatf(CLIENT_ACTIVEWEAPON);
- shealth = getstatf(CLIENT_HEALTH);
+ sitems = getstatbits (CLIENT_ITEMS, 0, 23);
+ sitems2 = getstatbits (CLIENT_ITEMS, 23, 9);
+ sweapon = getstatf (CLIENT_ACTIVEWEAPON);
+ shealth = getstatf (CLIENT_HEALTH);

// Don't show HUD, intermission or dead
- if (intermission || shealth <= 0) return;
+ if (intermission || shealth <= 0)
+ return;

- //------------------------------------------------------------------
+ //--------------------------------------------------------------
// Read console variable for background HUD alpha
- baralpha = cvar("scr_sbaralpha");
- if (baralpha == 0) baralpha = 0.75;
+ baralpha = cvar ("scr_sbaralpha");
+ if (baralpha == 0)
+ baralpha = 0.75;
// Default is 1 for everything else
hudalpha = 1;

- //------------------------------------------------------------------
+ //--------------------------------------------------------------
// Check if any weapons have been added to the inventory
// Update time so the flash function can detect it
// Check for player count for splitscreen!?! QSS/FTE feature
- if (numclientseats <= 1) {
+ if (numclientseats <= 1)
+ {
// Player alive and inventory changd?
- if (shealth && sitems != oitems) {
+ if (shealth && sitems != oitems)
+ {
// Go through all weapon flash counters
- for (i = 0; i < WPN_ICONS; i++) {
+ for (i = 0; i < WPN_ICONS; i++)
+ {
// Found weapon and its new?
if ((sitems & (1<<i)) && !(oitems & (1<<i)))
// Reset timer
@@ -784,175 +884,62 @@ void(vector virtsize, float showscores) CSQC_DrawHud =
}
}

- //------------------------------------------------------------------
+ //--------------------------------------------------------------
// Find out how much of the HUD is being displayed
// 100 = InfoBar & StatusBar (ALL=Default)
// 110 = StatusBar Only
// 120 = Speedometer
// 130 = Nothing
- //------------------------------------------------------------------
+ //--------------------------------------------------------------
+
// Read current HUD size
- hudviewsize = cvar("viewsize");
+ hudviewsize = cvar ("viewsize");
+
// Any HUD to display?
- if (hudviewsize < 130) {
+ if (hudviewsize < 130)
+ {
// Override scoreboard - check if no player health
- if (shealth <= 0) showscores = TRUE;
+ if (shealth <= 0)
+ showscores = TRUE;
+
// Find out mid point of screen
- pos_x = (virtsize_x-320)/2;
+ pos_x = (virtsize_x - 320) / 2;
pos_y = virtsize_y;
pos_z = 0;

// trying to center the speedometer display just below
// the crosshair. This doesn't seem to be right but it
- // works on my 960x720 window. CEV.
- pos_speedo_x = virtsize_x/2.0;
- pos_speedo_y = virtsize_y/2.0;
+ // works on my 960x720 window. -- CEV.
+ pos_speedo_x = virtsize_x / 2.0;
+ pos_speedo_y = virtsize_y / 2.0;
pos_speedo_z = 0;
- Hud_Speedometer(pos_speedo - [8*1.5,-8]);
- if (hudviewsize < 120) {
+ Hud_Speedometer (pos_speedo - [ 8 * 1.5, -8]);
+
+ if (hudviewsize < 120)
+ {
// Either show Sbar or Scores (bars are centered)
- if (showscores) Hud_QSScores_SBar(pos - '0 24 0');
- else Hud_DrawSBar(pos - '0 24 0', virtsize);
+ if (showscores)
+ Hud_QSScores_SBar (pos - '0 24 0');
+ else
+ Hud_DrawSBar (pos - '0 24 0', virtsize);
}
+
// Can the Info Bar be displayed?
if (hudviewsize < 110)
- Hud_DrawIBar(pos - '0 48 0', virtsize);
+ Hud_DrawIBar (pos - '0 48 0', virtsize);
}
};

//----------------------------------------------------------------------
void(vector virtsize, float showscores) CSQC_DrawScores =
{
- shealth = getstatf(CLIENT_HEALTH);
- if (intermission || showscores || shealth <= 0) {
- if (deathmatch) Hud_DMScoreboard('0 0 0', virtsize);
- else if (intermission) Hud_Intermission('0 0 0', virtsize);
- }
-};
-
-//----------------------------------------------------------------------
-void(float vwidth, float vheight, float notmenu) CSQC_UpdateView =
-{
- local vector ssize;
- ssize_x = vwidth; ssize_y = vheight; ssize_z = 0;
-
- // Is the CSQC functionality enabled/disabled?
- nocsqc = cvar("cl_nocsqc");
-
- clearscene();
- addentities(MASK_ENGINE|MASK_VIEWMODEL);
- setproperty(VF_MIN, '0 0');
- setproperty(VF_SIZE, ssize);
- // If hud is disabled, draw engine hud instead
- setproperty(VF_DRAWENGINESBAR, nocsqc);
- setproperty(VF_DRAWCROSSHAIR, TRUE);
- renderscene();
-
- // Revert back to using engine HUD?
- if (nocsqc > 0) return;
-
- // Required for DP engine
- if (detectDP == TRUE) {
- ssize_x = cvar("vid_conwidth");
- ssize_y = cvar("vid_conheight");
+ shealth = getstatf (CLIENT_HEALTH);
+
+ if (intermission || showscores || shealth <= 0)
+ {
+ if (deathmatch)
+ Hud_DMScoreboard ('0 0 0', virtsize);
+ else if (intermission)
+ Hud_Intermission ('0 0 0', virtsize);
}
-
- // Used on intermission screen later
- if (!intermission) intermission_time = time;
- // Read deathmatch variable and create csprogs coop variable
- // csprogs has no knowledge of the coop variable
- deathmatch = stof(serverkey("deathmatch"));
- coop = !deathmatch && maxclients > 1;
-
- // Draw the HUDs and scoreboards
- CSQC_DrawHud(ssize, sb_showscores);
- CSQC_DrawScores(ssize, sb_showscores);
-};
-
-//----------------------------------------------------------------------
-// Registers HUD gfx images (all setup in string arrays)
-//----------------------------------------------------------------------
-void(float apilevel, string enginename, float engineversion) CSQC_Init =
-{
- local float i, wadonly;
-
- // Is the CSQC functionality enabled/disabled?
- nocsqc = cvar("cl_nocsqc");
- // Revert back to using engine HUD?
- if (nocsqc > 0) return;
-
- // Send ping back to server that CSQC client is alive
- // This can be used on the server side to detect CSQC
- // and change functions for new features
- localcmd(strcat("cmd ", CSQC_PING, "\n"));
-
- // precache from gfx.wad ONLY!?!
- wadonly = TRUE;
-
- // Cache all string tables
- for (i = 0; i < 14; i++) {
- // HUD background images (320 wide+)
- if (i < backgrd.length) precache_pic(backgrd[i], wadonly);
- // Large 24x24 brown/red numbers
- if (i < number.length) {
- precache_pic(number[i], wadonly);
- precache_pic(anumber[i], wadonly);
- }
- // Large 24x24 extra font characters (intermission)
- if (i < extrachar.length) precache_pic(extrachar[i], wadonly);
- // Large 24x24 player face
- if (i < facetab.length) precache_pic(facetab[i], wadonly);
- // Large 24x24 icons
- if (i < sbitems.length) precache_pic(sbitems[i], wadonly);
- // Small 16x16 icons
- if (i < ibitems.length) precache_pic(ibitems[i], wadonly);
- // Special 8x16 runes
- if (i < ibrunes.length) precache_pic(ibrunes[i], wadonly);
- // All weapon setups (on/off/flashing)
- if (i < wpnnames.length) {
- precache_pic(strcat(wpnselect[0], wpnnames[i]),wadonly);
- precache_pic(strcat(wpnselect[1], wpnnames[i]),wadonly);
- precache_pic(strcat(wpnflash[0], wpnnames[i]), wadonly);
- precache_pic(strcat(wpnflash[1], wpnnames[i]), wadonly);
- precache_pic(strcat(wpnflash[2], wpnnames[i]), wadonly);
- precache_pic(strcat(wpnflash[3], wpnnames[i]), wadonly);
- precache_pic(strcat(wpnflash[4], wpnnames[i]), wadonly);
- }
- }
-};
-
-//----------------------------------------------------------------------
-// Wrapper for CSQC_Init to try and detect DP engine
-//----------------------------------------------------------------------
-__wrap void(float apilevel, string enginename, float engineversion) CSQC_Init =
-{
- // Try to detect DP engine (needed for CSQC_UpdateView later)
- if (!apilevel && !enginename && !engineversion) detectDP = TRUE;
- // Execute previous CSQC_Init function
- prior(apilevel, enginename, engineversion);
-
- registercommand("+showscores");
- registercommand("+showscores");
- registercommand("+showteamscores");
- registercommand("+showteamscores");
-};
-
-//----------------------------------------------------------------------
-// Wrapper for CSQC_ConsoleCommand to show different scoreboards
-//----------------------------------------------------------------------
-__wrap float(string str) CSQC_ConsoleCommand =
-{
- if (prior(str))
- return TRUE;
- string c = argv(0);
- if (c == "+showscores")
- sb_showscores |= 1;
- else if (c == "-showscores")
- sb_showscores &~= 1;
- else if (c == "+showteamscores")
- sb_showscores |= 2;
- else if (c == "-showteamscores")
- sb_showscores &~= 2;
- else return FALSE;
- return TRUE;
};

Return to the top of this page or return to the overview of this repo.

Diff qc/csqc/csqc_player.qc

diff --git a/qc/csqc/csqc_player.qc b/qc/csqc/csqc_player.qc
new file mode 100644
index 0000000..ecadb51
--- /dev/null
+++ b/qc/csqc/csqc_player.qc
@@ -0,0 +1,258 @@
+//==============================================================================
+// CSQC PLAYER MOVEMENT & PREDICTION
+//
+// This is based on code by Eukara [1] and the CSQCTest code shipped with
+// FTEQW [2].
+//
+// [1]: https://icculus.org/~marco/quakec/csqc/prediction.html
+// [2]: https://sourceforge.net/p/fteqw/code/HEAD/tree/trunk/quakec/csqctest/src
+//==============================================================================
+
+//======================================================================
+// No-op function for customphysics
+//----------------------------------------------------------------------
+void() Empty =
+{
+};
+
+//======================================================================
+// PlayerResetPrediction
+//
+// was Pred_ResetPlayerPrediction in CSQCTest cs/prediction.qc
+//----------------------------------------------------------------------
+void(entity ent) PlayerResetPrediction =
+{
+ ent.origin = player_org;
+ ent.velocity = player_vel;
+ ent.pmove_flags = player_pmflags;
+
+ // +1 because the received frame has the move already done (server side)
+ pmove_frame = player_sequence + 1;
+
+ if (pmove_frame < clientcommandframe - 128)
+ // avoid an infinite loop
+ pmove_frame = clientcommandframe - 128;
+};
+
+//======================================================================
+// PlayerRunMovement
+//
+// was Pred_RunMovement in CSQCTest cs/prediction.qc
+//----------------------------------------------------------------------
+void(entity ent, float endframe) PlayerRunMovement =
+{
+ if (servercommandframe >= player_sequence + 63)
+ {
+ // we're meant to be updating the player faster than
+ // this. hopefully its just that we're throttled...
+
+ // you can comment out this block and the player will
+ // continue to be predicted locally. But its best to
+ // freeze them
+ player_sequence = servercommandframe - 63;
+ return;
+ }
+
+ PlayerResetPrediction (ent);
+
+ if (getstatf(STAT_HEALTH) <= 0)
+ {
+ // dead, so don't run prediction. :D
+ pmove_frame = clientcommandframe;
+ if (!getinputstate(pmove_frame - 1))
+ {
+ // no-op ? -- CEV
+ }
+ return;
+ }
+
+ if (getinputstate(pmove_frame - 1))
+ // from CSQCTest; what is this doing? -- CEV;
+ ent.pmove_flags |= PMF_JUMP_HELD;
+
+ while (pmove_frame <= endframe)
+ {
+ if (!getinputstate(pmove_frame))
+ {
+ // no input from client
+ pmove_frame++;
+ continue;
+ }
+
+ if (input_timelength <= 0)
+ {
+ // partial frame / incomplete input packet
+ pmove_frame++;
+ continue;
+ }
+
+ // for testing
+ // runstandardplayerphysics (ent);
+ // for real
+ PM_Move (ent);
+ pmove_frame++;
+ }
+
+ // add anything that was applied after (for low packet
+ // rate protocols)
+ input_angles = view_angles;
+};
+
+//======================================================================
+// PlayerPreDraw
+//
+// Incorporates Pred_UpdateLocalMovement from CSQCTest.
+//----------------------------------------------------------------------
+float() PlayerPreDraw =
+{
+ local float viewheight;
+
+ if (self.entnum != player_localentnum)
+ {
+ self.renderflags = 0;
+ }
+ else
+ {
+ PlayerRunMovement (self, clientcommandframe);
+
+ if (self.origin_z >= player_step_oldz + 8 &&
+ self.origin_z < player_step_oldz + 24 &&
+ self.velocity_z == 0)
+ {
+ // evaluate out the remaining old step
+ if (player_steptime - time > 0)
+ player_step = (player_steptime - time) *
+ STEPTIME * player_step;
+ else
+ player_step = 0;
+
+ // work out the new step
+ player_step += (player_step_oldz - self.origin_z);
+ player_steptime = time + 1 / STEPTIME;
+ }
+ player_step_oldz = self.origin_z;
+
+ // allow the user to move the viewheight down 6 units so
+ // it's at +16, where projectiles come from.
+ viewheight = autocvar (v_viewheight, 0);
+ if (viewheight < -7)
+ viewheight = -7;
+ else if (viewheight > 7)
+ viewheight = 7;
+
+ vieworg = self.origin;
+ vieworg_z += getstatf (STAT_VIEWHEIGHT) + viewheight;
+ viewentity.origin = vieworg;
+
+ // correct the view position to compensate for any errors,
+ // slowly over time, 0.1 seconds.
+ /*
+ if (pmove_errortime - time > 0)
+ vieworg += (pmove_errortime - time) *
+ ERRORTIME * pmove_error;
+ */
+
+ if (player_steptime - time > 0)
+ vieworg_z += (player_steptime - time) *
+ STEPTIME * player_step;
+
+ if (self.lerptime)
+ self.lerpfrac = 1 - (time - self.lerptime) * 10;
+
+ self.renderflags |= RF_EXTERNALMODEL;
+ }
+
+ addentity (self);
+ return PREDRAW_NEXT;
+};
+
+//======================================================================
+// PlayerRemove
+//----------------------------------------------------------------------
+static void() PlayerRemove =
+{
+ if (player_local == self)
+ player_local = world;
+
+ setmodel (self, "");
+ self.oldskin = "";
+ self.predraw = __NULL__;
+};
+
+//======================================================================
+// PlayerNew
+//----------------------------------------------------------------------
+void() PlayerNew =
+{
+ self.classname = "player";
+ self.customphysics = Empty;
+ // MASK_NORMAL ?
+ self.drawmask = MASK_ENGINE;
+ self.movetype = MOVETYPE_WALK;
+ self.predraw = PlayerPreDraw;
+ self.removefunc = PlayerRemove;
+ self.solid = SOLID_SLIDEBOX;
+ setmodel (self, "progs/player.mdl");
+};
+
+//======================================================================
+// PlayerUpdate
+//
+// called from CSQC_Ent_Update for CLASS_PLAYER entities
+//----------------------------------------------------------------------
+void(float isnew) PlayerUpdate =
+{
+ local float f;
+
+ f = ReadByte ();
+ self.angles_x = ReadShort () / (32767 / 360);
+ self.angles_y = ReadShort () / (32767 / 360);
+ self.angles_z = ReadShort () / (32767 / 360);
+ self.origin_x = ReadCoord ();
+ self.origin_y = ReadCoord ();
+ self.origin_z = ReadCoord ();
+ self.velocity_x = ReadShort ();
+ self.velocity_y = ReadShort ();
+ self.velocity_z = ReadShort ();
+ self.flags = ReadFloat ();
+ self.pmove_flags = ReadFloat ();
+ self.movetype = ReadFloat ();
+
+ if (isnew && !(self.predraw))
+ PlayerNew ();
+
+ if (f != self.frame || isnew)
+ {
+ self.frame2 = self.frame;
+ self.lerptime = time;
+ self.frame = f;
+ }
+
+ if (self.entnum == player_localentnum)
+ {
+ local vector o, v;
+ local float pmflags;
+
+ // this is us; save for later
+ player_local = self;
+ o = self.origin;
+ v = self.velocity;
+ pmflags = self.pmove_flags;
+
+ // reset prediction
+ PlayerResetPrediction (self);
+ PlayerRunMovement (self, servercommandframe + 1);
+
+ player_org = o;
+ player_vel = v;
+ // TODO CEV ????
+ // player_pmflags = self.pmove_flags;
+ player_pmflags = pmflags;
+ player_sequence = servercommandframe;
+ PlayerResetPrediction (self);
+ }
+
+ setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
+ self.frameold = self.frame;
+ // setorigin (self, self.origin);
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/csqc/csqc_progs.src

diff --git a/qc/csqc/csqc_progs.src b/qc/csqc/csqc_progs.src
index d23fe5d..87d8245 100644
--- a/qc/csqc/csqc_progs.src
+++ b/qc/csqc/csqc_progs.src
@@ -1,7 +1,20 @@
-../../csprogs.dat
+#pragma progs_dat "../../csprogs.dat"

-csqc_fteopts.qc
+#pragma noref 1
+#pragma target fte
+
+#define FTE
+#define CSQC
+
+#includelist
+../defs_globalvars.qc
+../defs_entvars.qc
+../defs_constants.qc
+csqc_defsbuiltins.qc
csqc_defsclient.qc
csqc_defs.qc
-// didn't import csqc_hudad.qc
+../pmove.qc
+csqc_player.qc
csqc_hudvanilla.qc
+csqc_entrypoints.qc
+#endlist

Return to the top of this page or return to the overview of this repo.

Diff qc/defs_builtins.qc

diff --git a/qc/defs_builtins.qc b/qc/defs_builtins.qc
index e220cfb..26958d2 100644
--- a/qc/defs_builtins.qc
+++ b/qc/defs_builtins.qc
@@ -71,6 +71,10 @@ void(float to, float f) WriteCoord = #56;
void(float to, float f) WriteAngle = #57;
void(float to, string s) WriteString = #58;
void(float to, entity s) WriteEntity = #59;
+// 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 equivalent).
+void(float buf, int fl) WriteInt = #0:WriteInt;

//======================================================================
// broadcast client message generation
@@ -199,11 +203,17 @@ void(float num, float type, .__variant fld) clientstat = #232;
// moved entity.
void(optional entity ent, optional vector neworigin) touchtriggers = #279;

+void(float buf, float fl) WriteFloat = #280;
+
// Part of DP_SV_PRINT Unconditionally print on the local system's
// console, even in ssqc (doesn't care about the value of the
// developer cvar).
void(string s, ...) print = #339;

+// Perform the engine's standard player movement prediction upon the given
+// entity using the input_* globals to describe movement.
+void(entity ent) runstandardplayerphysics = #347;
+
// Look up a key in the server's public serverinfo string
string(string key) serverkey = #354;

Return to the top of this page or return to the overview of this repo.

Diff qc/defs_constants.qc

diff --git a/qc/defs_constants.qc b/qc/defs_constants.qc
index fce7c2f..3836d86 100644
--- a/qc/defs_constants.qc
+++ b/qc/defs_constants.qc
@@ -2,10 +2,13 @@
CONSTANT VALS COLLECTED HERE
==============================================================================*/

+#define FULLSEND 0xffffff
+
#define PM_AIRACCEL 8 // 10 in Q1; now 8
-#define PM_AIRACCELQ3 0.8 // 1.0 in Q3; now 0.8
+#define PM_AIRACCELQ3 0.8 // 1.0 in Q3 ?; now 0.8
#define PM_AIRACCELFWD 1.5 // 1 feels close to Q3 / CPM
#define PM_AIRACCELBACK 5 // Air stop speed in Q3?
+#define PM_AIRACCELTURN 150 // affects +fwd style turning radius
#define PM_BOOSTACCEL 12 // 12 is fast, 10 is enough
#define PM_BOOSTFRICTION 4 // Q1 friction (4) is plenty low
#define PM_FRICTION 8 // 4 for Q1, 6 for Q3, 8 for CPM
@@ -18,7 +21,7 @@

#define PM_JUMPSPEED 270 // standard jump Z velocity; 90 * 3
#define PM_DOUBLEJUMPSPEED 360 // 270 * 1.5 in CPM?; 360 = 90 * 4
-#define PM_TRIPLEJUMPSPEED 225 // reduced Z velocity; 90 * 2.5
+#define PM_TRIPLEJUMPSPEED 270 // 225 reduced Z velocity; 90 * 2.5
#define PM_TELEJUMPSPEED 360 // same as DOUBLEJUMPSPEED
#define PM_WALLJUMPFORCE 90 // amount of push away from wall
#define PM_WALLJUMPSPEED PM_JUMPSPEED // upward vel for walljumps
@@ -27,7 +30,7 @@
#define PM_STOPSPEED 100
#define PM_WATERSINKSPEED 60

-#define PM_JUMP_WINDOW 0.2 // minimum jump interval
+#define PM_JUMP_WINDOW 0.1 // minimum jump interval
#define PM_DOUBLEJUMP_WINDOW 0.4 // 2 jumps in this time is a double
#define PM_DOUBLEJUMP_COOLDOWN 0.4 //
#define PM_TELEJUMP_WINDOW 0.4 // duration to allow a telejump
@@ -35,6 +38,7 @@
#define PM_WALLCLIP_WINDOW 0.25 //
#define PM_BOOST_WINDOW 0.4 // groundboost duration

+#define PM_JUMPPADADDHEIGHT 64 // not currently in use
#define PM_TELEDROP '0 0 -64' // drop teleporter exit to floor if
// floor is within this distance
#define PM_TELEEXITSPEED 400 // exit teleporters at this speed

Return to the top of this page or return to the overview of this repo.

Diff qc/defs_misc.qc

diff --git a/qc/defs_misc.qc b/qc/defs_misc.qc
index ffd7c28..4462a79 100644
--- a/qc/defs_misc.qc
+++ b/qc/defs_misc.qc
@@ -28,8 +28,6 @@ float FL_ONGROUND = 512; // standing on something
float FL_PARTIALGROUND = 1024; // not all corners are valid
float FL_WATERJUMP = 2048; // player jumping out of water
float FL_JUMPRELEASED = 4096; // for jump debouncing
-float FL_DOUBLEJUMPED = 8192; // player has doublejumped
-float FL_WALLJUMP = 16384; // player has jumped off a wall
float FL_NOCENTERPRINT = 65536; // don't centerprint entity's message
// field when its targets are used
// edict.movetype values
@@ -149,6 +147,8 @@ float TE_LAVASPLASH = 10;
float TE_TELEPORT = 11;
float TE_EXPLOSION2 = 12; // from doe -- dumptruck_ds

+float CLASS_PLAYER = 77; // TODO CEV
+
// sound channels
// channel 0 never willingly overrides
// other channels (1-7) always override a playing sound on that channel
@@ -180,6 +180,14 @@ float MSG_BROADCAST = 0; // unreliable to all
float MSG_ONE = 1; // reliable to one (msg_entity)
float MSG_ALL = 2; // reliable to all
float MSG_INIT = 3; // write to the init string
+// The byte(s) will be written into the multicast buffer for more
+// selective sending. Messages sent this way will never be split across
+// packets, and using this for csqc-only messages will not break protocol
+// translation.
+float MSG_MULTICAST = 4;
+// The byte(s) will be written into the entity buffer. This is a special
+// value used only inside 'SendEntity' functions.
+float MSG_ENTITY = 5;

// spawnflags for func_movewall
float MOVEWALL_VISIBLE = 1;
@@ -191,10 +199,6 @@ float KNOWN_RELEASE_NOT = 0;
float KNOWN_RELEASE_ID1 = 1;
float KNOWN_RELEASE_FUNC_MAPJAMX = 2;

-// interfacing with CSQC -- CEV
-const float CLIENT_VELOCITY_X = 64;
-const float CLIENT_VELOCITY_Y = 65;
-
const float EV_VOID = 0;
const float EV_STRING = 1;
const float EV_FLOAT = 2;
@@ -297,10 +301,13 @@ float AS_TURRET = 5;
.float bubble_count; // keeps track of the number of bubbles
.string deathtype; // keeps track of how the player died

+.float pmove_flags; // custom movement flags -- CEV
.float jump_time; // last time the player jumped -- CEV
+.float land_time; // last time the player landed -- CEV
.vector primal_velocity; // velocity before engine physics -- CEV
.float primal_speed; // speed before engine physics -- CEV
.float boost_time; // time to simulate low friction -- CEV
+.void() customphysics;

float input_timelength; // from fteextensions.qc -- CEV
vector input_angles; /* +x=DOWN */
@@ -672,5 +679,17 @@ void(entity client, float density, vector color) csf_set;

.entity infight_activator;

-.void() customphysics;
+#ifdef SSQC
+// TODO CEV
+// Called by the engine whenever an entity needs to be (re)sent to a client's
+// csprogs, either because SendFlags was set or because data was lost. Must
+// write its data to the MSG_ENTITY buffer. Will be called at the engine's
+// leasure.
+.float(entity playerent, float changedflags) SendEntity;
+// Indicates that something in the entity has been changed, and that it needs
+// to be updated to all players that can see it. The engine will clear it at
+// some point, with the cleared bits appearing in the 'changedflags' argument
+// of the SendEntity method.
+.float SendFlags;
+#endif

Return to the top of this page or return to the overview of this repo.

Diff qc/dtmisc.qc

diff --git a/qc/dtmisc.qc b/qc/dtmisc.qc
index 8519097..1e676a3 100644
--- a/qc/dtmisc.qc
+++ b/qc/dtmisc.qc
@@ -1006,171 +1006,4 @@ void() misc_particle_stream =
self.think = particle_stream_start;
self.nextthink = time + 0.2;
};
-// from custents, modified by dumptruck_ds
-//##########################################
-//#### HEAL TRIGGER ####
-//##########################################
-// Original entity submitted by Jan Martin Mathiassen, aka. TGR

-void() heal_think =
-{
- if (self.cnt == self.count)
- {
- dprint("trigger_heal think: full\n");
- self.think = SUB_Null;
- return;
- }
- local float recharge_amount = self.speed;
- if (self.count < (self.cnt + self.speed))
- {
- recharge_amount = self.count - self.cnt;
- }
- dprint("trigger_heal think: [max: ");
- dprint(ftos(self.count));
- dprint(", current: ");
- dprint(ftos(self.cnt));
- dprint(", recharging: ");
- dprint(ftos(recharge_amount));
- dprint("]\n");
-
- self.cnt = self.cnt + recharge_amount;
- self.nextthink = time + self.delay;
-};
-
-void() heal_touch =
-{
- if (self.estate != STATE_ACTIVE)
- return;
- if (other.movetype == MOVETYPE_NOCLIP) // from Copper -- dumptruck_ds
- return FALSE;
- if(self.spawnflags & HEAL_PLAYER_ONLY && other.classname != "player")
- return;
- if(self.spawnflags & HEAL_MONSTER_ONLY && !(other.flags & FL_MONSTER))
- return;
- if(other.classname != "player" && !(other.flags & FL_MONSTER))
- return;
-
- if(other.heal_timer > time)
- return;
-
- if(self.count && self.cnt <= 0)
- {
- if(self.message2)
- centerprint(other, self.message2);
- return;
- }
-
- if ((other.takedamage) && (other.health < self.health_max))
- {
-
- if (self.noise != "")
- sound (self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
- else
- sound (self, CHAN_AUTO, "items/r_item1.wav", 1, ATTN_NORM);
- local float calculated_healing;
- if ((other.health + self.heal_amount) > self.health_max)
- {
- calculated_healing = self.health_max - other.health;
- }
- else
- {
- calculated_healing = self.heal_amount;
- }
-
- if (self.count)
- {
-
- if (calculated_healing > self.cnt)
- {
- calculated_healing = self.cnt;
- }
- self.cnt = self.cnt - calculated_healing;
- if (self.delay)
- {
- self.think = heal_think;
- self.nextthink = time + self.delay;
- }
- dprint("trigger_heal used: [max: ");
- dprint(ftos(self.count));
- dprint(", current: ");
- dprint(ftos(self.cnt));
- dprint(", using: ");
- dprint(ftos(calculated_healing));
- dprint("]\n");
- }
- if (self.message)
- {
- centerprint(other, self.message);
- }
- T_Heal (other, calculated_healing, 1);
- other.heal_timer = time + self.wait;
- }
-};
-
-void() heal_toggle=
-{
- if(self.touch == SUB_Null)
- self.touch = heal_touch;
- else
- self.touch = SUB_Null;
-};
-
-/*QUAKED trigger_heal (.5 .5 .5) ? HEAL_START_ON HEAL_PLAYER_ONLY HEAL_MONSTER_ONLY X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-
-Any object touching this will be healed
-heal_amount -- the amount to heal each time (default 5)
-wait -- the time between each healing (default 1)
-health_max -- the upper limit for the healing (default 100, max 250)
-sounds -- set to 1 to enable the noise1 field for custom healing sound
-noise -- path to custom sound file
-message -- message to print on heal
-count -- maximum heal before exhausted
-speed -- amount to recharge at a time
-delay -- time before recharging
-message2 -- message to print when exhausted
-*/
-void() trigger_heal =
- {
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
- //play custom sound for healing if noise key exists
- precache_sound("items/r_item1.wav");
- if (self.noise != "") precache_sound (self.noise);
-
- InitTrigger ();
-
- if (self.wait == 0)
- self.wait = 1;
- if (self.heal_amount == 0)
- self.heal_amount = 5;
- if (self.health_max == 0)
- self.health_max = 100;
- else if (self.health_max > 250)
- self.health_max = 250;
-
- if (self.count)
- {
- self.cnt = self.count;
-
- if (self.speed && !self.delay)
- {
- self.delay = 10;
- } else if (!self.speed && self.delay)
- {
- self.speed = 5;
- }
- }
-
- // if(self.targetname)
- // {
- // self.use = heal_toggle;
- // if(self.spawnflags & HEAL_START_ON)
- // self.touch = heal_touch;
- // else
- // self.touch = SUB_Null;
- // }
- // else
- self.touch = heal_touch;
-
- SUB_CheckWaiting();
-};

Return to the top of this page or return to the overview of this repo.

Diff qc/dtquake.qc

diff --git a/qc/dtquake.qc b/qc/dtquake.qc
deleted file mode 100644
index db407e7..0000000
--- a/qc/dtquake.qc
+++ /dev/null
@@ -1,103 +0,0 @@
-// /*this is a point entity from Rubicon Rumble Pack Devkit; REQUIRES A TARGETNAME*/
-//
-// // ===== TRIGGER_SHAKE =======================================================
-//
-float VIEWONLY = 1;
-
-void() shake_think =
-{
- if (self.attack_finished < time) // Done
- {
- self.nextthink = -1;
-
- if (self.noise1 != "")
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
-
- return;
- }
-
- local entity plyr;
-
- // Shake all players in the effect radius...
-
- plyr = findradius(self.origin, self.count);
-
- while(plyr)
- {
- if (plyr.flags & FL_CLIENT)
- {
- local float d;
-
- // Scale effect by distance
- d = vlen(self.origin - plyr.origin);
- d = (self.count - d)/self.count;
-
- if (d > 0)
- {
- // shake up the view
- plyr.punchangle_x = -1 * (random() + (0.025*self.dmg*d));
-
- // push the player around
- if (plyr.flags & FL_ONGROUND && !(self.spawnflags & VIEWONLY))
- {
- d = self.dmg*d;
- plyr.velocity_x = plyr.velocity_x + (random()*d*2 - d);
- plyr.velocity_y = plyr.velocity_y + (random()*d*2 - d);
- plyr.velocity_z = plyr.velocity_z + (random()*d);// always push up
- }
- }
- }
-
- plyr = plyr.chain;
- }
-
- // keep going
- self.nextthink = time + 0.1;
-};
-
-void() shake_use =
-{
- if (self.attack_finished > time) return;// already active
-
- // Start...
-
- if (self.noise != "")
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
-
- self.attack_finished = time + self.wait;
- self.nextthink = time + 0.1;
-};
-
-/*QUAKED trigger_shake (.5 0 .5) (-8 -8 -8) (8 8 8) VIEWONLY X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-
-Earthquake trigger - shakes players in it's radius when active.
-Strength of tremor is greatest at the centre.
-dmg Strength at center (default is 120)
-wait Duration of shake (default is 1)
-count Affect radius (defalt is 200)
-noise Noise to play when starting to shake
-noise1 Noise to play when stopping
-targetname Must be triggered
-Spawnflags
-VIEWONLY Shakes the view, but player movement is not affected
-*/
-void() trigger_shake =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (!self.targetname) objerror("trigger_shake without name");
-
- if (self.noise != "") precache_sound (self.noise);
- if (self.noise1 != "") precache_sound (self.noise1);
-
- if (!self.dmg) self.dmg = 120;
- if (self.count <= 0) self.count = 200;
- if (self.wait <= 0) self.wait = 1.0;
-
- setorigin(self, self.origin);
-
- self.nextthink = -1;
- self.think = shake_think;
- self.use = shake_use;
-};

Return to the top of this page or return to the overview of this repo.

Diff qc/fteopts.qc

diff --git a/qc/fteopts.qc b/qc/fteopts.qc
deleted file mode 100644
index 8f7324f..0000000
--- a/qc/fteopts.qc
+++ /dev/null
@@ -1,2 +0,0 @@
-#define FTE
-#pragma TARGET FTE

Return to the top of this page or return to the overview of this repo.

Diff qc/items_health.qc

diff --git a/qc/items_health.qc b/qc/items_health.qc
index 7ae7ada..72f2ba9 100644
--- a/qc/items_health.qc
+++ b/qc/items_health.qc
@@ -1,6 +1,18 @@
-/*==============================================================================
- HEALTH BOXES
-==============================================================================*/
+//==============================================================================
+// HEALTH BOXES
+//==============================================================================
+
+// constants
+float H_ROTTEN = 1;
+float H_MEGA = 2;
+float H_VIAL = 4;
+
+// fields
+.float healamount, healtype;
+
+// primitives
+void() health_touch;
+// void() item_megahealth_rot;

//======================================================================
// T_Heal: add health to an entity, limiting health to max_health
@@ -33,14 +45,6 @@ Rotten box heals 15 points.
Megahealth will add 100 health, then start to
rot the player back down to 100 health after 5 seconds.
*/
-
-float H_ROTTEN = 1;
-float H_MEGA = 2;
-float H_VIAL = 4;
-.float healamount, healtype;
-void() health_touch;
-// void() item_megahealth_rot;
-
//======================================================================
// item_health
//----------------------------------------------------------------------
@@ -169,8 +173,8 @@ void() item_health_vial =

// model from Hexen 2 -- dumptruck_ds
precache_body_model ("progs/h_mdls/pd_vial.mdl");
- body_model("progs/h_mdls/pd_vial.mdl");
- precache_sound_misc("items/r_item1.wav");
+ body_model ("progs/h_mdls/pd_vial.mdl");
+ precache_sound_misc ("items/r_item1.wav");
if !(self.snd_misc)
// set the custom noise in editor -- dumptruck_ds
self.snd_misc = "items/r_item1.wav";
@@ -209,7 +213,7 @@ void() health_touch =
}

sprint(other, "You receive ");
- s = ftos(amount);
+ s = ftos (amount);
sprint(other, s);
sprint(other, " health\n");

@@ -247,7 +251,7 @@ void() health_touch =
// item respawned). -- iw
//
if (!deathmatch)
- CheckItemRespawn(self, 30);
+ CheckItemRespawn (self, 30);
else if (deathmatch == 1)
// doesn't respawn in "deathmatch 2"
self.nextthink = time + 125;
@@ -255,7 +259,7 @@ void() health_touch =
else
{
if (!deathmatch)
- CheckItemRespawn(self, 30);
+ CheckItemRespawn (self, 30);
else if (deathmatch == 1)
// doesn't respawn in "deathmatch 2"
self.nextthink = time + 20;
@@ -266,7 +270,7 @@ void() health_touch =
SUB_UseTargets ();
};

-// Q3 entity support -- CEV
+// Quake 3 entity support -- CEV
void() item_health_small =
{
item_health_vial ();

Return to the top of this page or return to the overview of this repo.

Diff qc/misc.qc

diff --git a/qc/misc.qc b/qc/misc.qc
index 74b10f1..26009a1 100644
--- a/qc/misc.qc
+++ b/qc/misc.qc
@@ -1678,194 +1678,3 @@ void() target_autosave =
self.use = target_autosave_use;
}

-
-/*
-=============================================================
-
-trigger_textstory
-
-=============================================================
-*/
-
-float TEXTSTORY_SILENT = 1;
-float TEXTSTORY_NOFADE = 2;
-
-void(entity controller) textstory_hide = {
- if (!self.enemy || !(self.enemy.flags & FL_CLIENT)) return;
-
- self.enemy.suppressCenterPrint = FALSE;
- centerprint(self.enemy, "");
-
- if (controller.noise2)
- sound(self.enemy, CHAN_BODY, controller.noise2, 1, ATTN_NORM);
-
- if (!(controller.spawnflags & TEXTSTORY_NOFADE))
- csf_fade(self.enemy, 0, '0 0 0', 0.5);
-
-};
-
-void(entity controller) textstory_show = {
- if (!self.enemy || !(self.enemy.flags & FL_CLIENT)) return;
-
- self.enemy.suppressCenterPrint = TRUE;
-
- centerprint_builtin(self.enemy, controller.message);
-
- if (!self.state) {
- if (controller.noise1)
- sound(self.enemy, CHAN_BODY, controller.noise1, 1, ATTN_NORM);
-
- if (!(controller.spawnflags & TEXTSTORY_NOFADE))
- if (!self.fade_amt) //custom fade amount --dumptruck_ds
- {
- csf_fade(self.enemy, 160, '0 0 0', 1);
- }
- else
- csf_fade(self.enemy, self.fade_amt, '0 0 0', 1);
- }
-
-
- self.state = 1;
-};
-
-//----------------------------------------
-
-void() trigger_textstory_hide = {
- textstory_hide(self);
-
- self.enemy = world;
- self.state = 0;
-};
-
-void() trigger_textstory_show = {
- textstory_show(self);
-
- self.think = trigger_textstory_hide;
- self.nextthink = time + 0.2;
-
-};
-
-void() trigger_textstory_touch = {
-
- if (!(other.flags & FL_CLIENT)) return;
- if (self.estate != STATE_ACTIVE) return;
-
- // don't show message if another player is already triggering it
- if (other != self.enemy && self.state == 1) return;
-
- if (self.mangle && !isInAngle(other.v_angle, self.mangle, self.view_ofs))
- return;
-
- if (self.attack_finished < time) {
-
- self.attack_finished = time + 0.1;
- self.enemy = other;
-
- trigger_textstory_show();
- }
-};
-
-void() trigger_textstory = {
- InitTrigger();
- self.touch = trigger_textstory_touch;
-
- if (self.view_ofs == '0 0 0')
- self.view_ofs = '90 90 0';
-
- if (self.mangle) self.mangle = normalizeAngles180(self.mangle);
-
- if (self.noise1 == "")
- self.noise1 = "misc/talk.wav";
-
- if (self.noise2 == "")
- self.noise2 = "misc/null.wav";
-
- if (self.spawnflags & TEXTSTORY_SILENT) {
- self.noise1 = "";
- self.noise2 = "";
- }
-
-
- if (self.noise1 != "")
- precache_sound (self.noise1);
- if (self.noise2 != "")
- precache_sound (self.noise2);
-
- SUB_CheckWaiting();
-};
-
-
-//-----------------------------
-
-
-void() target_textstory_helper_hide = {
-
- textstory_hide(self.owner);
- remove(self);
-};
-
-void() target_textstory_helper_show = {
- if (!self.enemy || !(self.enemy.flags & FL_CLIENT)) {
- remove(self);
- return;
- }
-
- textstory_show(self.owner);
-
- if (self.attack_finished < time) self.think = target_textstory_helper_hide;
-
- self.nextthink = time + 0.1;
-};
-
-void(entity tgt) target_textstory_spawn_helper = {
- entity e;
-
- e = spawn();
- e.classname = "target_textstory_helper";
- e.owner = self;
- e.think = target_textstory_helper_show;
- e.nextthink = time + 0.1;
- e.attack_finished = time + self.wait;
- e.enemy = tgt;
-};
-
-void() target_textstory_use = {
-
- if (!(activator.flags & FL_CLIENT)) return;
- if (self.estate != STATE_ACTIVE) return;
-
- entity t;
-
- if (self.spawnflags & TRIGGER_CENTERPRINTALL) {
- t = find(world, classname, "player");
- while (t) {
- target_textstory_spawn_helper(t);
- t = find(t, classname, "player");
- }
- }
- else
- target_textstory_spawn_helper(activator);
-};
-
-void() target_textstory = {
- if (self.noise1 == "")
- self.noise1 = "misc/talk.wav";
-
- if (self.noise2 == "")
- self.noise2 = "misc/null.wav";
-
- if (self.spawnflags & TEXTSTORY_SILENT) {
- self.noise1 = "";
- self.noise2 = "";
- }
-
- if (self.noise1 != "")
- precache_sound (self.noise1);
- if (self.noise2 != "")
- precache_sound (self.noise2);
-
- if (!self.wait)
- self.wait = 5;
-
- self.use = target_textstory_use;
-};

Return to the top of this page or return to the overview of this repo.

Diff qc/misc_model.qc

diff --git a/qc/misc_model.qc b/qc/misc_model.qc
index 0730297..c801bc2 100644
--- a/qc/misc_model.qc
+++ b/qc/misc_model.qc
@@ -7,14 +7,8 @@
* Edited by: dumptruck_ds to add start and stop animations
*/

-// The starting frame of the animation
-.float first_frame;
-
-// The ending frame of the animation
-.float last_frame;
-
-// Forward declarations
-void() misc_model_think;
+.float first_frame; // The starting frame of the animation
+.float last_frame; // The ending frame of the animation

/*QUAKED misc_model (0 0.5 0.8) (-8 -8 -8) (8 8 8) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
@@ -39,33 +33,93 @@ float MISC_MODEL_ONLY_ONCE = 8;
float MISC_MODEL_PLAY_COUNT = 16;
float MISC_MODEL_STARTOFF = 32;

-
-void() misc_model_use = {
- if (self.state == STATE_ACTIVE) {
- if (self.spawnflags & MISC_MODEL_SOLID) self.solid = SOLID_NOT;
+void() misc_model_use =
+{
+ if (self.state == STATE_ACTIVE)
+ {
+ if (self.spawnflags & MISC_MODEL_SOLID)
+ self.solid = SOLID_NOT;
self.model = "";

self.state = STATE_INVISIBLE;
- setorigin(self, self.origin);
+ setorigin (self, self.origin);
}
- else {
- if (self.spawnflags & MISC_MODEL_SOLID) self.solid = SOLID_BBOX;
+ else
+ {
+ if (self.spawnflags & MISC_MODEL_SOLID)
+ self.solid = SOLID_BBOX;
self.model = self.mdl;

self.state = STATE_ACTIVE;
- setorigin(self, self.origin);
+ setorigin (self, self.origin);
}
};

-void() misc_model = {
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
+/*
+ * misc_model_think
+ *
+ * Handles animation for misc_model entity.
+ */
+void() misc_model_think =
+{
+ self.nextthink = time + fabs(self.speed);
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ self.frame = self.frame + sign (self.speed);

- if (!self.mdl || self.mdl == "")
- objerror("Model not defined");
+ if (self.spawnflags & MISC_MODEL_BACK_AND_FORTH
+ && self.frame < self.first_frame)
+ {
+ self.speed = -1 * self.speed;
+ self.frame += 2;
+ }
+ else if (self.spawnflags & MISC_MODEL_BACK_AND_FORTH
+ && self.frame > self.last_frame)
+ {
+ self.speed = -1 * self.speed;
+ self.frame -= 2;
+ }
+ else
+ {
+ self.frame = wrap (self.frame, self.first_frame,
+ self.last_frame);
+ }

- if(!self.centeroffset) self.centeroffset = '0 0 0';
- if(!self.mdlsz) self.mdlsz = '32 32 32';
+ if (self.spawnflags & MISC_MODEL_ONLY_ONCE
+ && self.frame == self.last_frame
+ && self.last_frame != self.first_frame)
+ self.nextthink = -1;
+
+ if (self.spawnflags & MISC_MODEL_PLAY_COUNT
+ && self.frame == self.last_frame
+ && self.last_frame != self.first_frame)
+ {
+ if !(self.count)
+ objerror ("Error: set count to the number of animation cycles!");
+ self.cnt = self.cnt + 1;
+ dprint (ftos(self.cnt));
+ dprint ("\n");
+ if (self.cnt != self.count)
+ return FALSE;
+ else
+ self.nextthink = -1;
+ }
+};
+
+void() misc_model =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit ())
+ return;
+
+ if (!self.mdl || self.mdl == "")
+ objerror("Model not defined");
+
+ if (!self.centeroffset)
+ self.centeroffset = '0 0 0';
+ if (!self.mdlsz)
+ self.mdlsz = '32 32 32';

vector vmin, vmax;

@@ -77,94 +131,58 @@ void() misc_model = {
vmax_y = self.centeroffset_y + (self.mdlsz_y / 2);
vmax_z = self.centeroffset_z + (self.mdlsz_z / 2);

- precache_model(self.mdl);
- setmodel(self, self.mdl);
-
+ precache_model(self.mdl);
+ setmodel(self, self.mdl);
+
setsize(self, vmin, vmax);
-
- if(self.spawnflags & MISC_MODEL_SOLID) self.solid = SOLID_BBOX;
+
+ if (self.spawnflags & MISC_MODEL_SOLID)
+ self.solid = SOLID_BBOX;
else self.solid = SOLID_NOT;

- if(self.spawnflags & MISC_MODEL_GRAVITY) self.movetype = MOVETYPE_TOSS;
+ if (self.spawnflags & MISC_MODEL_GRAVITY)
+ self.movetype = MOVETYPE_TOSS;
else self.movetype = MOVETYPE_NONE;

- self.use = misc_model_use;
-
- if (!self.frame) {
- self.frame = self.first_frame;
- }
-
- // Make static (not animate) if not given a frame range, and not affected by gravity
- // also remains active if it has a targetname (so it can be killtargeted/toggled)
- if (!self.last_frame
- && !(self.spawnflags & MISC_MODEL_GRAVITY)
- && !(self.spawnflags & MISC_MODEL_SOLID)
- && !self.targetname
- && !self.targetname2
- // && !(self.spawnflags & MISC_MODEL_DONTMAKESTATIC)
- ) makestatic(self);
- // Make static (not animate) if not given a frame range, and not affected by gravity
- //changed by bmFbr
- // if (!self.last_frame && !(self.spawnflags & MISC_MODEL_GRAVITY)) {
- // makestatic(self);
- // return;
- // }
-
- if (self.last_frame) { // if it as a custom animation range
- // Default animation speed to 10 fps
- if (!self.speed) {
- self.speed = 0.1;
- }
- self.nextthink = time + self.speed;
- self.think = misc_model_think;
- }
-
- if (self.spawnflags & MISC_MODEL_STARTOFF)
+ self.use = misc_model_use;
+
+ if (!self.frame)
+ self.frame = self.first_frame;
+
+ // Make static (not animate) if not given a frame range, and
+ // not affected by gravity; also remains active if it has a
+ // targetname (so it can be killtargeted/toggled)
+ if (!self.last_frame
+ && !(self.spawnflags & MISC_MODEL_GRAVITY)
+ && !(self.spawnflags & MISC_MODEL_SOLID)
+ && !self.targetname
+ && !self.targetname2)
+ // && !(self.spawnflags & MISC_MODEL_DONTMAKESTATIC)
+ makestatic(self);
+
+ // Make static (not animate) if not given a frame range, and
+ // not affected by gravity
+ // changed by bmFbr
+ // if (!self.last_frame && !(self.spawnflags & MISC_MODEL_GRAVITY))
+ // {
+ // makestatic(self);
+ // return;
+ // }
+
+ // if it as a custom animation range
+ if (self.last_frame)
+ {
+ // Default animation speed to 10 fps
+ if (!self.speed)
+ self.speed = 0.1;
+ self.nextthink = time + self.speed;
+ self.think = misc_model_think;
+ }
+
+ if (self.spawnflags & MISC_MODEL_STARTOFF)
self.state = STATE_ACTIVE;
- else
+ else
self.state = STATE_INVISIBLE;

- misc_model_use();
-
-};
-
-/*
- * misc_model_think
- *
- * Handles animation for misc_model entity.
- */
-void() misc_model_think = {
- self.nextthink = time + fabs(self.speed);
- if (self.estate != STATE_ACTIVE) return;
-
- self.frame = self.frame + sign(self.speed);
-
- if (self.spawnflags & MISC_MODEL_BACK_AND_FORTH && self.frame < self.first_frame)
- {
- self.speed = -1 * self.speed;
- self.frame+=2;
- }
- else if (self.spawnflags & MISC_MODEL_BACK_AND_FORTH && self.frame > self.last_frame)
- {
- self.speed = -1 * self.speed;
- self.frame-=2;
- }
- else
- self.frame = wrap(self.frame, self.first_frame, self.last_frame);
-
- if(self.spawnflags & MISC_MODEL_ONLY_ONCE && self.frame==self.last_frame && self.last_frame!=self.first_frame)
- self.nextthink = -1;
-
- if(self.spawnflags & MISC_MODEL_PLAY_COUNT && self.frame==self.last_frame && self.last_frame!=self.first_frame)
- {
- if !(self.count)
- objerror ("Error: set count to the number of animation cycles!");
- self.cnt = self.cnt +1;
- dprint (ftos(self.cnt));
- dprint ("\n");
- if (self.cnt != self.count)
- return FALSE;
- else
- self.nextthink = -1;
- }
+ misc_model_use ();
};

Return to the top of this page or return to the overview of this repo.

Diff qc/pmove.qc

diff --git a/qc/pmove.qc b/qc/pmove.qc
index b2ca7cc..d0713a7 100644
--- a/qc/pmove.qc
+++ b/qc/pmove.qc
@@ -1,17 +1,29 @@
-/*==============================================================================
- PMOVE.QC
-==============================================================================*/
+//==============================================================================
+// PMOVE
+//==============================================================================

.entity groundentity;
.vector groundnormal;

-static void(entity tother) phys_dotouch =
+// pmove_flags
+enumflags
{
- entity oself;
+ PMF_JUMP_HELD,
+ PMF_RESERVED,
+ PMF_ONGROUND,
+ PMF_WALLJUMP,
+ PMF_DOUBLEJUMPED,
+ PMF_WATERJUMP
+};

+//----------------------------------------------------------------------
+static void(entity tother) PM_DoTouch =
+{
if (tother.touch == __NULL__)
return;

+ entity oself;
+
oself = self;
other = self;
self = tother;
@@ -19,13 +31,17 @@ static void(entity tother) phys_dotouch =
self = oself;
};

+//======================================================================
+// PM_Nudge
+//
// from the GPL2 CSQCTest code that comes with FTEQW
-float() phys_nudge =
+//----------------------------------------------------------------------
+float() PM_Nudge =
{
vector test, org = self.origin;

// check current position.
- tracebox(org, self.mins, self.maxs, org, FALSE, self);
+ tracebox (org, self.mins, self.maxs, org, FALSE, self);
if (!trace_startsolid)
return TRUE;

@@ -46,7 +62,7 @@ float() phys_nudge =
for (float x = 0; x < offsets.length; x++)
{
test.x = org.x + offsets[x];
- tracebox(test, self.mins, self.maxs, test,
+ tracebox (test, self.mins, self.maxs, test,
FALSE, self);
if (!trace_startsolid)
{
@@ -61,8 +77,12 @@ float() phys_nudge =
return FALSE;
};

-#define STOP_EPSILON 0.1
-vector(vector vel, vector normal, float ob, float oneside) phys_clipvelocity =
+//======================================================================
+// PM_ClipVelocity
+//----------------------------------------------------------------------
+#define STOP_EPSILON 0.125
+#if 0
+vector(vector vel, vector normal, float ob, float oneside) PM_ClipVelocity =
{
local float backoff, backoffz;

@@ -80,18 +100,78 @@ vector(vector vel, vector normal, float ob, float oneside) phys_clipvelocity =

vel -= normal * backoff;

- if (vel_x > -STOP_EPSILON && vel_x < STOP_EPSILON) vel_x = 0;
- if (vel_y > -STOP_EPSILON && vel_y < STOP_EPSILON) vel_y = 0;
- if (vel_z > -STOP_EPSILON && vel_z < STOP_EPSILON) vel_z = 0;
+ if (vel_x > -STOP_EPSILON && vel_x < STOP_EPSILON)
+ vel_x = 0;
+ if (vel_y > -STOP_EPSILON && vel_y < STOP_EPSILON)
+ vel_y = 0;
+ if (vel_z > -STOP_EPSILON && vel_z < STOP_EPSILON)
+ vel_z = 0;

return vel;
};
+#endif
+
+//======================================================================
+// PM_Rebound
+//
+// Alternative ClipVelocity that does ground checking.
+// For use with Eukara / Nuclide move.
+//----------------------------------------------------------------------
+void(vector normal, float ob, float oneside) PM_Rebound =
+{
+ local float backoff, backoffz;
+
+ backoff = self.velocity * normal;
+ backoffz = 0;
+
+ if (backoff < 0)
+ backoff *= ob;
+ else
+ if (oneside)
+ // backoff = 0;
+ backoff *= -0.001;
+ else
+ backoff /= ob;
+
+ self.velocity -= normal * backoff;
+
+ if (self.velocity_x > -STOP_EPSILON && self.velocity_x < STOP_EPSILON)
+ self.velocity_x = 0;
+ if (self.velocity_y > -STOP_EPSILON && self.velocity_y < STOP_EPSILON)
+ self.velocity_y = 0;
+ if (self.velocity_z > -STOP_EPSILON && self.velocity_z < STOP_EPSILON)
+ self.velocity_z = 0;
+
+ if (normal_z > 0.7)
+ {
+ if (trace_ent.solid == SOLID_BSP)
+ {
+ self.groundentity = trace_ent;
+ self.groundnormal = trace_plane_normal;
+ self.pmove_flags |= PMF_ONGROUND;
+ }
+ }
+ else
+ {
+ self.groundentity = __NULL__;
+ self.groundnormal = __NULL__;
+ self.pmove_flags &= ~PMF_ONGROUND;
+ }
+};

-#define PHYS_SLIDE_NUMBUMPS 4
-#define PHYS_SLIDE_MAX_CLIP_PLANES 5
-int(float dogravity, float onesided) phys_q1flymove =
+#define PM_SLIDE_NUMBUMPS 4
+#define PM_SLIDE_MAX_CLIP_PLANES 5
+//======================================================================
+// PM_Q1FlyMove
+//
+// Based on Quake 1's SV_FlyMove function (found in id's engine, QuakeSpasm,
+// and others). Has the disadvantage of using an array of vectors, and
+// is slow (I assume) in QuakeC. -- CEV
+//----------------------------------------------------------------------
+#if 0
+int(float dogravity, float onesided) PM_Q1FlyMove =
{
- vector planes[PHYS_SLIDE_MAX_CLIP_PLANES];
+ vector planes[PM_SLIDE_MAX_CLIP_PLANES];
vector dir, end, new_v, start_v;
int blocked, bumpcount, numplanes, i, j;
float d, ent_grav, grav, time_left;
@@ -99,7 +179,7 @@ int(float dogravity, float onesided) phys_q1flymove =
blocked = numplanes = 0;

// initialize all these vectors
- for (i = 0; i < PHYS_SLIDE_MAX_CLIP_PLANES; i++)
+ for (i = 0; i < PM_SLIDE_MAX_CLIP_PLANES; i++)
planes[i] = '0 0 0';
dir = end = new_v = '0 0 0';

@@ -109,7 +189,7 @@ int(float dogravity, float onesided) phys_q1flymove =
ent_grav = self.gravity;
else
ent_grav = 1.0;
- grav = ent_grav * cvar("sv_gravity") * input_timelength;
+ grav = ent_grav * autocvar(sv_gravity, 800) * input_timelength;
// we'll do half of it now, half later -- CEV
self.velocity_z -= grav * 0.5;
}
@@ -118,7 +198,7 @@ int(float dogravity, float onesided) phys_q1flymove =
start_v = self.velocity;

for (bumpcount = 0, time_left = input_timelength;
- time_left > 0 && bumpcount < PHYS_SLIDE_NUMBUMPS; bumpcount++)
+ time_left > 0 && bumpcount < PM_SLIDE_NUMBUMPS; bumpcount++)
{
end = self.origin + self.velocity * time_left;
tracebox (self.origin, self.mins, self.maxs, end, FALSE, self);
@@ -126,11 +206,14 @@ int(float dogravity, float onesided) phys_q1flymove =
if (trace_allsolid || trace_startsolid)
{
// entity is trapped in a solid; attempt to nudge out
- if (phys_nudge()) continue;
+ if (PM_Nudge())
+ continue;

// nah, we're stuck. don't build up falling damage
// but allow sideways acceleration
- dprint ("phys_q1flymove: entity trapped in a solid\n");
+ #ifdef SSQC
+ dprint ("PM_Q1FlyMove: entity trapped in a solid\n");
+ #endif
self.velocity_z = 0;
return 3;
}
@@ -138,7 +221,7 @@ int(float dogravity, float onesided) phys_q1flymove =
if (trace_fraction >= 0.001)
self.origin = trace_endpos;

- if (trace_fraction == 1)
+ if (trace_fraction >= 1.0f)
break;

if (trace_plane_normal_z > 0.7)
@@ -151,17 +234,19 @@ int(float dogravity, float onesided) phys_q1flymove =
if (!(trace_plane_normal_z))
blocked |= 2;

- phys_dotouch (trace_ent);
+ PM_DoTouch (trace_ent);
time_left -= time_left * trace_fraction;

- if (numplanes >= PHYS_SLIDE_MAX_CLIP_PLANES)
+ if (numplanes >= PM_SLIDE_MAX_CLIP_PLANES)
{
// this shouldn't really happen
if (cvar("developer"))
{
- dprint ("phys_q1flymove: numplanes >= max: ");
+ #ifdef SSQC
+ dprint ("PM_Q1FlyMove: numplanes >= max: ");
dprint (ftos(numplanes));
dprint ("\n");
+ #endif
}
self.velocity = '0 0 0';
blocked = 7;
@@ -174,7 +259,7 @@ int(float dogravity, float onesided) phys_q1flymove =
for (i = 0; i < numplanes; i++)
{
// slide along the plane
- new_v = phys_clipvelocity (self.velocity,
+ new_v = PM_ClipVelocity (self.velocity,
planes[i], PM_OVERCLIP, onesided);

for (j = 0; j < numplanes; j++)
@@ -191,7 +276,9 @@ int(float dogravity, float onesided) phys_q1flymove =
{
if (numplanes != 2)
{
- dprint ("phys_q1flymove: stopping dead\n");
+ #ifdef SSQC
+ dprint ("PM_Q1FlyMove: stopping dead\n");
+ #endif
self.velocity = '0 0 0';
blocked = 7;
break;
@@ -208,7 +295,9 @@ int(float dogravity, float onesided) phys_q1flymove =

if ((self.velocity * start_v) <= 0)
{
- dprint ("phys_q1flymove: turned against orig vel\n");
+ #ifdef SSQC
+ dprint ("PM_Q1FlyMove: turned against orig vel\n");
+ #endif
self.velocity = '0 0 0';
break;
}
@@ -218,28 +307,43 @@ int(float dogravity, float onesided) phys_q1flymove =
if ( // (self.primal_speed > PM_MAXSPEED) &&
(self.velocity != '0 0 0') &&
(self.jump_time) &&
- (!(self.flags & FL_WATERJUMP)) &&
+ (!(self.pmove_flags & PMF_WATERJUMP)) &&
(self.teleport_time <= (time - 0.1)) &&
(self.boost_time <= time - PM_BOOST_WINDOW) &&
(self.jump_time > (time - PM_WALLCLIP_WINDOW)) &&
(vlen(start_v) > vlen(self.velocity)))
{
- dprint ("phys_q1flymove: restoring velocity...\n");
- if (dogravity)
- start_v_z -= grav * 0.5;
- self.velocity = start_v;
- }
- else
- {
- // final gravity check here
- if (dogravity)
- self.velocity_z -= grav * 0.5;
+ #ifdef SSQC
+ dprint ("PM_Q1FlyMove: restoring velocity...\n");
+ #endif
+ self.velocity = [start_v_x, start_v_y, self.velocity_z];
}

+ // final gravity check here
+ if (dogravity)
+ self.velocity_z -= grav * 0.5;
+
+ /* for debugging -- CEV
+ #ifdef SSQC
+ dprint ("PM_Q1FlyMove: numplanes ");
+ dprint (ftos(numplanes));
+ dprint ("\n");
+ #endif
+ */
+
return blocked;
};
-
-void(float dogravity, float onesided) phys_stepslidemove =
+#endif
+
+//======================================================================
+// PM_StepSlideMove
+//
+// Based on the StepSlideMove function found in the Quake III sourcecode.
+// Calls PM_Q1FlyMove several times. This works, but is slow and has
+// some tracking issues (probably my fault). -- CEV
+//----------------------------------------------------------------------
+#if 0
+void(float dogravity, float onesided) PM_StepSlideMove =
{
vector start_o, start_v, first_o, first_v;
vector up, down;
@@ -250,19 +354,21 @@ void(float dogravity, float onesided) phys_stepslidemove =
clip = first_clip = 0;
start_o = self.origin;
start_v = self.velocity;
- start_onground = (self.flags & FL_ONGROUND);
+ start_onground = (self.pmove_flags & PMF_ONGROUND);

// first try let's go
- first_clip = phys_q1flymove (dogravity, onesided);
+ first_clip = PM_Q1FlyMove (dogravity, onesided);

if (!(first_clip & 2) && !(first_clip & 8))
{
// we got where we wanted to go right away
- // dprint ("phys_stepslidemove: accepting first move\n");
+ // #ifdef SSQC
+ // dprint ("PM_StepSlideMove: accepting first move\n");
+ // #endif
if (first_clip & 1)
- self.flags |= FL_ONGROUND;
+ self.pmove_flags |= PMF_ONGROUND;
else
- self.flags &= ~FL_ONGROUND;
+ self.pmove_flags &= ~PMF_ONGROUND;
return;
}

@@ -270,10 +376,15 @@ void(float dogravity, float onesided) phys_stepslidemove =
// gibbed by a trigger?
return;

- if (cvar("sv_nostep"))
+ if (autocvar(pm_nostep, FALSE))
// no stepping. useful for testing -- CEV
return;

+ if (!(autocvar(pm_airstep, TRUE)) && !(self.pmove_flags & PMF_ONGROUND))
+ // Borrowing FTE's pm_airstep cvar here. If false, don't
+ // step up while in the air (changes stairs) -- CEV
+ return;
+
first_o = self.origin;
first_v = self.velocity;

@@ -286,13 +397,15 @@ void(float dogravity, float onesided) phys_stepslidemove =

if (trace_allsolid)
{
- dprint ("phys_stepslidemove: can't step up\n");
+ #ifdef SSQC
+ dprint ("PM_StepSlideMove: can't step up\n");
+ #endif
self.origin = first_o;
self.velocity = first_v;
if (first_clip & 1)
- self.flags |= FL_ONGROUND;
+ self.pmove_flags |= PMF_ONGROUND;
else
- self.flags &= ~FL_ONGROUND;
+ self.pmove_flags &= ~PMF_ONGROUND;
return;
}

@@ -300,7 +413,7 @@ void(float dogravity, float onesided) phys_stepslidemove =
stepsize = trace_endpos_z - start_o_z;
self.origin = trace_endpos;
self.velocity = start_v;
- clip = phys_q1flymove (dogravity, onesided);
+ clip = PM_Q1FlyMove (dogravity, onesided);

// push down the final amount
down = self.origin;
@@ -309,50 +422,56 @@ void(float dogravity, float onesided) phys_stepslidemove =

if (trace_allsolid)
{
- dprint ("phys_stepslidemove: second move is in a solid\n");
+ #ifdef SSQC
+ dprint ("PM_StepSlideMove: second move is in a solid\n");
+ #endif
self.origin = first_o;
self.velocity = first_v;
if (first_clip & 1)
- self.flags |= FL_ONGROUND;
+ self.pmove_flags |= PMF_ONGROUND;
else
- self.flags &= ~FL_ONGROUND;
+ self.pmove_flags &= ~PMF_ONGROUND;
return;
}

if (!trace_plane_normal_z || trace_plane_normal_z > 0.7)
{
// we're on 'good ground', accept the second slidemove
- // dprint ("phys_stepslidemove: accepting second slidemove\n");
+ // #ifdef SSQC
+ // dprint ("PM_StepSlideMove: accepting second slidemove\n");
+ // #endif
self.origin = trace_endpos;
if (trace_fraction < 1.0)
{
// clip to step
- self.velocity = phys_clipvelocity (self.velocity,
+ self.velocity = PM_ClipVelocity (self.velocity,
trace_plane_normal, PM_OVERCLIP, onesided);
}
if (trace_plane_normal_z > 0.7)
- self.flags |= FL_ONGROUND;
+ self.pmove_flags |= PMF_ONGROUND;
else
- self.flags &= ~FL_ONGROUND;
+ self.pmove_flags &= ~PMF_ONGROUND;
}
else
{
// not on 'good ground', revert to first slidemove
// see the similar section of SV_WalkMove
- // dprint ("phys_stepslidemove: reverting to first move\n");
+ // #ifdef SSQC
+ // dprint ("PM_StepSlideMove: reverting to first move\n");
+ // #endif
self.origin = first_o;
self.velocity = first_v;
if (first_clip & 1)
- self.flags |= FL_ONGROUND;
+ self.pmove_flags |= PMF_ONGROUND;
else
- self.flags &= ~FL_ONGROUND;
+ self.pmove_flags &= ~PMF_ONGROUND;
}

// this is a complicated check.
// if we started in the air and we're now on the ground
// and we stepped up and we lost some Z velocity then we've
// clipped to ground on a step up
- if (!start_onground && (self.flags & FL_ONGROUND) &&
+ if (!start_onground && (self.pmove_flags & PMF_ONGROUND) &&
(start_v_z > self.velocity_z) &&
(self.velocity_z < 1) &&
(self.origin_z - start_o_z > 0))
@@ -363,35 +482,220 @@ void(float dogravity, float onesided) phys_stepslidemove =

if (cvar("developer"))
{
+ #ifdef SSQC
stepsize = self.origin_z - start_o_z;
- dprint (sprintf("phys_stepslidemove: step up: %g\n",
+ dprint (sprintf("PM_StepSlideMove: step up: %g\n",
stepsize));
+ #endif
}
}
};
-
-// based on the GPL2 Quake 3 sourcecode. No idea what it does other than
-// make strafejumping feel, I dunno, more "right". -- CEV
-float(float speed, float forward, float side, float up) phys_pm_cmdscale =
+#endif
+
+//======================================================================
+// PM_NuclideMove
+//
+// Updates origin, moves the player through the world. Similar to Q3
+// SlideMove and Q1 FlyMove. This version applies gravity and restores
+// velocity based on a timer check (both features of Quake 3's pmove).
+//
+// Based on code from the Nuclide SDK (presumably by Eukara), specifically
+// the function PMoveCustom_Move found in the file pmove_custom.qc.
+// This in turn appears to be based on a similar function in CSQCTest.
+//----------------------------------------------------------------------
+void(float dogravity, float onesided) PM_NuclideMove =
{
- float scale, total;
- int max;
+ vector end, saved_plane, start_o, start_v;
+ float dostep, ent_grav, grav, stepsize, time_left;
+ int i, start_onground;
+
+ if (dogravity)
+ {
+ if (self.gravity)
+ ent_grav = self.gravity;
+ else
+ ent_grav = 1.0;
+ grav = ent_grav * autocvar(sv_gravity, 800) * input_timelength;
+ // Half now, half later. Apparently affects framerate
+ // dependence. -- CEV
+ self.velocity_z -= grav * 0.5;
+ }
+
+ start_o = self.origin;
+ start_v = self.velocity;
+ start_onground = (self.pmove_flags & PMF_ONGROUND);
+
+ dostep = TRUE;
+ if (autocvar(pm_nostep, FALSE))
+ // no stepping. useful for testing -- CEV
+ dostep = FALSE;
+
+ if (!(autocvar(pm_airstep, TRUE)) && !(self.pmove_flags & PMF_ONGROUND))
+ // Borrowing FTE's pm_airstep cvar here. If false, don't
+ // step up while in the air (changes stairs) -- CEV
+ dostep = FALSE;
+
+ // we need to bounce off surfaces (in order to slide along them),
+ // so we need at 2 attempts -- comment from Nuclide
+ // I've changed this to a larger number of attempts (from 3 to 5)
+ // to accommodate more complex plane interactions -- CEV
+ i = PM_SLIDE_NUMBUMPS + 1;
+ for (time_left = input_timelength; time_left > 0 && i; i--)
+ {
+ end = self.origin + (self.velocity * time_left);
+ tracebox (self.origin, self.mins, self.maxs, end, FALSE, self);
+
+ if (trace_allsolid || trace_startsolid)
+ {
+ // entity is trapped in a solid; attempt to nudge out
+ if (PM_Nudge())
+ continue;
+
+ // nah, we're stuck. don't build up falling damage
+ // but allow sideways acceleration -- CEV
+ #ifdef SSQC
+ dprint ("PM_NuclideMove: entity trapped in a solid\n");
+ #endif
+ self.velocity_z = 0;
+ break;
+ }
+
+ self.origin = trace_endpos;
+
+ if (trace_fraction >= 1.0f)
+ {
+ setorigin (self, self.origin);
+ break;
+ }
+
+ saved_plane = trace_plane_normal;
+ time_left -= time_left * trace_fraction;
+
+ // integrated StepSlideMove -- CEV
+ if (time_left && dostep)
+ {
+ // step up if we can
+ // first: move up
+ trace_endpos = self.origin;
+ trace_endpos_z += PM_STEPHEIGHT;
+ tracebox (self.origin, self.mins, self.maxs,
+ trace_endpos, FALSE, self);
+ stepsize = trace_endpos_z - self.origin_z;
+
+ local float roof_fraction = trace_fraction;
+ local vector roof_plane_normal = trace_plane_normal;
+
+ // second: move forward
+ end = trace_endpos + (self.velocity * time_left);
+ end_z = trace_endpos_z;
+ tracebox (trace_endpos, self.mins, self.maxs,
+ end, FALSE, self);
+
+ if (trace_fraction == 1.0f)
+ {
+ local float fwd_fraction = trace_fraction;
+ local vector fwd_plane = trace_plane_normal;
+
+ // third: move down
+ end = trace_endpos;
+ end_z -= stepsize;
+ tracebox (trace_endpos, self.mins, self.maxs,
+ end, FALSE, self);
+
+ if (trace_fraction < 1.0f &&
+ trace_plane_normal_z > 0.7f)
+ {
+ time_left -= time_left * fwd_fraction;
+
+ // we hit the ceiling; clip velocity
+ if (roof_fraction < 1.0f)
+ PM_Rebound (roof_plane_normal,
+ PM_OVERCLIP, onesided);
+
+ // clip velocity to either the down
+ // or forward move if either hit
+ // something
+ if (trace_fraction < 1.0f)
+ PM_Rebound (trace_plane_normal,
+ PM_OVERCLIP, onesided);
+ else if (fwd_fraction < 1.0f)
+ PM_Rebound (fwd_plane,
+ PM_OVERCLIP, onesided);
+
+ // accept the down move
+ self.origin = trace_endpos;
+ continue;
+ }
+ }
+ }
+
+ // stepping not requested or did not succeed.
+ // clip velocity to the plane from the outermost loop
+ // (saved_plane) then touch trace_ent.
+ // This may have tracking problems (trace_ent might
+ // not correspond to saved_plane) -- CEV
+ PM_Rebound (saved_plane, PM_OVERCLIP, onesided);
+ PM_DoTouch (trace_ent);
+ }
+
+ // wallclip / wall skim timer check
+ // in order: velocity is non-zero, we're within WALLCLIP_WINDOW,
+ // we haven't just teleported, we're not waterjumping, and we
+ // lost speed during the move -- CEV
+ if (self.velocity && self.jump_time > (time - PM_WALLCLIP_WINDOW) &&
+ (self.teleport_time <= (time - 0.1)) &&
+ (!(self.pmove_flags & PMF_WATERJUMP)) &&
+ (vlen(start_v) > vlen(self.velocity)))
+ {
+ #ifdef SSQC
+ dprint ("PM_NuclideMove: wallclip, restoring velocity...\n");
+ #endif
+ // take whichever Z velocity is lower; fixes steep ramps -- CEV
+ if (start_v_z > self.velocity_z)
+ self.velocity = [start_v_x, start_v_y, self.velocity_z];
+ else
+ self.velocity = start_v;
+ }

- max = fabs (forward);
- if (fabs(side) > max)
- max = fabs (side);
- if (fabs(up) > max)
- max = fabs (up);
- if (!max)
- return 0;
+ // final gravity check here
+ if (dogravity)
+ self.velocity_z -= grav * 0.5;

- total = sqrt (forward * forward + side * side + up * up);
- scale = speed * max / (127.0 * total);
+ // manage the "boost" timer -- CEV
+ // this seems like an overly complicated check -- CEV
+ if (!start_onground && (self.pmove_flags & PMF_ONGROUND) &&
+ (start_v_z > self.velocity_z) &&
+ (self.velocity_z < 1) &&
+ (self.origin_z - start_o_z > 0))
+ {
+ if (!self.boost_time &&
+ self.boost_time <= time - PM_BOOST_WINDOW)
+ self.boost_time = time;
+ /*
+ if (cvar("developer"))
+ {
+ // more debugging -- CEV
+ #ifdef SSQC
+ local float stepsize2;
+ stepsize2 = self.origin_z - start_o_z;
+ dprint (sprintf("PM_NuclideMove: step up: %g, %g\n",
+ stepsize, stepsize2));
+ #endif
+ }
+ */
+ }

- return scale;
+ /*
+ #ifdef SSQC
+ if (cvar("developer"))
+ // for debugging purposes -- CEV
+ dprint (sprintf("PM_NuclideMove: %i bumps\n", 5 - i));
+ #endif
+ */
};

-void(float friction) phys_friction =
+//----------------------------------------------------------------------
+void(float friction) PM_Friction =
{
float control, newspeed, speed;

@@ -408,11 +712,13 @@ void(float friction) phys_friction =
newspeed = speed - control * friction * input_timelength;

// and slow them
- if (newspeed < 0) newspeed = 0;
+ if (newspeed < 0)
+ newspeed = 0;
self.velocity = self.velocity * (newspeed / speed);
};

-void(entity ground_e, vector ground_v, int docheck) phys_setonground =
+//----------------------------------------------------------------------
+void(entity ground_e, vector ground_v, int docheck) PM_SetOnground =
{
// look for ground with tracebox if requested
if (docheck)
@@ -446,40 +752,56 @@ void(entity ground_e, vector ground_v, int docheck) phys_setonground =
if (self.groundnormal != __NULL__)
{
// on ground
- self.flags |= FL_ONGROUND;
- self.flags &= ~FL_WALLJUMP;
+ if (!(self.pmove_flags & PMF_ONGROUND))
+ // transitioning from in-air to onground
+ self.land_time = time;
+ self.pmove_flags |= PMF_ONGROUND;
+ self.pmove_flags &= ~PMF_WALLJUMP;
}
else
{
// not on ground
- self.flags &= ~FL_ONGROUND;
+ if (self.pmove_flags & PMF_ONGROUND)
+ self.land_time = 0;
+ self.pmove_flags &= ~PMF_ONGROUND;
}
+
+ if (self.pmove_flags & PMF_ONGROUND)
+ self.flags |= FL_ONGROUND;
+ else
+ self.flags &= ~FL_ONGROUND;
};

-// function based on GPL2 purecsqc pmove.qc
-void() phys_categorizeposition =
+//======================================================================
+// PM_CategorizePosition
+// Based on similarly-named function in the GPL2 purecsqc pmove.qc
+//----------------------------------------------------------------------
+void() PM_CategorizePosition =
{
vector p;
float pc;

if (self.movetype == MOVETYPE_NOCLIP)
// noclip is never on ground
- phys_setonground (__NULL__, __NULL__, FALSE);
+ PM_SetOnground (__NULL__, __NULL__, FALSE);
else
- phys_setonground (__NULL__, __NULL__, TRUE);
+ // do a trace to check
+ PM_SetOnground (__NULL__, __NULL__, TRUE);

// clear doublejumped if outside of DOUBLEJUMP_COOLDOWN
- if ((self.flags & FL_DOUBLEJUMPED)
+ if ((self.pmove_flags & PMF_DOUBLEJUMPED)
&& self.jump_time < (time - PM_DOUBLEJUMP_COOLDOWN))
{
- // dprint ("phys_categorize: clear FL_DOUBLEJUMPED\n");
- self.flags &= ~FL_DOUBLEJUMPED;
+ // #ifdef SSQC
+ // dprint ("PM_Categorize: clear FL_DOUBLEJUMPED\n");
+ // #endif
+ self.pmove_flags &= ~PMF_DOUBLEJUMPED;
}

// check water levels
p = self.origin;
p_z = self.origin_z + self.mins_z + 1;
- pc = pointcontents(p);
+ pc = pointcontents (p);
if (pc < CONTENT_SOLID)
{
self.watertype = pc;
@@ -493,7 +815,9 @@ void() phys_categorizeposition =
self.waterlevel = 2;
}
else
+ {
self.waterlevel = 1;
+ }
}
else
{
@@ -502,14 +826,16 @@ void() phys_categorizeposition =
}
};

-void(vector wishdir, float wishspeed, float accel) phys_accelerate =
+//----------------------------------------------------------------------
+void(vector wishdir, float wishspeed, float accel) PM_Accelerate =
{
float addspeed, accelspeed, curspeed;

curspeed = self.velocity * wishdir;
addspeed = wishspeed - curspeed;

- if (addspeed <= 0) return;
+ if (addspeed <= 0)
+ return;

accelspeed = accel * input_timelength * wishspeed;
if (accelspeed > addspeed) accelspeed = addspeed;
@@ -517,7 +843,8 @@ void(vector wishdir, float wishspeed, float accel) phys_accelerate =
self.velocity = self.velocity + accelspeed * wishdir;
};

-void(vector wishvel, float wishspeed, float accel) phys_q1airaccelerate =
+//----------------------------------------------------------------------
+void(vector wishvel, float wishspeed, float accel) PM_Q1AirAccelerate =
{
float addspeed, wishspd, accelspeed, currentspeed;

@@ -528,7 +855,8 @@ void(vector wishvel, float wishspeed, float accel) phys_q1airaccelerate =
if (wishspd > PM_MAXAIRSPEED) wishspd = PM_MAXAIRSPEED;

addspeed = wishspd - currentspeed;
- if (addspeed <= 0) return;
+ if (addspeed <= 0)
+ return;

accelspeed = accel * input_timelength * wishspeed;
if (accelspeed > addspeed) accelspeed = addspeed;
@@ -536,127 +864,167 @@ void(vector wishvel, float wishspeed, float accel) phys_q1airaccelerate =
self.velocity = self.velocity + accelspeed * wishvel;
};

-// based on code from Xonotic -- CEV
-void(vector wishdir, float wishspeed, float accel) phys_aircontrol =
+//======================================================================
+// PM_AirControl
+// CPM-like Air Control. Based on Xonotic and an old experiment. -- CEV
+//----------------------------------------------------------------------
+void(vector wishdir, float wishspeed, float accel) PM_AirControl =
{
- float addspeed, accelspeed, curspeed, speed, dot, k, z;
+ local float dot, xyspeed, zspeed;

- z = self.velocity_z;
+ zspeed = self.velocity_z;
self.velocity_z = 0;
- speed = vlen (self.velocity);
- curspeed = self.velocity * wishdir;
- addspeed = wishspeed - curspeed;

+ PM_Accelerate (wishdir, wishspeed, accel);
+
+ xyspeed = vlen (self.velocity);
self.velocity = normalize (self.velocity);
dot = self.velocity * wishdir;
- k = 4800 * dot * dot * input_timelength;

if (dot > 0)
- self.velocity = self.velocity * speed + wishdir * k;
-
- self.velocity = normalize (self.velocity);
- self.velocity = self.velocity * speed;
-
- if (addspeed > 0)
{
- accelspeed = accel * input_timelength * wishspeed;
- if (accelspeed > addspeed) accelspeed = addspeed;
-
- self.velocity = self.velocity + accelspeed * wishdir;
+ self.velocity = normalize (self.velocity * xyspeed +
+ wishdir * PM_AIRACCELTURN);
}

- self.velocity_z = z;
+ self.velocity = self.velocity * xyspeed;
+ self.velocity_z = zspeed;
};

-void() phys_jump =
+//----------------------------------------------------------------------
+void() PM_Jump =
{
// are we already waterjumping?
- if (self.flags & FL_WATERJUMP) return;
+ if (self.pmove_flags & PMF_WATERJUMP)
+ return;

// are we noclipping?
- if (self.movetype == MOVETYPE_NOCLIP) return;
+ if (self.movetype == MOVETYPE_NOCLIP)
+ return;

// don't pogo
- if (!(self.flags & FL_JUMPRELEASED)) return;
+ if (self.pmove_flags & PMF_JUMP_HELD)
+ return;

// don't let the player jump more often than JUMP_WINDOW -- CEV
+ /*
if ((self.jump_time) && (self.jump_time > time - PM_JUMP_WINDOW))
return;
-
- // player jumping sound
- sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
+ */

// make sure we get at least jumpspeed upwards from
// the ground plane by clamping it first.
if (self.groundnormal && (self.velocity * self.groundnormal < 0))
{
- // dprint("phys_jump: clamping to ground\n");
+ // #ifdef SSQC
+ // dprint("PM_Jump: clamping to ground\n");
+ // #endif
self.velocity -= self.groundnormal *
(self.velocity * self.groundnormal);
}

+ // make sure we get at least the indicated jump speed
+ // this changes the behavior of downward ramps -- CEV
+ if (self.velocity_z < 0)
+ self.velocity_z = 0;
+
// teleport jumps; allow a larger (+0.2) window to account for
// time to travel thru teleporter. -- CEV
if ((self.jump_time > time - PM_TELEJUMP_WINDOW) &&
(self.teleport_time > time - (PM_TELEJUMP_WINDOW + 0.2)))
{
- dprint ("phys_jump: telejump\n");
+ #ifdef SSQC
+ dprint ("PM_Jump: telejump ");
+ dprint (ftos(self.velocity_z));
+ dprint (", ");
+ #endif
self.velocity_z += PM_TELEJUMPSPEED;
- if !(self.flags & FL_DOUBLEJUMPED)
- self.flags |= FL_DOUBLEJUMPED;
+ if !(self.pmove_flags & PMF_DOUBLEJUMPED)
+ self.pmove_flags |= PMF_DOUBLEJUMPED;
}
// A doublejump is two jumps within 400ms, usually +50% Z velocity.
else if (self.jump_time > (time - PM_DOUBLEJUMP_WINDOW))
{
- if (self.boost_time && self.boost_time > time - PM_BOOST_WINDOW)
- dprint ("phys_jump: stairjump\n");
+ if (self.boost_time && self.boost_time >
+ (time - PM_BOOST_WINDOW))
+ {
+ #ifdef SSQC
+ dprint ("PM_Jump: stairjump ");
+ #endif
+ }
else
- dprint ("phys_jump: doublejump\n");
- if (self.flags & FL_DOUBLEJUMPED)
+ {
+ #ifdef SSQC
+ dprint ("PM_Jump: doublejump ");
+ #endif
+ }
+ #ifdef SSQC
+ dprint (ftos(self.velocity_z));
+ dprint (", ");
+ #endif
+ if (self.pmove_flags & PMF_DOUBLEJUMPED)
{
self.velocity_z += PM_TRIPLEJUMPSPEED;
}
else
{
self.velocity_z += PM_DOUBLEJUMPSPEED;
- self.flags |= FL_DOUBLEJUMPED;
+ self.pmove_flags |= PMF_DOUBLEJUMPED;
}
}
// normal jump
else
{
+ #ifdef SSQC
+ dprint ("PM_Jump: jump ");
+ dprint (ftos(self.velocity_z));
+ dprint (", ");
+ #endif
self.velocity_z += PM_JUMPSPEED;
}

+ // report Z velocity
+ #ifdef SSQC
+ dprint (ftos(self.velocity_z));
+ dprint ("\n");
+ #endif
+
// clear flags
- phys_setonground (__NULL__, __NULL__, FALSE);
- self.flags &~= FL_JUMPRELEASED;
- self.button2 = 0;
+ PM_SetOnground (__NULL__, __NULL__, FALSE);
+ self.pmove_flags |= PMF_JUMP_HELD;
// timers
self.jump_time = time;
if (self.boost_time)
{
- // dprint ("phys_jump: clearing boost_time\n");
+ // #ifdef SSQC
+ // dprint ("PM_Jump: clearing boost_time\n");
+ // #endif
self.boost_time = 0;
}
};

-void(vector checkdir) phys_walljump =
+//----------------------------------------------------------------------
+void(vector checkdir) PM_WallJump =
{
// is our upward speed greater than walljump speed?
- if (self.velocity_z > PM_WALLJUMPSPEED) return;
+ if (self.velocity_z > PM_WALLJUMPSPEED)
+ return;

// are we already waterjumping?
- if (self.flags & FL_WATERJUMP) return;
+ if (self.pmove_flags & PMF_WATERJUMP)
+ return;

// are we already walljumping?
- if (self.flags & FL_WALLJUMP) return;
+ if (self.pmove_flags & PMF_WALLJUMP)
+ return;

// are we noclipping?
- if (self.movetype == MOVETYPE_NOCLIP) return;
+ if (self.movetype == MOVETYPE_NOCLIP)
+ return;

// don't pogo
- if (!(self.flags & FL_JUMPRELEASED)) return;
+ if (self.pmove_flags & PMF_JUMP_HELD)
+ return;

// don't let the player jump more often than WALLJUMP_WINDOW -- CEV
if ((self.jump_time) && (self.jump_time > time - PM_WALLJUMP_WINDOW))
@@ -675,10 +1043,14 @@ void(vector checkdir) phys_walljump =
if (trace_fraction < 1 && trace_plane_normal_z < 0.2 &&
(vlen(self.origin - trace_endpos) < 10))
{
- dprint (sprintf("phys_walljump: walljump dist %g\n",
+ #ifdef SSQC
+ dprint (sprintf("PM_WallJump: walljump dist %g\n",
vlen(self.origin - trace_endpos)));
+ #endif
// player jumping sound
+ #ifndef CSQC
sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
+ #endif
// modify X and Y velocity
self.velocity_x += trace_plane_normal_x * PM_WALLJUMPFORCE;
self.velocity_y += trace_plane_normal_y * PM_WALLJUMPFORCE;
@@ -686,16 +1058,15 @@ void(vector checkdir) phys_walljump =
if (self.jump_time > (time - PM_DOUBLEJUMP_WINDOW))
{
self.velocity_z += PM_DOUBLEJUMPSPEED;
- // if (self.velocity_z > PM_DOUBLEJUMPSPEED)
- // self.velocity_z = PM_DOUBLEJUMPSPEED;
}
else if (self.velocity_z < (PM_WALLJUMPSPEED / 0.5))
self.velocity_z = PM_WALLJUMPSPEED;
else
self.velocity_z += PM_WALLJUMPSPEED;
// set walljump flag
- self.flags |= FL_WALLJUMP;
+ self.pmove_flags |= PMF_WALLJUMP;
// clear misc flags & ground fields
+ self.pmove_flags |= PMF_JUMP_HELD;
self.button2 = 0;
self.groundnormal = __NULL__;
self.groundentity = __NULL__;
@@ -704,26 +1075,29 @@ void(vector checkdir) phys_walljump =
}
};

-void() phys_waterjump =
+//----------------------------------------------------------------------
+void() PM_WaterJump =
{
// can't be waterjumping if we're on ground
- if ((self.flags & FL_WATERJUMP) &&
+ if ((self.pmove_flags & PMF_WATERJUMP) &&
(((time > self.teleport_time) && !(self.waterlevel)) ||
- (self.flags & FL_ONGROUND)))
+ (self.pmove_flags & PMF_ONGROUND)))
{
- dprint ("phys_waterjump: clearing FL_WATERJUMP\n");
+ #ifdef SSQC
+ dprint ("PM_WaterJump: clearing FL_WATERJUMP\n");
+ #endif
+ self.pmove_flags &= ~PMF_WATERJUMP;
self.flags &= ~FL_WATERJUMP;
self.teleport_time = 0;
}
};

-int() phys_walkaccelerate =
+//----------------------------------------------------------------------
+int() PM_WalkAccelerate =
{
vector forward, right, up;
vector wishvel, wishdir, wishang;
- vector curang;
- float tempf, wishspeed;
- float scale;
+ float wishspeed;
int onesided;

onesided = FALSE;
@@ -746,97 +1120,79 @@ int() phys_walkaccelerate =
wishspeed = vlen (wishvel);
wishdir = normalize (wishvel);

- /* TODO CEV
- if (self.primal_speed > PM_MAXSPEED * 0.1)
- {
- scale = phys_pm_cmdscale (self.primal_speed, input_movevalues_x,
- input_movevalues_y, input_movevalues_z);
- if (scale > 0)
- {
- dprint ("phys_walkaccelerate: applying scale ");
- dprint (ftos(scale));
- dprint ("\n");
- wishspeed *= scale;
- }
- }
- */
-
- if (wishspeed > PM_MAXSPEED) wishspeed = PM_MAXSPEED;
+ if (wishspeed > PM_MAXSPEED)
+ wishspeed = PM_MAXSPEED;

if (input_buttons & 2)
- if (self.flags & FL_ONGROUND)
- phys_jump ();
- else
- phys_walljump (right);
- else
- self.flags |= FL_JUMPRELEASED;
+ // +jump was pressed
+ if (self.pmove_flags & PMF_ONGROUND)
+ PM_Jump ();
+ // else
+ // PM_WallJump (right);

- if (self.flags & FL_ONGROUND)
+ if (self.pmove_flags & PMF_ONGROUND)
{
- if (self.boost_time > time - PM_BOOST_WINDOW)
+ if (self.boost_time > (time - PM_BOOST_WINDOW))
{
- phys_friction (PM_BOOSTFRICTION);
- phys_accelerate (wishdir, wishspeed, PM_BOOSTACCEL);
+ PM_Friction (PM_BOOSTFRICTION);
+ PM_Accelerate (wishdir, wishspeed, PM_BOOSTACCEL);
}
else
{
- phys_friction (PM_FRICTION);
- phys_accelerate (wishdir, wishspeed, PM_GROUNDACCEL);
+ PM_Friction (PM_FRICTION);
+ PM_Accelerate (wishdir, wishspeed, PM_GROUNDACCEL);
}
}
else
{
- // Q3 strafejumping if requesting both X and Y
+ // Quake 3 strafejumping if requesting both X and Y
// -- CEV
if (input_movevalues_x && input_movevalues_y)
{
- phys_accelerate (wishdir, wishspeed, PM_AIRACCELQ3);
+ PM_Accelerate (wishdir, wishspeed, PM_AIRACCELQ3);
}
else
{
// I'm a little afraid doing this is expensive
// CPU-wise but it seems to be the right way.
// this is inspired by the old Slide mod -- CEV
- if (self.primal_speed > 30)
- {
- wishang = vectoangles (wishdir);
- curang = vectoangles (self.velocity);
- wishang_y = anglemod (wishang_y);
- curang_y = anglemod (curang_y);
-
- tempf = fabs (wishang_y - curang_y);
- if (tempf >= 180) tempf = fabs (tempf - 360);
- /*
- dprint ("phys_walkaccelerate: tempf ");
- dprint (ftos(tempf));
- dprint (", input_movevalues_x: ");
- dprint (ftos(input_movevalues_x));
- dprint (", input_movevalues_y: ");
- dprint (ftos(input_movevalues_y));
- dprint ("\n");
- */
- }
- else
- {
- tempf = 0;
- }
+
+ // calculate the difference between the angle
+ // we're currently moving and the angle the
+ // user is requesting to move
+ wishang = vectoangles (wishdir) -
+ vectoangles (self.velocity);
+ wishang_y = anglemod (wishang_y);
+
+ // limit wishang_y to a range of 0-180 (roughly)
+ if (wishang_y >= 180)
+ wishang_y = fabs (wishang_y - 360);
+
+ /*
+ #ifdef SSQC
+ dprint ("PM_WalkAccelerate: wishang_y ");
+ dprint (ftos(wishang_y));
+ dprint ("\n");
+ #endif
+ */

// Q1 air control when requesting movement within
- // 45 to 130 degrees of current movement -- CEV
- if ((tempf > 45) && (tempf < 135))
+ // 45 to 135 degrees of current movement -- CEV
+ if ((wishang_y > 45) && (wishang_y < 135) &&
+ self.primal_speed >= 180)
{
- phys_q1airaccelerate (wishvel, wishspeed,
+ PM_Q1AirAccelerate (wishvel, wishspeed,
PM_AIRACCEL);
}
// +direction style air control otherwise -- CEV
else
{
- if (tempf >= 135)
+ if (wishang_y >= 135)
// we're slowing down / stopping
- phys_aircontrol (wishdir, wishspeed,
+ PM_AirControl (wishdir, wishspeed,
PM_AIRACCELBACK);
else
- phys_aircontrol (wishdir, wishspeed,
+ PM_AirControl (wishdir, wishspeed,
PM_AIRACCELFWD);
}
}
@@ -844,7 +1200,8 @@ int() phys_walkaccelerate =
return onesided;
};

-void(float scale) phys_noclipaccelerate =
+//----------------------------------------------------------------------
+void(float scale) PM_NoClipAccelerate =
{
vector wishdir;
float wishspeed;
@@ -866,42 +1223,65 @@ void(float scale) phys_noclipaccelerate =
wishspeed = vlen (wishdir) * scale;
wishdir = normalize (wishdir);

- phys_friction (PM_FRICTION);
- phys_accelerate (wishdir, wishspeed, PM_GROUNDACCEL);
+ PM_Friction (PM_FRICTION);
+ PM_Accelerate (wishdir, wishspeed, PM_GROUNDACCEL);
};

-void(entity ent) phys_move =
+//======================================================================
+// PM_Move -- PMOVE entrypoint -- CEV
+//----------------------------------------------------------------------
+void(entity target) PM_Move =
{
+ entity oldself;
float dogravity, onesided;

- self = ent;
+ oldself = self;
+ self = target;
onesided = FALSE;

- phys_nudge ();
- phys_categorizeposition ();
- phys_waterjump ();
+ PM_Nudge ();
+
+ if (!(input_buttons & 2))
+ self.pmove_flags &= ~PMF_JUMP_HELD;
+
+ PM_CategorizePosition ();
+ PM_WaterJump ();
+
+ // save velocity + speed here -- CEV
+ self.primal_velocity = self.velocity;
+ self.primal_speed = vlen ([self.velocity_x, self.velocity_y, 0]);

if (self.boost_time && self.boost_time <= time - PM_BOOST_WINDOW)
{
// Clear the boost timer if it's set
- // dprint ("phys_move: clearing boost_time\n");
+ // #ifdef SSQC
+ // dprint ("PM_Move: clearing boost_time\n");
+ // #endif
self.boost_time = 0;
}

- if (input_timelength >= 0)
+ if (input_timelength < 0)
+ {
+ dprint (sprintf("PM_Move: returning, input_timelength: %g\n",
+ input_timelength));
+ self = oldself;
+ return;
+ }
+
+ switch (self.movetype)
{
- switch(self.movetype)
- {
case MOVETYPE_WALK:
if (self.waterlevel >= 2)
{
- phys_noclipaccelerate (0.7);
+ PM_NoClipAccelerate (0.7);
// water friction
self.velocity -= 0.8 * self.waterlevel *
input_timelength * self.velocity;
}
else
- onesided = phys_walkaccelerate ();
+ {
+ onesided = PM_WalkAccelerate ();
+ }

// onesided if outside DOUBLEJUMP_WINDOW time
if (self.jump_time <= (time - PM_DOUBLEJUMP_WINDOW))
@@ -909,43 +1289,43 @@ void(entity ent) phys_move =

// don't stick to the floor when stepping up if we've
// doublejumped recently
- if (self.flags & FL_DOUBLEJUMPED)
+ if (self.pmove_flags & PMF_DOUBLEJUMPED)
onesided = TRUE;

// don't stick to the floor when jumping out of water
- if ((self.flags & FL_WATERJUMP) ||
- (self.flags & FL_WALLJUMP))
+ if ((self.pmove_flags & PMF_WATERJUMP) ||
+ (self.pmove_flags & PMF_WALLJUMP))
onesided = TRUE;

// apply gravity when in the air
- dogravity = !(self.flags & FL_ONGROUND);
+ dogravity = !(self.pmove_flags & PMF_ONGROUND);

// apply gravity when we're on a ramp
if (self.groundnormal && self.groundnormal_z < 1 &&
- self.groundnormal_z > 0.7)
+ // self.groundnormal_z > 0.7)
+ self.groundnormal_z > 0)
dogravity = TRUE;

- phys_stepslidemove (dogravity, onesided);
+ PM_NuclideMove (dogravity, onesided);
break;
+
case MOVETYPE_FLY:
- phys_noclipaccelerate (1.0);
- phys_q1flymove (FALSE, TRUE);
+ PM_NoClipAccelerate (1.0);
+ PM_NuclideMove (FALSE, TRUE);
break;
+
case MOVETYPE_NOCLIP:
- phys_noclipaccelerate (1.0);
+ PM_NoClipAccelerate (1.0);
self.origin += self.velocity * input_timelength;
break;
+
case MOVETYPE_NONE:
break;
- }
-
- if (self.groundentity)
- phys_dotouch (self.groundentity);
- phys_setonground (self.groundentity, self.groundnormal, TRUE);
- touchtriggers (self);
- }
- else
- {
- print (sprintf("phys_move: timelength %g\n", input_timelength));
}
+
+ if (self.groundentity)
+ PM_DoTouch (self.groundentity);
+ PM_SetOnground (self.groundentity, self.groundnormal, TRUE);
+ touchtriggers (self);
+ self = oldself;
};

Return to the top of this page or return to the overview of this repo.

Diff qc/progs.src

diff --git a/qc/progs.src b/qc/progs.src
index b542459..988058b 100644
--- a/qc/progs.src
+++ b/qc/progs.src
@@ -1,7 +1,11 @@
-../progs.dat
+#pragma progs_dat "../progs.dat"
+
+#define FTE
+#pragma target fte
#pragma autoproto
+#define SSQC

-fteopts.qc
+#includelist
defs_constants.qc // compiler defines (fixed constant values)
defs_globalvars.qc // globalvars_t
defs_entvars.qc // entvars_t
@@ -34,7 +38,11 @@ keylock.qc // common code for entities unlockable with keys
doors.qc
buttons.qc
triggers.qc // added trigger_push_custom based on Hipnotic
+triggers_heal.qc // trigger_heal (was in dtmisc.qc) -- CEV
triggers_push.qc // wind/push brushes, jumppads -- CEV
+triggers_shake.qc // triggerable shake from Zer cutscenes; was dtquake.qc
+triggers_teleport.qc // was in triggers.qc -- CEV
+triggers_textstory.qc // textstory (was in misc.qc) -- CEV
plats.qc
misc.qc
lights.qc // c0burn's excellent switchable lights
@@ -75,8 +83,7 @@ doe_ltrail.qc // from DOE lightnin.qc
doe_plats.qc // Rogue MP newplats.qc

rubicon2.qc // selections from Rubicon2 QC
-dtquake.qc // triggerable earthquake from Zer cutscenes
func_bob.qc // RennyC's stand alone version based on AD
func_fall2.qc // Renny's improved version.
mobot.qc // Using "bot" creation code for func_monster_spawner
-
+#endlist

Return to the top of this page or return to the overview of this repo.

Diff qc/sv_runclient.qc

diff --git a/qc/sv_runclient.qc b/qc/sv_runclient.qc
index 4f33511..ef48409 100644
--- a/qc/sv_runclient.qc
+++ b/qc/sv_runclient.qc
@@ -1,7 +1,9 @@
-void(entity ent) phys_move;
+void(entity ent) PM_Move;

void() SV_RunClientCommand =
{
- //should match the one used by csqc.
- phys_move (self);
+ // should match the one used by csqc.
+ PM_Move (self);
+ // for testing -- CEV
+ // runstandardplayerphysics (self);
};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers.qc

diff --git a/qc/triggers.qc b/qc/triggers.qc
index 1413a00..fc10495 100644
--- a/qc/triggers.qc
+++ b/qc/triggers.qc
@@ -1,9 +1,8 @@
-/*==============================================================================
- TRIGGERS.QC
-==============================================================================*/
-
-// entity s;
+//==============================================================================
+// TRIGGERS.QC
+//==============================================================================

+// entity s;

void() trigger_reactivate =
{
@@ -322,477 +321,6 @@ void() trigger_counter =
/*
==============================================================================

-TELEPORT TRIGGERS with added functions from Zerstrorer and Qmaster
--- dumptruck_ds
-
-==============================================================================
-*/
-
-float PLAYER_ONLY = 1;
-float SILENT = 2;
-float RANDOM = 4;
-float TELE_STEALTH = 8;
-float MONSTER_ONLY = 16;
-float TELE_DD = 32;
-
-void() play_teleport =
-{
- local float v;
- local string tmpstr;
-
- v = random() * 5;
- if (v < 1)
- tmpstr = "misc/r_tele1.wav";
- else if (v < 2)
- tmpstr = "misc/r_tele2.wav";
- else if (v < 3)
- tmpstr = "misc/r_tele3.wav";
- else if (v < 4)
- tmpstr = "misc/r_tele4.wav";
- else
- tmpstr = "misc/r_tele5.wav";
-
- sound (self, CHAN_VOICE, tmpstr, 1, ATTN_NORM);
- remove (self);
-};
-
-void(vector org) spawn_tfog =
-{
- local entity s;
-
- s = spawn ();
- s.origin = org;
- s.spawnflags = self.spawnflags; //dumptruck_ds
- s.nextthink = time + 0.2;
- s.think = play_teleport;
-
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_TELEPORT);
- WriteCoord (MSG_BROADCAST, org_x);
- WriteCoord (MSG_BROADCAST, org_y);
- WriteCoord (MSG_BROADCAST, org_z);
-};
-
-
-void() tdeath_touch =
-{
- if (other == self.owner)
- return;
-
-// frag anyone who teleports in on top of an invincible player
- if (other.classname == "player")
- {
-// 1998-07-26 Pentagram telefrag fix by Zoid/Maddes start
- if (self.owner.classname != "player")
- { // other monsters explode themselves
- T_Damage (self.owner, self, self, 50000);
- return;
- }
-// 1998-07-26 Pentagram telefrag fix by Zoid/Maddes end
- if (other.invincible_finished > time)
-// 1998-07-26 Pentagram telefrag fix by Zoid/Maddes start
- { //player on spot has active pentagram
- if (self.owner.invincible_finished > time)
- { // teleported player has active pentagram too
- // can happen often in deathmatch 4
- // and levels with more than one pentagram
- self.classname = "teledeath3";
- other.invincible_finished = 0;
- T_Damage (other, self, self, 50000); // kill player on spot
-/* 1998-07-26 only telefrag player on spot by Maddes
- local entity other2;
- other2 = self.owner;
- self.owner = other;
- other2.invincible_finished = 0;
- T_Damage (other2, self, self, 50000); // kill teleported player
-*/
- }
- else // 1998-07-26 only telefrag player on spot by Maddes
- { // 1998-07-26 only telefrag player on spot by Maddes
-// 1998-07-26 Pentagram telefrag fix by Zoid/Maddes end
- self.classname = "teledeath2";
-// 1998-07-26 Pentagram telefrag fix by Zoid/Maddes start
- T_Damage (self.owner, self, self, 50000);
- } // 1998-07-26 only telefrag player on spot by Maddes
- return;
- }
-
-/*
- if (self.owner.classname != "player")
- { // other monsters explode themselves
- T_Damage (self.owner, self, self, 50000);
- return;
- }
-*/
-// 1998-07-26 Pentagram telefrag fix by Zoid/Maddes end
-
- }
-
- if (other.health)
- {
- T_Damage (other, self, self, 50000);
- }
-};
-
-
-void(vector org, entity death_owner) spawn_tdeath =
-{
-local entity death;
-
- death = spawn();
- death.classname = "teledeath";
- death.movetype = MOVETYPE_NONE;
- death.solid = SOLID_TRIGGER;
- death.angles = '0 0 0';
- setsize (death, death_owner.mins - '1 1 1', death_owner.maxs + '1 1 1');
- setorigin (death, org);
- death.touch = tdeath_touch;
- death.nextthink = time + 0.2;
- death.think = SUB_Remove;
- death.owner = death_owner;
-
- force_retouch = 2; // make sure even still objects get hit
-};
-
-/*-----------------------------------------------*/
-/*| more Zerstrorer-- dumptruck_ds |*/
-/*| teleport_randomspot - returns a random spot |*/
-/*| to teleport to among all of the |*/
-/*| "info_teleport_random" entities in the |*/
-/*| level. self.count is number of spots |*/
-/*-----------------------------------------------*/
-entity() teleport_randomspot =
-{
-local float rndm;
-// local float rndm, num1;
-local entity spot,first;
-
- rndm = rint(random() * (self.count - 1));
- spot = find(world, classname, "info_teleport_random");
- if(!spot)
- dprint("No random teleport points found!\n");
- first = spot;
-
- while (rndm > 0)
- {
- rndm = rndm - 1;
- spot = find(spot, classname, "info_teleport_random");
- }
-
- if (spot == world)
- {
- dprint("Random spot found world!!\n");
- spot = first;
- }
-
- return spot;
-};
-// end dumptruck_ds
-void() teleport_touch =
-{
-local entity t;
-local vector org;
-
- if (self.estate != STATE_ACTIVE) return;
-
- if (self.targetname != "")
- {
- if (self.nextthink < time)
- {
- return; // not fired yet
- }
- }
-
- if (self.spawnflags & PLAYER_ONLY)
- {
- if (other.classname != "player")
- return;
- }
-
- if (self.spawnflags & MONSTER_ONLY) // is this going to work? dumptruck_ds
- {
- if (other.classname == "player")
- return;
- }
-
- if (other.movetype == MOVETYPE_NOCLIP) // from Copper -- dumptruck_ds
- return;
-
- if (self.is_waiting == TRUE) // Supa, is this trigger waiting to be activated?
- return;
-
- if (self.is_waiting != -1) // Special case
- if (self.targetname != "")
- {
- if (self.nextthink < time)
- {
- return; // not fired yet
- }
- }
-
-// only teleport living creatures
- if (other.health <= 0 || other.solid != SOLID_SLIDEBOX)
- return;
-
- SUB_UseTargets ();
-
- // put a tfog where the player was
- // ### dhm - if stealth, don't spawn a fog
- if (!(self.spawnflags & TELE_STEALTH))
- spawn_tfog (other.origin);
-
- //dhm - if this is a random teleporter, pick a random spot!
- if (self.spawnflags & RANDOM)
- t = teleport_randomspot();
- else if ((self.spawnflags & TELE_DD) && other.classname == "player")
- t = find (world, targetname, self.noise);
- else
- t = find (world, targetname, self.target);
-
- if (!t)
- objerror ("couldn't find target");
-
-// // put a tfog where the player was
-// spawn_tfog (other.origin);
-//
-// t = find (world, targetname, self.target);
-// if (!t)
-// objerror ("couldn't find target");
-
-// spawn a tfog flash in front of the destination
- makevectors (t.mangle);
- org = t.origin + 32 * v_forward;
-
-// ### dhm - if stealth, don't spawn a fog
-if (!(self.spawnflags & TELE_STEALTH))
- spawn_tfog (org);
-
- spawn_tdeath(t.origin, other);
-
-// move the player and lock him down for a little while
- if (!other.health)
- {
- other.origin = t.origin;
- other.velocity = (v_forward * other.velocity_x) + (v_forward * other.velocity_y);
- return;
- }
-
- setorigin (other, t.origin);
- other.angles = t.mangle;
- if (other.classname == "player")
- {
- fog_setFromEnt(other, t); // retrieves fog values from teleport destination, if any
-
- other.fixangle = 1; // turn this way immediately
- other.teleport_time = time + 0.7;
- // TODO CEV
- // if (other.flags & FL_ONGROUND)
- // other.flags = other.flags - FL_ONGROUND;
- other.velocity = v_forward * PM_TELEEXITSPEED;
- }
- other.flags = other.flags - other.flags & FL_ONGROUND;
-
- if ((self.spawnflags & MONSTER_ONLY) && other.classname != "player")
- {
- other.fixangle = 1; // turn this way immediately
- other.teleport_time = time + 0.7;
- if (other.flags & FL_ONGROUND)
- other.flags = other.flags - FL_ONGROUND;
- other.velocity = v_forward * PM_TELEEXITSPEED;
- }
- other.flags = other.flags - other.flags & FL_ONGROUND;
-};
-
-// this is from Qmaster:
-
-// "I created an info_teleport_changedest
-// target = targetname of trigger_teleport to affect
-// message = targetname of new info_teleport_destination (or whatever entity
-// really) to now teleport to
-
-// So that I can automatically update the teleporter under my coagula map as you
-// progress rather than have a bunch of triggers that I need to killtarget.
-// Falling is not fatal then, but it does put you back some. Works as a sorta
-// checkpoint system but also builds on my older idea for saving time in coop
-// implemented in my Terracity map eons ago.
-
-// looking at vanilla, you would only need to change trig.target to match
-// self.message if you were to add this.""
-
-void() teleport_destchange =
-{
- local entity trig;
-
- trig = find(world,targetname,self.target);
- if (!trig || trig.classname != "trigger_teleport") {
- dprint("\b[TELEPORT_DESTCHANGE]\b Cannot find trigger_teleport\n");
- return;
- }
-
- trig.goalentity = find (world, targetname, self.message);
- if (!trig.goalentity) {
- dprint("\b[TELEPORT_DESTCHANGE]\b Cannot find teleport destination\n");
- return;
- }
-
- makevectors (trig.goalentity.mangle);
- trig.goalentity.movedir = v_forward;
- trig.goalentity.pos1 = trig.goalentity.origin + 32 * trig.goalentity.movedir;
-
- trig.target = self.message; //dumptruck_ds see comment above
-};
-
-/*QUAKED info_teleport_changedest (0 0.5 0) (-4 -4 -4) (4 4 4) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-Allows a mapper to change the target of a teleport_trigger. Useful in maps where
-the player may fall into a void and the mapper wants to update where they "respawn"
-as they progress through the level. Could also be used for teleport puzzles and more.
-target = trigger_teleport to change
-message = new info_teleport_destination's targetname to switch to
-targetname = name of this entity so we can use it
-*/
-void() info_teleport_changedest =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.use = teleport_destchange;
- if (self.targetname == "") {
- dprint("\b[ERROR]\b info_teleport_changedest with no targetname");
- remove(self);
- }
-
- if (self.target == "") {
- dprint("\b[ERROR]\b info_teleport_changedest with no target");
- remove(self);
- }
-
- if (self.message == "") {
- dprint("\b[ERROR]\b info_teleport_changedest with no message set for new destination");
- remove(self);
- }
-};
-
-/*QUAKED info_teleport_destination (.5 .5 .5) (-8 -8 -8) (8 8 32) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-{
-model ("progs/player.mdl");
-}
-This is the destination marker for a teleporter. It should have a "targetname" field with the same value as a teleporter's "target" field.
-*/
-void() info_teleport_destination =
-{
- vector end;
-
- // new spawnflags for all entities -- iw
- if (SUB_Inhibit ())
- return;
-
- // this does nothing, just serves as a target spot
- self.mangle = self.angles;
- self.angles = '0 0 0';
- self.model = "";
- // drop teleporter exit to the floor if within 64 units -- CEV
- end = self.origin + PM_TELEDROP;
- tracebox(self.origin, self.mins, self.maxs, end, FALSE, self);
- if (trace_allsolid || trace_startsolid || trace_fraction < 1)
- {
- droptofloor ();
- // bump origin up so the player won't exit into the floor
- self.origin = self.origin + '0 0 24';
- }
- else
- // instead apply the standard fixed Z offset
- self.origin = self.origin + '0 0 27';
-
- if (!self.targetname)
- if (self.target)
- // quake 3 compat -- CEV
- self.targetname = self.target;
- else
- objerror ("no targetname");
-};
-
-// quake 3 compat -- CEV
-void() misc_teleporter_dest =
-{
- info_teleport_destination();
-};
-
-void() misc_teleporter_destination =
-{
- info_teleport_destination();
-};
-
-void() target_teleporter =
-{
- info_teleport_destination();
-};
-
-/*QUAKED info_teleport_random (.5 .5 .5) (-8 -8 -8) (8 8 32) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-{
-model ("progs/player.mdl");
-}
-This is a random destination marker for a teleporter.
-*/
-void() info_teleport_random =
-{
-// this does nothing, just serves as a target spot
- self.mangle = self.angles;
- self.angles = '0 0 0';
- self.model = "";
- self.origin = self.origin + '0 0 27';
-};
-
-void() teleport_use =
-{
- self.nextthink = time + 0.2;
- force_retouch = 2; // make sure even still objects get hit
- self.think = SUB_Null;
-};
-
-// -------------------------
-/*QUAKED trigger_teleport (.5 .5 .5) ? PLAYER_ONLY SILENT RANDOM STEALTH X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-
-Any object touching this will be transported to the corresponding
-info_teleport_destination entity. You must set the "target" field,
-and create an object with a "targetname" field that matches.
-
-If the trigger_teleport has a targetname, it will only teleport entities
-when it has been fired.
-
-SILENT(2) eliminates the teleporter ambient noise (good for hidden monster teleporters.
-RANDOM(4) causes the teleporter to send the player to a random destination
- among the info_teleport_random markers in the level. You MUST place a
- "count" field that is the number of info_teleport_random entities you
- placed.
-STEALTH(8) eliminates the particle flash and noise when an entity is teleported.
-MONSTER_ONLY(16) will only teleport monsters
-*/void() trigger_teleport =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- local vector o;
-
- InitTrigger ();
- self.touch = teleport_touch;
- // find the destination
- if (!self.target)
- objerror ("no target");
- self.use = teleport_use;
-
- if (!(self.spawnflags & SILENT))
- {
- precache_sound ("ambience/hum1.wav");
- o = (self.mins + self.maxs)*0.5;
- ambientsound (o, "ambience/hum1.wav",0.5 , ATTN_STATIC);
- }
-
- SUB_CheckWaiting();
-};
-
-/*
-==============================================================================
-
trigger_setskill

==============================================================================

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers_heal.qc

diff --git a/qc/triggers_heal.qc b/qc/triggers_heal.qc
new file mode 100644
index 0000000..8bac914
--- /dev/null
+++ b/qc/triggers_heal.qc
@@ -0,0 +1,179 @@
+//==============================================================================
+// HEAL TRIGGER
+//==============================================================================
+
+// from custents, modified by dumptruck_ds
+// Original entity submitted by Jan Martin Mathiassen, aka. TGR
+
+// was in dtmisc.qc -- CEV
+
+//----------------------------------------------------------------------
+void() heal_think =
+{
+ if (self.cnt == self.count)
+ {
+ dprint ("trigger_heal think: full\n");
+ self.think = SUB_Null;
+ return;
+ }
+
+ local float recharge_amount = self.speed;
+
+ if (self.count < (self.cnt + self.speed))
+ recharge_amount = self.count - self.cnt;
+
+ dprint ("trigger_heal think: [max: ");
+ dprint (ftos(self.count));
+ dprint (", current: ");
+ dprint (ftos(self.cnt));
+ dprint (", recharging: ");
+ dprint (ftos(recharge_amount));
+ dprint ("]\n");
+
+ self.cnt = self.cnt + recharge_amount;
+ self.nextthink = time + self.delay;
+};
+
+//----------------------------------------------------------------------
+void() heal_touch =
+{
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ // from Copper -- dumptruck_ds
+ if (other.movetype == MOVETYPE_NOCLIP)
+ return;
+ if (self.spawnflags & HEAL_PLAYER_ONLY && other.classname != "player")
+ return;
+ if (self.spawnflags & HEAL_MONSTER_ONLY && !(other.flags & FL_MONSTER))
+ return;
+ if (other.classname != "player" && !(other.flags & FL_MONSTER))
+ return;
+ if (other.heal_timer > time)
+ return;
+
+ if (self.count && self.cnt <= 0)
+ {
+ if (self.message2)
+ centerprint (other, self.message2);
+ return;
+ }
+
+ if ((other.takedamage) && (other.health < self.health_max))
+ {
+ if (self.noise != "")
+ sound (self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
+ else
+ sound (self, CHAN_AUTO, "items/r_item1.wav", 1,
+ ATTN_NORM);
+
+ local float calculated_healing;
+
+ if ((other.health + self.heal_amount) > self.health_max)
+ calculated_healing = self.health_max - other.health;
+ else
+ calculated_healing = self.heal_amount;
+
+ if (self.count)
+ {
+ if (calculated_healing > self.cnt)
+ calculated_healing = self.cnt;
+
+ self.cnt = self.cnt - calculated_healing;
+
+ if (self.delay)
+ {
+ self.think = heal_think;
+ self.nextthink = time + self.delay;
+ }
+
+ dprint ("trigger_heal used: [max: ");
+ dprint (ftos(self.count));
+ dprint (", current: ");
+ dprint (ftos(self.cnt));
+ dprint (", using: ");
+ dprint (ftos(calculated_healing));
+ dprint ("]\n");
+ }
+
+ if (self.message)
+ centerprint (other, self.message);
+
+ T_Heal (other, calculated_healing, 1);
+ other.heal_timer = time + self.wait;
+ }
+};
+
+//----------------------------------------------------------------------
+void() heal_toggle =
+{
+ if (self.touch == SUB_Null)
+ self.touch = heal_touch;
+ else
+ self.touch = SUB_Null;
+};
+
+/*QUAKED trigger_heal (.5 .5 .5) ? HEAL_START_ON HEAL_PLAYER_ONLY HEAL_MONSTER_ONLY X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+
+Any object touching this will be healed
+heal_amount -- the amount to heal each time (default 5)
+wait -- the time between each healing (default 1)
+health_max -- the upper limit for the healing (default 100, max 250)
+sounds -- set to 1 to enable the noise1 field for custom healing sound
+noise -- path to custom sound file
+message -- message to print on heal
+count -- maximum heal before exhausted
+speed -- amount to recharge at a time
+delay -- time before recharging
+message2 -- message to print when exhausted
+*/
+void() trigger_heal =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit ())
+ return;
+
+ // play custom sound for healing if noise key exists
+ precache_sound ("items/r_item1.wav");
+ if (self.noise != "")
+ precache_sound (self.noise);
+
+ InitTrigger ();
+
+ if (self.wait == 0)
+ self.wait = 1;
+
+ if (self.heal_amount == 0)
+ self.heal_amount = 5;
+
+ if (self.health_max == 0)
+ self.health_max = 100;
+ else if (self.health_max > 250)
+ self.health_max = 250;
+
+ if (self.count)
+ {
+ self.cnt = self.count;
+
+ if (self.speed && !self.delay)
+ self.delay = 10;
+ else if (!self.speed && self.delay)
+ self.speed = 5;
+ }
+
+ /*
+ if (self.targetname)
+ {
+ self.use = heal_toggle;
+ if (self.spawnflags & HEAL_START_ON)
+ self.touch = heal_touch;
+ else
+ self.touch = SUB_Null;
+ }
+ else
+ */
+
+ self.touch = heal_touch;
+
+ SUB_CheckWaiting ();
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers_push.qc

diff --git a/qc/triggers_push.qc b/qc/triggers_push.qc
index 975fcd8..0cc7617 100644
--- a/qc/triggers_push.qc
+++ b/qc/triggers_push.qc
@@ -1,10 +1,6 @@
-/*==============================================================================
- TRIGGER_PUSH.QC
-==============================================================================*/
-
-//======================================================================
-// trigger_push
-//----------------------------------------------------------------------
+//==============================================================================
+// TRIGGER PUSH
+//==============================================================================

////////////////////////////////////////////////////////////////////////
// start dumptruck_ds additions ////////////////////////////////////////
@@ -19,9 +15,13 @@ float DT_NOISE = 32; // use custom sound via noise key/value
// start code CEV copied from Nexuiz ///////////////////////////////////
////////////////////////////////////////////////////////////////////////

+//======================================================================
+// solve_quadratic
+//
// from Nexuiz source code; copied from
// https://github.com/smlinux/nexuiz/blob/master/data/qcsrc/common/util.qc
// ax^2 + bx + c = 0
+//----------------------------------------------------------------------
vector(float a, float b, float c) solve_quadratic =
{
vector v;
@@ -77,23 +77,24 @@ vector(float a, float b, float c) solve_quadratic =
return v;
}

-/*
- trigger_push_calculatevelocity
-
- Arguments:
- org - origin of the object which is to be pushed
- tgt - target entity (can be either a point or a model entity; if it
- is the latter, its midpoint is used)
- ht - jump height, measured from the higher one of org and tgt's
- midpoint
-
- Returns: velocity for the jump
- the global trigger_push_calculatevelocity_flighttime is set to the
- total jump time
- */

+//======================================================================
+// trigger_push_calculatevelocity
+//
+// Arguments:
+// org - origin of the object which is to be pushed
+// tgt - target entity (can be either a point or a model entity; if it
+// is the latter, its midpoint is used)
+// ht - jump height, measured from the higher one of org and tgt's
+// midpoint
+//
+// Returns: velocity for the jump
+// the global trigger_push_calculatevelocity_flighttime is set to the
+// total jump time
+//
// from Nexuiz source code; copied from
// https://github.com/smlinux/nexuiz/blob/master/data/qcsrc/server/t_jumppads.qc
+//----------------------------------------------------------------------
vector(vector org, entity tgt, float ht) trigger_push_calculatevelocity =
{
local float grav, sdist, zdist, vs, vz, jumpheight;
@@ -200,6 +201,7 @@ vector(vector org, entity tgt, float ht) trigger_push_calculatevelocity =
return sdir * vs + '0 0 1' * vz;
};

+//----------------------------------------------------------------------
void() trigger_push_findtarget =
{
self.enemy = find (world, targetname, self.target);
@@ -217,6 +219,7 @@ void() trigger_push_findtarget =
// end code CEV copied from Nexuiz /////////////////////////////////////
////////////////////////////////////////////////////////////////////////

+//----------------------------------------------------------------------
void() trigger_push_touch =
{
if (self.estate != STATE_ACTIVE)
@@ -263,6 +266,7 @@ void() trigger_push_touch =
if (!(self.spawnflags & DT_SILENT))
{
if (other.fly_sound < time)
+ {
if (!(self.spawnflags & DT_NOISE))
{
other.fly_sound = time + 1.5;
@@ -277,6 +281,7 @@ void() trigger_push_touch =
self.noise,
1, ATTN_NORM);
}
+ }
}
}
}
@@ -321,7 +326,9 @@ void() trigger_push =
SUB_CheckWaiting ();
};

+//======================================================================
// dumptruck_ds was based on hipnotic blocker_use now Alklaine estate
+//----------------------------------------------------------------------
void() push_toggle =
{
if (self.estate != STATE_ACTIVE)
@@ -356,14 +363,10 @@ void() trigger_push_custom =
self.touch = trigger_push_touch;

if (self.spawnflags & DT_STARTOFF)
- {
self.estate = STATE_INACTIVE;
- }

if (self.noise != "")
- {
precache_sound(self.noise);
- }

if (!self.speed)
self.speed = 1000;
@@ -371,7 +374,9 @@ void() trigger_push_custom =
SUB_CheckWaiting ();
};

+//======================================================================
// push target entities for Quake 3 compatibility -- CEV
+//----------------------------------------------------------------------
void() target_push =
{
// new spawnflags for all entities -- iw
@@ -386,6 +391,7 @@ void() target_push =
objerror ("no targetname");
};

+//----------------------------------------------------------------------
void() target_position =
{
target_push ();
@@ -394,7 +400,6 @@ void() target_position =
//======================================================================
// monsterjump
//----------------------------------------------------------------------
-
void() trigger_monsterjump_touch =
{
if (self.estate != STATE_ACTIVE)
@@ -455,4 +460,3 @@ void() trigger_monsterjump =
////////////////////////////////////////////////////////////////////////
// end dumptruck_ds additions //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers_shake.qc

diff --git a/qc/triggers_shake.qc b/qc/triggers_shake.qc
new file mode 100644
index 0000000..b6b1675
--- /dev/null
+++ b/qc/triggers_shake.qc
@@ -0,0 +1,122 @@
+//==============================================================================
+// TRIGGER_SHAKE
+//==============================================================================
+
+// this is a point entity from Rubicon Rumble Pack Devkit
+// REQUIRES A TARGETNAME
+
+// constants
+float VIEWONLY = 1;
+
+//----------------------------------------------------------------------
+void() shake_think =
+{
+ if (self.attack_finished < time)
+ {
+ // Done
+ self.nextthink = -1;
+
+ if (self.noise1 != "")
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+
+ return;
+ }
+
+ // Shake all players in the effect radius...
+
+ local entity plyr;
+ plyr = findradius (self.origin, self.count);
+
+ while (plyr)
+ {
+ if (plyr.flags & FL_CLIENT)
+ {
+ local float d;
+
+ // Scale effect by distance
+ d = vlen (self.origin - plyr.origin);
+ d = (self.count - d) / self.count;
+
+ if (d > 0)
+ {
+ // shake up the view
+ plyr.punchangle_x = -1 *
+ (random() + (0.025 * self.dmg * d));
+
+ // push the player around
+ if (plyr.flags & FL_ONGROUND
+ && !(self.spawnflags & VIEWONLY))
+ {
+ d = self.dmg * d;
+ plyr.velocity_x = plyr.velocity_x +
+ (random() * d * 2 - d);
+ plyr.velocity_y = plyr.velocity_y +
+ (random() * d * 2 - d);
+ // always push up
+ plyr.velocity_z = plyr.velocity_z +
+ (random() * d);
+ }
+ }
+ }
+ plyr = plyr.chain;
+ }
+
+ // keep going
+ self.nextthink = time + 0.1;
+};
+
+//----------------------------------------------------------------------
+void() shake_use =
+{
+ // already active
+ if (self.attack_finished > time)
+ return;
+
+ // Start...
+ if (self.noise != "")
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+
+ self.attack_finished = time + self.wait;
+ self.nextthink = time + 0.1;
+};
+
+/*QUAKED trigger_shake (.5 0 .5) (-8 -8 -8) (8 8 8) VIEWONLY X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+
+Earthquake trigger - shakes players in it's radius when active.
+Strength of tremor is greatest at the centre.
+dmg Strength at center (default is 120)
+wait Duration of shake (default is 1)
+count Affect radius (defalt is 200)
+noise Noise to play when starting to shake
+noise1 Noise to play when stopping
+targetname Must be triggered
+Spawnflags
+VIEWONL Shakes the view, but player movement is not affected
+*/
+void() trigger_shake =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit ())
+ return;
+
+ if (!self.targetname)
+ objerror("trigger_shake without name");
+
+ if (self.noise != "")
+ precache_sound (self.noise);
+ if (self.noise1 != "")
+ precache_sound (self.noise1);
+
+ if (!self.dmg)
+ self.dmg = 120;
+ if (self.count <= 0)
+ self.count = 200;
+ if (self.wait <= 0)
+ self.wait = 1.0;
+
+ setorigin (self, self.origin);
+
+ self.nextthink = -1;
+ self.think = shake_think;
+ self.use = shake_use;
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers_teleport.qc

diff --git a/qc/triggers_teleport.qc b/qc/triggers_teleport.qc
new file mode 100644
index 0000000..f55704a
--- /dev/null
+++ b/qc/triggers_teleport.qc
@@ -0,0 +1,516 @@
+//==============================================================================
+// TRIGGER_TELEPORT
+//==============================================================================
+
+// TELEPORT TRIGGERS with added functions from Zerstrorer and Qmaster
+// -- dumptruck_ds
+
+// constants
+float PLAYER_ONLY = 1;
+float SILENT = 2;
+float RANDOM = 4;
+float TELE_STEALTH = 8;
+float MONSTER_ONLY = 16;
+float TELE_DD = 32;
+
+//----------------------------------------------------------------------
+void() play_teleport =
+{
+ local float v;
+ local string tmpstr;
+
+ v = random () * 5;
+ if (v < 1)
+ tmpstr = "misc/r_tele1.wav";
+ else if (v < 2)
+ tmpstr = "misc/r_tele2.wav";
+ else if (v < 3)
+ tmpstr = "misc/r_tele3.wav";
+ else if (v < 4)
+ tmpstr = "misc/r_tele4.wav";
+ else
+ tmpstr = "misc/r_tele5.wav";
+
+ sound (self, CHAN_VOICE, tmpstr, 1, ATTN_NORM);
+ remove (self);
+};
+
+//----------------------------------------------------------------------
+void(vector org) spawn_tfog =
+{
+ local entity s;
+
+ s = spawn ();
+ s.origin = org;
+ s.spawnflags = self.spawnflags; // dumptruck_ds
+ s.nextthink = time + 0.2;
+ s.think = play_teleport;
+
+ WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
+ WriteByte (MSG_BROADCAST, TE_TELEPORT);
+ WriteCoord (MSG_BROADCAST, org_x);
+ WriteCoord (MSG_BROADCAST, org_y);
+ WriteCoord (MSG_BROADCAST, org_z);
+};
+
+//----------------------------------------------------------------------
+void() tdeath_touch =
+{
+ if (other == self.owner)
+ return;
+
+ // frag anyone who teleports in on top of an invincible player
+ if (other.classname == "player")
+ {
+ // 1998-07-26 Pentagram telefrag fix by Zoid/Maddes start
+ if (self.owner.classname != "player")
+ {
+ // other monsters explode themselves
+ T_Damage (self.owner, self, self, 50000);
+ return;
+ }
+ // 1998-07-26 Pentagram telefrag fix by Zoid/Maddes end
+
+ // 1998-07-26 Pentagram telefrag fix by Zoid/Maddes start
+ if (other.invincible_finished > time)
+ {
+ // player on spot has active pentagram
+ if (self.owner.invincible_finished > time)
+ {
+ // teleported player has active pentagram too
+ // can happen often in deathmatch 4
+ // and levels with more than one pentagram
+ self.classname = "teledeath3";
+ other.invincible_finished = 0;
+ // kill player on spot
+ T_Damage (other, self, self, 50000);
+
+ /*
+ // 1998-07-26 only telefrag player on spot
+ // by Maddes
+ local entity other2;
+ other2 = self.owner;
+ self.owner = other;
+ other2.invincible_finished = 0;
+ // kill teleported player
+ T_Damage (other2, self, self, 50000);
+ */
+ }
+ else
+ {
+ // 1998-07-26 Pentagram telefrag fix by
+ // Zoid/Maddes end
+ self.classname = "teledeath2";
+ // 1998-07-26 Pentagram telefrag fix by
+ // Zoid/Maddes start
+ T_Damage (self.owner, self, self, 50000);
+ }
+ return;
+ }
+
+ /*
+ if (self.owner.classname != "player")
+ { // other monsters explode themselves
+ T_Damage (self.owner, self, self, 50000);
+ return;
+ }
+ */
+ // 1998-07-26 Pentagram telefrag fix by Zoid/Maddes end
+ }
+
+ if (other.health)
+ T_Damage (other, self, self, 50000);
+};
+
+//----------------------------------------------------------------------
+void(vector org, entity death_owner) spawn_tdeath =
+{
+ local entity death;
+
+ death = spawn ();
+ death.classname = "teledeath";
+ death.movetype = MOVETYPE_NONE;
+ death.solid = SOLID_TRIGGER;
+ death.angles = '0 0 0';
+ setsize (death, death_owner.mins - '1 1 1', death_owner.maxs + '1 1 1');
+ setorigin (death, org);
+ death.touch = tdeath_touch;
+ death.nextthink = time + 0.2;
+ death.think = SUB_Remove;
+ death.owner = death_owner;
+
+ // make sure even still objects get hit
+ force_retouch = 2;
+};
+
+//======================================================================
+// teleport_randomspot
+//
+// more Zerstrorer -- dumptruck_ds
+// teleport_randomspot - returns a random spot to teleport to among all
+// of the "info_teleport_random" entities in the level. self.count is
+// the number of spots
+//----------------------------------------------------------------------
+entity() teleport_randomspot =
+{
+ local float rndm;
+ // local float rndm, num1;
+ local entity spot,first;
+
+ rndm = rint (random() * (self.count - 1));
+ spot = find (world, classname, "info_teleport_random");
+ if (!spot)
+ dprint ("No random teleport points found!\n");
+ first = spot;
+
+ while (rndm > 0)
+ {
+ rndm = rndm - 1;
+ spot = find (spot, classname, "info_teleport_random");
+ }
+
+ if (spot == world)
+ {
+ dprint ("Random spot found world!!\n");
+ spot = first;
+ }
+
+ return spot;
+};
+// end dumptruck_ds
+
+//----------------------------------------------------------------------
+void() teleport_touch =
+{
+ local entity t;
+ local vector org;
+
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ if (self.targetname != "")
+ if (self.nextthink < time)
+ // not fired yet
+ return;
+
+ if (self.spawnflags & PLAYER_ONLY)
+ if (other.classname != "player")
+ return;
+
+ // is this going to work? dumptruck_ds
+ if (self.spawnflags & MONSTER_ONLY)
+ if (other.classname == "player")
+ return;
+
+ // from Copper -- dumptruck_ds
+ if (other.movetype == MOVETYPE_NOCLIP)
+ return;
+
+ // Supa, is this trigger waiting to be activated?
+ if (self.is_waiting == TRUE)
+ return;
+
+ // Special case
+ if (self.is_waiting != -1)
+ if (self.targetname != "")
+ if (self.nextthink < time)
+ // not fired yet
+ return;
+
+ // only teleport living creatures
+ if (other.health <= 0 || other.solid != SOLID_SLIDEBOX)
+ return;
+
+ SUB_UseTargets ();
+
+ // put a tfog where the player was
+ // ### dhm - if stealth, don't spawn a fog
+ if (!(self.spawnflags & TELE_STEALTH))
+ spawn_tfog (other.origin);
+
+ // dhm - if this is a random teleporter, pick a random spot!
+ if (self.spawnflags & RANDOM)
+ t = teleport_randomspot ();
+ else if ((self.spawnflags & TELE_DD) && other.classname == "player")
+ t = find (world, targetname, self.noise);
+ else
+ t = find (world, targetname, self.target);
+
+ if (!t)
+ objerror ("couldn't find target");
+
+ // put a tfog where the player was
+ /*
+ spawn_tfog (other.origin);
+
+ t = find (world, targetname, self.target);
+ if (!t)
+ objerror ("couldn't find target");
+ */
+
+ // spawn a tfog flash in front of the destination
+ makevectors (t.mangle);
+ org = t.origin + 32 * v_forward;
+
+ // ### dhm - if stealth, don't spawn a fog
+ if (!(self.spawnflags & TELE_STEALTH))
+ spawn_tfog (org);
+
+ spawn_tdeath (t.origin, other);
+
+ // move the player and lock him down for a little while
+ if (!other.health)
+ {
+ other.origin = t.origin;
+ other.velocity = (v_forward * other.velocity_x) +
+ (v_forward * other.velocity_y);
+ return;
+ }
+
+ setorigin (other, t.origin);
+ other.angles = t.mangle;
+
+ if (other.classname == "player")
+ {
+ // retrieves fog values from teleport destination, if any
+ fog_setFromEnt (other, t);
+
+ // turn this way immediately
+ other.fixangle = 1;
+ other.teleport_time = time + 0.7;
+ // TODO CEV
+ /*
+ if (other.flags & FL_ONGROUND)
+ other.flags = other.flags - FL_ONGROUND;
+ */
+ other.velocity = v_forward * PM_TELEEXITSPEED;
+ }
+ other.flags = other.flags - other.flags & FL_ONGROUND;
+
+ if ((self.spawnflags & MONSTER_ONLY) && other.classname != "player")
+ {
+ // turn this way immediately
+ other.fixangle = 1;
+ other.teleport_time = time + 0.7;
+ if (other.flags & FL_ONGROUND)
+ other.flags = other.flags - FL_ONGROUND;
+ other.velocity = v_forward * PM_TELEEXITSPEED;
+ }
+ other.flags = other.flags - other.flags & FL_ONGROUND;
+};
+
+// this is from Qmaster:
+
+// "I created an info_teleport_changedest
+// target = targetname of trigger_teleport to affect
+// message = targetname of new info_teleport_destination (or whatever entity
+// really) to now teleport to
+
+// So that I can automatically update the teleporter under my coagula map as you
+// progress rather than have a bunch of triggers that I need to killtarget.
+// Falling is not fatal then, but it does put you back some. Works as a sorta
+// checkpoint system but also builds on my older idea for saving time in coop
+// implemented in my Terracity map eons ago.
+
+// looking at vanilla, you would only need to change trig.target to match
+// self.message if you were to add this."
+
+//----------------------------------------------------------------------
+void() teleport_destchange =
+{
+ local entity trig;
+
+ trig = find(world,targetname,self.target);
+ if (!trig || trig.classname != "trigger_teleport")
+ {
+ dprint ("\b[TELEPORT_DESTCHANGE]\b ");
+ dprint ("Cannot find trigger_teleport\n");
+ return;
+ }
+
+ trig.goalentity = find (world, targetname, self.message);
+ if (!trig.goalentity)
+ {
+ dprint ("\b[TELEPORT_DESTCHANGE]\b ");
+ dprint ("Cannot find teleport destination\n");
+ return;
+ }
+
+ makevectors (trig.goalentity.mangle);
+ trig.goalentity.movedir = v_forward;
+ trig.goalentity.pos1 = trig.goalentity.origin + 32 *
+ trig.goalentity.movedir;
+
+ // dumptruck_ds see comment above
+ trig.target = self.message;
+};
+
+/*QUAKED info_teleport_changedest (0 0.5 0) (-4 -4 -4) (4 4 4) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+Allows a mapper to change the target of a teleport_trigger. Useful in maps where
+the player may fall into a void and the mapper wants to update where they "respawn"
+as they progress through the level. Could also be used for teleport puzzles and more.
+target = trigger_teleport to change
+message = new info_teleport_destination's targetname to switch to
+targetname = name of this entity so we can use it
+*/
+void() info_teleport_changedest =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit ())
+ return;
+
+ self.use = teleport_destchange;
+ if (self.targetname == "")
+ {
+ dprint ("\b[ERROR]\b info_teleport_changedest ");
+ dprint ("with no targetname\n");
+ remove (self);
+ }
+
+ if (self.target == "")
+ {
+ dprint ("\b[ERROR]\b info_teleport_changedest ");
+ dprint ("with no target\n");
+ remove(self);
+ }
+
+ if (self.message == "")
+ {
+ dprint ("\b[ERROR]\b info_teleport_changedest ");
+ dprint ("with no message set for new destination\n");
+ remove (self);
+ }
+};
+
+/*QUAKED info_teleport_destination (.5 .5 .5) (-8 -8 -8) (8 8 32) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+{
+model ("progs/player.mdl");
+}
+This is the destination marker for a teleporter. It should have a "targetname"
+field with the same value as a teleporter's "target" field.
+*/
+void() info_teleport_destination =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit ())
+ return;
+
+ local vector end;
+
+ // this does nothing, just serves as a target spot
+ self.mangle = self.angles;
+ self.angles = '0 0 0';
+ self.model = "";
+
+ // drop teleporter exit to the floor if it's PM_TELEDROP units
+ // away -- CEV
+ end = self.origin + PM_TELEDROP;
+ tracebox (self.origin, self.mins, self.maxs, end, FALSE, self);
+ if (trace_allsolid || trace_startsolid || trace_fraction < 1)
+ {
+ droptofloor ();
+ // bump origin up so player won't exit into the floor -- CEV
+ // This was '0 0 24' but that was causing issues -- CEV
+ self.origin = self.origin + '0 0 27';
+ }
+ else
+ {
+ // instead apply the standard fixed Z offset -- CEV
+ self.origin = self.origin + '0 0 27';
+ }
+
+ if (!self.targetname)
+ if (self.target)
+ // quake 3 compat -- CEV
+ self.targetname = self.target;
+ else
+ objerror ("no targetname");
+};
+
+//======================================================================
+// Quake 3 compat (I think) -- CEV
+//----------------------------------------------------------------------
+void() misc_teleporter_dest =
+{
+ info_teleport_destination ();
+};
+
+//----------------------------------------------------------------------
+void() misc_teleporter_destination =
+{
+ info_teleport_destination ();
+};
+
+//----------------------------------------------------------------------
+void() target_teleporter =
+{
+ info_teleport_destination ();
+};
+
+/*QUAKED info_teleport_random (.5 .5 .5) (-8 -8 -8) (8 8 32) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+{
+model ("progs/player.mdl");
+}
+This is a random destination marker for a teleporter.
+*/
+void() info_teleport_random =
+{
+ // this does nothing, just serves as a target spot
+ self.mangle = self.angles;
+ self.angles = '0 0 0';
+ self.model = "";
+ self.origin = self.origin + '0 0 27';
+};
+
+//----------------------------------------------------------------------
+void() teleport_use =
+{
+ self.nextthink = time + 0.2;
+ // make sure even still objects get hit
+ force_retouch = 2;
+ self.think = SUB_Null;
+};
+
+/*QUAKED trigger_teleport (.5 .5 .5) ? PLAYER_ONLY SILENT RANDOM STEALTH X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+
+Any object touching this will be transported to the corresponding
+info_teleport_destination entity. You must set the "target" field,
+and create an object with a "targetname" field that matches.
+
+If the trigger_teleport has a targetname, it will only teleport entities
+when it has been fired.
+
+SILENT(2) eliminates the teleporter ambient noise (good for hidden monster teleporters.
+RANDOM(4) causes the teleporter to send the player to a random destination
+ among the info_teleport_random markers in the level. You MUST place a
+ "count" field that is the number of info_teleport_random entities you
+ placed.
+STEALTH(8) eliminates the particle flash and noise when an entity is teleported.
+MONSTER_ONLY(16) will only teleport monsters
+*/
+void() trigger_teleport =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit ())
+ return;
+
+ local vector o;
+
+ InitTrigger ();
+ self.touch = teleport_touch;
+
+ // find the destination
+ if (!self.target)
+ objerror ("no target");
+
+ self.use = teleport_use;
+
+ if (!(self.spawnflags & SILENT))
+ {
+ precache_sound ("ambience/hum1.wav");
+ o = (self.mins + self.maxs) * 0.5;
+ ambientsound (o, "ambience/hum1.wav", 0.5, ATTN_STATIC);
+ }
+
+ SUB_CheckWaiting ();
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers_textstory.qc

diff --git a/qc/triggers_textstory.qc b/qc/triggers_textstory.qc
new file mode 100644
index 0000000..7d62443
--- /dev/null
+++ b/qc/triggers_textstory.qc
@@ -0,0 +1,225 @@
+//==============================================================================
+// TRIGGER_TEXTSTORY
+//==============================================================================
+
+// constants
+float TEXTSTORY_SILENT = 1;
+float TEXTSTORY_NOFADE = 2;
+
+//----------------------------------------------------------------------
+void(entity controller) textstory_hide =
+{
+ if (!self.enemy || !(self.enemy.flags & FL_CLIENT))
+ return;
+
+ self.enemy.suppressCenterPrint = FALSE;
+ centerprint (self.enemy, "");
+
+ if (controller.noise2)
+ sound (self.enemy, CHAN_BODY, controller.noise2, 1, ATTN_NORM);
+
+ if (!(controller.spawnflags & TEXTSTORY_NOFADE))
+ csf_fade (self.enemy, 0, '0 0 0', 0.5);
+
+};
+
+//----------------------------------------------------------------------
+void(entity controller) textstory_show =
+{
+ if (!self.enemy || !(self.enemy.flags & FL_CLIENT))
+ return;
+
+ self.enemy.suppressCenterPrint = TRUE;
+
+ centerprint_builtin (self.enemy, controller.message);
+
+ if (!self.state)
+ {
+ if (controller.noise1)
+ {
+ sound (self.enemy, CHAN_BODY, controller.noise1,
+ 1, ATTN_NORM);
+ }
+
+ if (!(controller.spawnflags & TEXTSTORY_NOFADE))
+ {
+ //custom fade amount --dumptruck_ds
+ if (!self.fade_amt)
+ csf_fade (self.enemy, 160, '0 0 0', 1);
+ else
+ csf_fade (self.enemy, self.fade_amt,
+ '0 0 0', 1);
+ }
+ }
+
+ self.state = 1;
+};
+
+//----------------------------------------------------------------------
+void() trigger_textstory_hide =
+{
+ textstory_hide (self);
+
+ self.enemy = world;
+ self.state = 0;
+};
+
+//----------------------------------------------------------------------
+void() trigger_textstory_show =
+{
+ textstory_show (self);
+
+ self.think = trigger_textstory_hide;
+ self.nextthink = time + 0.2;
+
+};
+
+//----------------------------------------------------------------------
+void() trigger_textstory_touch =
+{
+
+ if (!(other.flags & FL_CLIENT))
+ return;
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ // don't show message if another player is already triggering it
+ if (other != self.enemy && self.state == 1)
+ return;
+
+ if (self.mangle &&
+ !isInAngle (other.v_angle, self.mangle, self.view_ofs))
+ return;
+
+ if (self.attack_finished < time)
+ {
+
+ self.attack_finished = time + 0.1;
+ self.enemy = other;
+
+ trigger_textstory_show ();
+ }
+};
+
+//----------------------------------------------------------------------
+void() trigger_textstory =
+{
+ InitTrigger ();
+ self.touch = trigger_textstory_touch;
+
+ if (self.view_ofs == '0 0 0')
+ self.view_ofs = '90 90 0';
+
+ if (self.mangle)
+ self.mangle = normalizeAngles180(self.mangle);
+
+ if (self.noise1 == "")
+ self.noise1 = "misc/talk.wav";
+
+ if (self.noise2 == "")
+ self.noise2 = "misc/null.wav";
+
+ if (self.spawnflags & TEXTSTORY_SILENT)
+ {
+ self.noise1 = "";
+ self.noise2 = "";
+ }
+
+
+ if (self.noise1 != "")
+ precache_sound (self.noise1);
+ if (self.noise2 != "")
+ precache_sound (self.noise2);
+
+ SUB_CheckWaiting ();
+};
+
+//----------------------------------------------------------------------
+void() target_textstory_helper_hide =
+{
+
+ textstory_hide (self.owner);
+ remove (self);
+};
+
+//----------------------------------------------------------------------
+void() target_textstory_helper_show =
+{
+ if (!self.enemy || !(self.enemy.flags & FL_CLIENT))
+ {
+ remove (self);
+ return;
+ }
+
+ textstory_show (self.owner);
+
+ if (self.attack_finished < time)
+ self.think = target_textstory_helper_hide;
+
+ self.nextthink = time + 0.1;
+};
+
+//----------------------------------------------------------------------
+void(entity tgt) target_textstory_spawn_helper =
+{
+ entity e;
+
+ e = spawn();
+ e.classname = "target_textstory_helper";
+ e.owner = self;
+ e.think = target_textstory_helper_show;
+ e.nextthink = time + 0.1;
+ e.attack_finished = time + self.wait;
+ e.enemy = tgt;
+};
+
+//----------------------------------------------------------------------
+void() target_textstory_use =
+{
+
+ if (!(activator.flags & FL_CLIENT))
+ return;
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ entity t;
+
+ if (self.spawnflags & TRIGGER_CENTERPRINTALL)
+ {
+ t = find (world, classname, "player");
+ while (t)
+ {
+ target_textstory_spawn_helper (t);
+ t = find (t, classname, "player");
+ }
+ }
+ else
+ {
+ target_textstory_spawn_helper (activator);
+ }
+};
+
+//----------------------------------------------------------------------
+void() target_textstory =
+{
+ if (self.noise1 == "")
+ self.noise1 = "misc/talk.wav";
+
+ if (self.noise2 == "")
+ self.noise2 = "misc/null.wav";
+
+ if (self.spawnflags & TEXTSTORY_SILENT) {
+ self.noise1 = "";
+ self.noise2 = "";
+ }
+
+ if (self.noise1 != "")
+ precache_sound (self.noise1);
+ if (self.noise2 != "")
+ precache_sound (self.noise2);
+
+ if (!self.wait)
+ self.wait = 5;
+
+ self.use = target_textstory_use;
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/weapons.qc

diff --git a/qc/weapons.qc b/qc/weapons.qc
index 3182504..5729d49 100644
--- a/qc/weapons.qc
+++ b/qc/weapons.qc
@@ -1,11 +1,13 @@
-/*
-*/
-void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
-void () player_run;
+/*==============================================================================
+ WEAPONS.QC
+==============================================================================*/
+
+void(entity targ, entity inflictor, entity attacker, float damage) T_Damage;
+void() player_run;
void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
void(vector org, vector vel, float damage) SpawnBlood;
void() SuperDamageSound;
-void() create_mobot; //dumptruck_ds mobot.qc
+void() create_mobot; // dumptruck_ds mobot.qc
void(entity mis, float speed) SetupHoming;

void(entity mis, vector dir, float speed) SetSpeed =
@@ -14,16 +16,19 @@ void(entity mis, vector dir, float speed) SetSpeed =
{
mis.velocity = dir * speed;
}
- else {
+ else
+ {
mis.velocity = dir * cvar("sv_maxvelocity");
}
};

-// called by worldspawn
+//======================================================================
+// W_Precache called by worldspawn
+//----------------------------------------------------------------------
void() W_Precache =
{
precache_sound ("weapons/r_exp3.wav"); // new rocket explosion
- precache_sound ("weapons/rocket1i.wav"); // spike gun
+ precache_sound ("weapons/rocket1i.wav");// spike gun
precache_sound ("weapons/sgun1.wav");
precache_sound ("weapons/guncock.wav"); // player shotgun
precache_sound ("weapons/ric1.wav"); // ricochet (used in c code)
@@ -32,11 +37,10 @@ void() W_Precache =
precache_sound ("weapons/spike2.wav"); // super spikes
precache_sound ("weapons/tink1.wav"); // spikes tink (used in c code)
precache_sound ("weapons/grenade.wav"); // grenade launcher
- precache_sound ("weapons/bounce.wav"); // grenade bounce
+ precache_sound ("weapons/bounce.wav"); // grenade bounce
precache_sound ("weapons/shotgn2.wav"); // super shotgun

-// dumptruck_ds mobot.qc precaches START
-
+ // dumptruck_ds mobot.qc precaches START
precache_model ("progs/ogre.mdl");
precache_model ("progs/h_ogre.mdl");
precache_model ("progs/grenade.mdl");
@@ -66,13 +70,13 @@ void() W_Precache =
precache_sound2 ("enforcer/death1.wav");
precache_sound2 ("enforcer/enfire.wav");
precache_sound2 ("enforcer/enfstop.wav");
- precache_sound2("enforcer/idle1.wav");
+ precache_sound2 ("enforcer/idle1.wav");
precache_sound2 ("enforcer/pain1.wav");
precache_sound2 ("enforcer/pain2.wav");
precache_sound2 ("enforcer/sight1.wav");
precache_sound2 ("enforcer/sight2.wav");
precache_sound2 ("enforcer/sight3.wav");
- precache_sound2("enforcer/sight4.wav");
+ precache_sound2 ("enforcer/sight4.wav");

precache_model ("progs/soldier.mdl");
precache_model ("progs/h_guard.mdl");
@@ -87,12 +91,12 @@ void() W_Precache =
precache_sound ("soldier/pain2.wav");
precache_sound ("soldier/sattck1.wav");
precache_sound ("soldier/sight1.wav");
- precache_sound ("player/udeath.wav"); // gib death
+ precache_sound ("player/udeath.wav"); // gib death

precache_model ("progs/h_dog.mdl");
precache_model ("progs/dog.mdl");
precache_sound ("dog/dattack1.wav");
- precache_sound("dog/ddeath.wav");
+ precache_sound ("dog/ddeath.wav");
precache_sound ("dog/dpain1.wav");
precache_sound ("dog/dsight.wav");
precache_sound ("dog/idle.wav");
@@ -101,7 +105,7 @@ void() W_Precache =
precache_model ("progs/h_wizard.mdl");
precache_model ("progs/w_spike.mdl");

- precache_sound ("wizard/hit.wav"); // used by c code
+ precache_sound ("wizard/hit.wav"); // used by c code
precache_sound ("wizard/wattack.wav");
precache_sound ("wizard/wdeath.wav");
precache_sound ("wizard/widle1.wav");
@@ -142,7 +146,7 @@ void() W_Precache =
precache_sound2 ("hknight/death1.wav");
precache_sound2 ("hknight/pain1.wav");
precache_sound2 ("hknight/sight1.wav");
- precache_sound ("hknight/hit.wav"); // used by C code, so don't sound2
+ precache_sound ("hknight/hit.wav"); // used by C code; don't sound2
precache_sound2 ("hknight/slash1.wav");
precache_sound2 ("hknight/idle.wav");
precache_sound2 ("hknight/grunt.wav");
@@ -183,31 +187,28 @@ void() W_Precache =
precache_sound ("shambler/melee1.wav");
precache_sound ("shambler/melee2.wav");
precache_sound ("shambler/smack.wav");
-
// dumptruck_ds mobot.qc END
};

float() crandom =
{
- return 2*(random() - 0.5);
+ return 2 * (random () - 0.5);
};

-/*
-================
-W_FireAxe
-================
-*/
+//======================================================================
+// W_FireAxe
+//----------------------------------------------------------------------
void() W_FireAxe =
{
- local vector source;
- local vector org;
+ local vector source;
+ local vector org;

makevectors (self.v_angle);
source = self.origin + '0 0 16';
- traceline (source, source + v_forward*64, FALSE, self);
+ traceline (source, source + v_forward * 64, FALSE, self);
if (trace_fraction == 1.0)
return;
- org = trace_endpos - v_forward*4;
+ org = trace_endpos - v_forward * 4;

if (trace_ent.takedamage)
{
@@ -226,32 +227,26 @@ void() W_FireAxe =
}
};

-
-//============================================================================
-
-
+//----------------------------------------------------------------------
vector() wall_velocity =
{
- local vector vel;
+ local vector vel;

vel = normalize (self.velocity);
- vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
- vel = vel + 2*trace_plane_normal;
+ vel = normalize (vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
+ vel = vel + 2 * trace_plane_normal;
vel = vel * 200;

return vel;
};


-/*
-================
-SpawnMeatSpray
-================
-*/
+//======================================================================
+// SpawnMeatSpray
+//----------------------------------------------------------------------
void(vector org, vector vel) SpawnMeatSpray =
{
- local entity missile;
-
+ local entity missile;

missile = spawn ();
missile.owner = self;
@@ -261,11 +256,11 @@ void(vector org, vector vel) SpawnMeatSpray =
makevectors (self.angles);

missile.velocity = vel;
- missile.velocity_z = missile.velocity_z + 250 + 50*random();
+ missile.velocity_z = missile.velocity_z + 250 + 50 * random ();

missile.avelocity = '3000 1000 2000';

-// set missile duration
+ // set missile duration
missile.nextthink = time + 1;
missile.think = SUB_Remove;

@@ -274,52 +269,39 @@ void(vector org, vector vel) SpawnMeatSpray =
setorigin (missile, org);
};

-/*
-================
-SpawnBlood
-================
-*/
+//======================================================================
+// SpawnBlood
+//----------------------------------------------------------------------
void(vector org, vector vel, float damage) SpawnBlood =
{
- particle (org, vel*0.1, 73, damage*2);
+ particle (org, vel * 0.1, 73, damage * 2);
};

-/*
-================
-spawn_touchblood
-================
-*/
+//======================================================================
+// spawn_touchblood
+//----------------------------------------------------------------------
void(float damage) spawn_touchblood =
{
- local vector vel;
+ local vector vel;

vel = wall_velocity () * 0.2;
- SpawnBlood (self.origin + vel*0.01, vel, damage);
+ SpawnBlood (self.origin + vel* 0.01, vel, damage);
};

-
-/*
-================
-SpawnChunk
-================
-*/
+//======================================================================
+// SpawnChunk
+//----------------------------------------------------------------------
void(vector org, vector vel) SpawnChunk =
{
- particle (org, vel*0.02, 0, 10);
+ particle (org, vel * 0.02, 0, 10);
};

-/*
-==============================================================================
-
+/*======================================================================
MULTI-DAMAGE
-
Collects multiple small damages into a single damage
-
-==============================================================================
-*/
-
-entity multi_ent;
-float multi_damage;
+======================================================================*/
+entity multi_ent;
+float multi_damage;

void() ClearMultiDamage =
{
@@ -346,9 +328,13 @@ void(entity hit, float damage) AddMultiDamage =
multi_ent = hit;
}
else
+ {
multi_damage = multi_damage + damage;
+ }
};

+// TODO CEV
+
/*
==============================================================================

@@ -387,43 +373,41 @@ void(float damage, vector dir) TraceAttack =
}
};

-/*
-================
-FireBullets
-
-Used by shotgun, super shotgun, and enemy soldier firing
-Go to the trouble of combining multiple pellets into a single damage call.
-================
-*/
+//======================================================================
+// FireBullets
+//
+// Used by shotgun, super shotgun, and enemy soldier firing. Go to the
+// trouble of combining multiple pellets into a single damage call.
+//----------------------------------------------------------------------
void(float shotcount, vector dir, vector spread) FireBullets =
{
- local vector direction;
- local vector src;
+ local vector direction;
+ local vector src;

- makevectors(self.v_angle);
+ makevectors (self.v_angle);

- src = self.origin + v_forward*10;
+ src = self.origin + v_forward * 10;
src_z = self.absmin_z + self.size_z * 0.7;

ClearMultiDamage ();
while (shotcount > 0)
{
- direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
+ direction = dir + crandom() * spread_x * v_right
+ + crandom() *spread_y * v_up;

- traceline (src, src + direction*2048, FALSE, self);
+ traceline (src, src + direction * 2048, FALSE, self);
if (trace_fraction != 1.0)
TraceAttack (4, direction);

shotcount = shotcount - 1;
}
+
ApplyMultiDamage ();
};

-/*
-================
-W_FireShotgun
-================
-*/
+//======================================================================
+// W_FireShotgun
+//----------------------------------------------------------------------
void() W_FireShotgun =
{
local vector dir;
@@ -434,6 +418,7 @@ void() W_FireShotgun =

self.currentammo = self.ammo_shells = self.ammo_shells - 1;
dir = aim (self, 100000);
+ // TODO CEV
FireBullets (6, dir, '0.04 0.04 0');
};

@@ -784,7 +769,9 @@ void() W_FireLightning =

self.currentammo = self.ammo_cells = self.ammo_cells - 1;

+ // TODO CEV
org = self.origin + '0 0 16';
+ // org = self.origin;

traceline (org, org + v_forward*600, TRUE, self);

Return to the top of this page or return to the overview of this repo.

Diff qc/world.qc

diff --git a/qc/world.qc b/qc/world.qc
index fdb3f3f..ea6f277 100644
--- a/qc/world.qc
+++ b/qc/world.qc
@@ -1,13 +1,16 @@
+/*==============================================================================
+ WORLD
+==============================================================================*/

+//
void() InitBodyQue;

-
+//----------------------------------------------------------------------
void() main =
{
dprint ("main function\n");

-// these are just commands the the prog compiler to copy these files
-
+ // these are just commands the the prog compiler to copy these files
precache_file ("progs.dat");
precache_file ("gfx.wad");
precache_file ("quake.rc");
@@ -20,9 +23,7 @@ void() main =
precache_file ("demo2.dem");
precache_file ("demo3.dem");

-//
-// these are all of the lumps from the cached.ls files
-//
+ // these are all of the lumps from the cached.ls files
precache_file ("gfx/palette.lmp");
precache_file ("gfx/colormap.lmp");

@@ -96,7 +97,7 @@ void() main =
precache_file ("gfx/p_save.lmp");
precache_file ("gfx/p_multi.lmp");

-// sounds loaded by C code
+ // sounds loaded by C code
precache_sound ("misc/menu1.wav");
precache_sound ("misc/menu2.wav");
precache_sound ("misc/menu3.wav");
@@ -104,7 +105,7 @@ void() main =
precache_sound ("ambience/water1.wav");
precache_sound ("ambience/wind2.wav");

-// shareware
+ // shareware
precache_file ("maps/start.bsp");

precache_file ("maps/e1m1.bsp");
@@ -116,7 +117,7 @@ void() main =
precache_file ("maps/e1m7.bsp");
precache_file ("maps/e1m8.bsp");

-// registered
+ // registered
precache_file2 ("gfx/pop.lmp");

precache_file2 ("maps/e2m1.bsp");
@@ -154,16 +155,12 @@ void() main =
precache_file2 ("maps/dm6.bsp");
};

-
-/*
-================
-DetectKnownRelease
-
-This detects whether the current map is from a known release for which
-a backwards-compatibility hack should be applied, and sets the
-known_release global accordingly. -- iw
-================
-*/
+//======================================================================
+// DetectKnownRelease
+// This detects whether the current map is from a known release for which
+// a backwards-compatibility hack should be applied, and sets the
+// known_release global accordingly. -- iw
+//----------------------------------------------------------------------
void() DetectKnownRelease =
{
local string release_name;
@@ -243,10 +240,8 @@ void() DetectKnownRelease =
}
};

+entity lastspawn;

-entity lastspawn;
-
-//=======================
/*QUAKED worldspawn (0 0 0) ?
Only used for the world entity.

@@ -319,86 +314,83 @@ fog_color(string) : "Fog Color R/G/B example = (0.3 0.3 0.3)"

sky(string) : "Sky Texture" : : "Must have compatible skybox textures in gfx/env folder."
*/
-//=======================
void() worldspawn =
{
DetectKnownRelease ();

- InitNewSpawnflags (); // new spawnflags for all entities -- iw
+ // new spawnflags for all entities -- iw
+ InitNewSpawnflags ();

lastspawn = world;

- if (cvar("pr_checkextension"))
- {
- clientstat (CLIENT_VELOCITY_X, EV_FLOAT, velocity_x);
- clientstat (CLIENT_VELOCITY_Y, EV_FLOAT, velocity_y);
- }
-
InitBodyQue ();

-// custom map attributes
+ // custom map attributes
if (self.model == "maps/e1m8.bsp" && self.skip_id1_overrides == 0)
cvar_set ("sv_gravity", "100");
else
cvar_set ("sv_gravity", "800");

- cutscene = 0; // No cutscene is active during worldspawn. Drake -- dumptruck_ds
+ // No cutscene is active during worldspawn. Drake -- dumptruck_ds
+ cutscene = 0;

- world_sounds = &world.sounds; //Spike via dumptruck_ds || not read-only yet...
+ // Spike via dumptruck_ds || not read-only yet...
+ world_sounds = &world.sounds;

-// the area based ambient sounds MUST be the first precache_sounds
+ // the area based ambient sounds MUST be the first precache_sounds

-// player precaches
- W_Precache (); // get weapon precaches
+ // player precaches
+ // get weapon precaches
+ W_Precache ();

-// sounds used from C physics code
- precache_sound_land ("demon/dland2.wav"); // landing thud
- precache_sound ("misc/h2ohit1.wav"); // landing splash
+ // sounds used from C physics code
+ precache_sound_land ("demon/dland2.wav"); // landing thud
+ precache_sound ("misc/h2ohit1.wav"); // landing splash

-// setup precaches always needed
- precache_sound ("items/itembk2.wav"); // item respawn sound
- precache_sound ("player/plyrjmp8.wav"); // player jump
- precache_sound ("player/land.wav"); // player landing
- precache_sound ("player/land2.wav"); // player hurt landing
- precache_sound ("player/drown1.wav"); // drowning pain
- precache_sound ("player/drown2.wav"); // drowning pain
- precache_sound ("player/gasp1.wav"); // gasping for air
- precache_sound ("player/gasp2.wav"); // taking breath
- precache_sound ("player/h2odeath.wav"); // drowning death
+ // setup precaches always needed
+ precache_sound ("items/itembk2.wav"); // item respawn sound
+ precache_sound ("player/plyrjmp8.wav"); // player jump
+ precache_sound ("player/land.wav"); // player landing
+ precache_sound ("player/land2.wav"); // player hurt landing
+ precache_sound ("player/drown1.wav"); // drowning pain
+ precache_sound ("player/drown2.wav"); // drowning pain
+ precache_sound ("player/gasp1.wav"); // gasping for air
+ precache_sound ("player/gasp2.wav"); // taking breath
+ precache_sound ("player/h2odeath.wav"); // drowning death

- precache_sound ("misc/talk.wav"); // talk
- precache_sound ("player/teledth1.wav"); // telefrag
- precache_sound ("misc/r_tele1.wav"); // teleport sounds
+ precache_sound ("misc/talk.wav"); // talk
+ precache_sound ("player/teledth1.wav"); // telefrag
+ precache_sound ("misc/r_tele1.wav"); // teleport sounds
precache_sound ("misc/r_tele2.wav");
precache_sound ("misc/r_tele3.wav");
precache_sound ("misc/r_tele4.wav");
precache_sound ("misc/r_tele5.wav");
- precache_sound ("weapons/lock4.wav"); // ammo pick up
- precache_sound ("weapons/pkup.wav"); // weapon up
- precache_sound ("items/armor1.wav"); // armor up
- precache_sound ("weapons/lhit.wav"); //lightning
- precache_sound ("weapons/lstart.wav"); //lightning start
-
- // iw -- fix powerup cheat sounds // noticed this in Copper so why not? --ds
+ precache_sound ("weapons/lock4.wav"); // ammo pick up
+ precache_sound ("weapons/pkup.wav"); // weapon up
+ precache_sound ("items/armor1.wav"); // armor up
+ precache_sound ("weapons/lhit.wav"); //lightning
+ precache_sound ("weapons/lstart.wav"); //lightning start
+
+ // iw -- fix powerup cheat sounds
+ // noticed this in Copper so why not? --ds
// sounds used by cheats
- precache_sound ("items/suit2.wav"); // suit (finish)
- precache_sound ("items/protect2.wav"); // pent (finish)
- precache_sound ("items/protect3.wav"); // pent (protect)
- precache_sound ("items/inv2.wav"); // ring (finish)
- precache_sound ("items/inv3.wav"); // ring (idle)
- precache_sound ("items/damage2.wav"); // quad (finish)
- precache_sound ("items/damage3.wav"); // quad (attack)
+ precache_sound ("items/suit2.wav"); // suit (finish)
+ precache_sound ("items/protect2.wav"); // pent (finish)
+ precache_sound ("items/protect3.wav"); // pent (protect)
+ precache_sound ("items/inv2.wav"); // ring (finish)
+ precache_sound ("items/inv3.wav"); // ring (idle)
+ precache_sound ("items/damage2.wav"); // quad (finish)
+ precache_sound ("items/damage3.wav"); // quad (attack)
// iw -- END

- precache_sound ("misc/power.wav"); //lightning for boss
-
-// player gib sounds
- precache_sound ("player/gib.wav"); // player gib sound
- precache_sound ("player/udeath.wav"); // player gib sound
- precache_sound ("player/tornoff2.wav"); // gib sound
+ precache_sound ("misc/power.wav"); // lightning for boss

-// player pain sounds
+ // player gib sounds
+ precache_sound ("player/gib.wav"); // player gib sound
+ precache_sound ("player/udeath.wav"); // player gib sound
+ precache_sound ("player/tornoff2.wav"); // gib sound

+ // player pain sounds
precache_sound ("player/pain1.wav");
precache_sound ("player/pain2.wav");
precache_sound ("player/pain3.wav");
@@ -406,33 +398,35 @@ void() worldspawn =
precache_sound ("player/pain5.wav");
precache_sound ("player/pain6.wav");

-// player death sounds
+ // player death sounds
precache_sound ("player/death1.wav");
precache_sound ("player/death2.wav");
precache_sound ("player/death3.wav");
precache_sound ("player/death4.wav");
precache_sound ("player/death5.wav");

-// ax sounds
- precache_sound ("weapons/ax1.wav"); // ax swoosh
- precache_sound ("player/axhit1.wav"); // ax hit meat
- precache_sound ("player/axhit2.wav"); // ax hit world
+ // ax sounds
+ precache_sound ("weapons/ax1.wav"); // ax swoosh
+ precache_sound ("player/axhit1.wav"); // ax hit meat
+ precache_sound ("player/axhit2.wav"); // ax hit world

- precache_sound ("player/h2ojump.wav"); // player jumping into water
- precache_sound ("player/slimbrn2.wav"); // player enter slime
- precache_sound ("player/inh2o.wav"); // player enter water
- precache_sound ("player/inlava.wav"); // player enter lava
- precache_sound ("misc/outwater.wav"); // leaving water sound
+ precache_sound ("player/h2ojump.wav"); // player jumping into water
+ precache_sound ("player/slimbrn2.wav"); // player enter slime
+ precache_sound ("player/inh2o.wav"); // player enter water
+ precache_sound ("player/inlava.wav"); // player enter lava
+ precache_sound ("misc/outwater.wav"); // leaving water sound

- precache_sound ("player/lburn1.wav"); // lava burn
- precache_sound ("player/lburn2.wav"); // lava burn
+ precache_sound ("player/lburn1.wav"); // lava burn
+ precache_sound ("player/lburn2.wav"); // lava burn

- precache_sound ("misc/water1.wav"); // swimming
- precache_sound ("misc/water2.wav"); // swimming
+ precache_sound ("misc/water1.wav"); // swimming
+ precache_sound ("misc/water2.wav"); // swimming

precache_model ("progs/player.mdl");
- precache_model ("progs/s_null.spr"); // Invisible -- Drake -- dumptruck_ds
- // precache_model ("progs/null_256.spr"); // Invisible -- Drake -- dumptruck_ds
+ // Invisible -- Drake -- dumptruck_ds
+ precache_model ("progs/s_null.spr");
+ // Invisible -- Drake -- dumptruck_ds
+ // precache_model ("progs/null_256.spr");
precache_model ("progs/eyes.mdl");
precache_model ("progs/h_player.mdl");
precache_model ("progs/gib1.mdl");
@@ -450,9 +444,9 @@ void() worldspawn =
precache_model ("progs/v_nail2.mdl");
precache_model ("progs/v_rock2.mdl");

- precache_model ("progs/bolt.mdl"); // for lightning gun
- precache_model ("progs/bolt2.mdl"); // for lightning gun
- precache_model ("progs/bolt3.mdl"); // for boss shock
+ precache_model ("progs/bolt.mdl"); // for lightning gun
+ precache_model ("progs/bolt2.mdl"); // for lightning gun
+ precache_model ("progs/bolt3.mdl"); // for boss shock
precache_model ("progs/lavaball.mdl"); // for testing

precache_model ("progs/missile.mdl");
@@ -470,8 +464,9 @@ void() worldspawn =

precache_model ("progs/v_light.mdl");

- precache_model ("progs/w_s_key.mdl"); // dumptruck_ds needed for DropStuff
- precache_model ("progs/w_g_key.mdl"); //
+ // dumptruck_ds needed for DropStuff
+ precache_model ("progs/w_s_key.mdl");
+ precache_model ("progs/w_g_key.mdl");
precache_sound ("misc/medkey.wav");
precache_sound ("misc/runekey.wav");
precache_model ("progs/m_s_key.mdl");
@@ -481,89 +476,91 @@ void() worldspawn =
precache_model2 ("progs/b_g_key.mdl");
precache_model ("progs/h_mdls/pd_vial.mdl"); // DropVial -- dumptruck_ds
precache_sound ("items/r_item1.wav");
- precache_sound ("dump/armsh1.wav"); // DropShard -- dumptruck_ds
+ precache_sound ("dump/armsh1.wav"); // DropShard -- dumptruck_ds
precache_model ("progs/armshr.mdl");

-//
-// Setup light animation tables. 'a' is total darkness, 'z' is maxbright.
-//
+ // Setup light anim tables. 'a' is total darkness, 'z' is maxbright.

// 0 normal
- lightstyle(0, "m");
+ lightstyle (0, "m");

// 1 FLICKER (first variety)
- lightstyle(1, "mmnmmommommnonmmonqnmmo");
+ lightstyle (1, "mmnmmommommnonmmonqnmmo");

// 2 SLOW STRONG PULSE
- lightstyle(2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba");
+ lightstyle (2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba");

// 3 CANDLE (first variety)
- lightstyle(3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg");
+ lightstyle (3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg");

// 4 FAST STROBE
- lightstyle(4, "mamamamamama");
+ lightstyle (4, "mamamamamama");

// 5 GENTLE PULSE 1
- lightstyle(5,"jklmnopqrstuvwxyzyxwvutsrqponmlkj");
+ lightstyle (5,"jklmnopqrstuvwxyzyxwvutsrqponmlkj");

// 6 FLICKER (second variety)
- lightstyle(6, "nmonqnmomnmomomno");
+ lightstyle (6, "nmonqnmomnmomomno");

// 7 CANDLE (second variety)
- lightstyle(7, "mmmaaaabcdefgmmmmaaaammmaamm");
+ lightstyle (7, "mmmaaaabcdefgmmmmaaaammmaamm");

// 8 CANDLE (third variety)
- lightstyle(8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa");
+ lightstyle (8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa");

// 9 SLOW STROBE (fourth variety)
- lightstyle(9, "aaaaaaaazzzzzzzz");
+ lightstyle (9, "aaaaaaaazzzzzzzz");

// 10 FLUORESCENT FLICKER
- lightstyle(10, "mmamammmmammamamaaamammma");
+ lightstyle (10, "mmamammmmammamamaaamammma");

// 11 SLOW PULSE NOT FADE TO BLACK
- lightstyle(11, "abcdefghijklmnopqrrqponmlkjihgfedcba");
+ lightstyle (11, "abcdefghijklmnopqrrqponmlkjihgfedcba");

// styles 32-62 are assigned by the light program for switchable lights

// 63 testing
- lightstyle(63, "a");
+ lightstyle (63, "a");
};

-void() RestartLoopSounds_think = {
- sound(self, self.impulse, self.noise, self.volume, self.speed);
+//----------------------------------------------------------------------
+void() RestartLoopSounds_think =
+{
+ sound (self, self.impulse, self.noise, self.volume, self.speed);
};

-void() RestartLoopSounds = {
+//----------------------------------------------------------------------
+void() RestartLoopSounds =
+{
entity e;
- e = find(world, classname, "play_sound_triggered");
+ e = find (world, classname, "play_sound_triggered");
while (e) {
-
- if (e.spawnflags & 3 == 3) { // both "toggle" and "looped" need to be set
+ if (e.spawnflags & 3 == 3) {
+ // both "toggle" and "looped" need to be set
if (e.state == 1) {
e.nextthink = time + 0.1;
e.think = RestartLoopSounds_think;
}
}
-
- e = find(e, classname, "play_sound_triggered");
+ e = find (e, classname, "play_sound_triggered");
}
};

-
+//----------------------------------------------------------------------
void() StartFrame =
{
- if (!done_inhibition_summary) // new spawnflags for all entities -- iw
+ // new spawnflags for all entities -- iw
+ if (!done_inhibition_summary)
PrintInhibitionSummary ();

- teamplay = cvar("teamplay");
- skill = cvar("skill");
+ teamplay = cvar ("teamplay");
+ skill = cvar ("skill");
framecount = framecount + 1;

- if (cleanUpClientStuff) {
+ if (cleanUpClientStuff)
+ {
cleanUpClientStuff -= 1;
-
- RestartLoopSounds();
+ RestartLoopSounds ();
}
else if (!gamestarted && framecount > 2)
{
@@ -574,37 +571,39 @@ void() StartFrame =
}
};

-/*
-==============================================================================
-
-BODY QUE
-
-==============================================================================
-*/
+/*==============================================================================
+ BODY QUE
+==============================================================================*/

entity bodyque_head;

+//----------------------------------------------------------------------
void() bodyque =
-{ // just here so spawn functions don't complain after the world
+{
+ // just here so spawn functions don't complain after the world
// creates bodyques
};

+//----------------------------------------------------------------------
void() InitBodyQue =
{
- bodyque_head = spawn();
+ bodyque_head = spawn ();
bodyque_head.classname = "bodyque";
- bodyque_head.owner = spawn();
+ bodyque_head.owner = spawn ();
bodyque_head.owner.classname = "bodyque";
- bodyque_head.owner.owner = spawn();
+ bodyque_head.owner.owner = spawn ();
bodyque_head.owner.owner.classname = "bodyque";
- bodyque_head.owner.owner.owner = spawn();
+ bodyque_head.owner.owner.owner = spawn ();
bodyque_head.owner.owner.owner.classname = "bodyque";
bodyque_head.owner.owner.owner.owner = bodyque_head;
};

-
+//======================================================================
+// CopyToBodyQue
+//
// make a body que entry for the given ent so the ent can be
// respawned elsewhere
+//----------------------------------------------------------------------
void(entity ent) CopyToBodyQue =
{
bodyque_head.angles = ent.angles;

Return to the top of this page or return to the overview of this repo.