]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - dpdefs/csprogsdefs.qc
README: Remove Discord invite link. The Discord server is now deprecated
[xonotic/darkplaces.git] / dpdefs / csprogsdefs.qc
index bb5f2137f47a19c5872ef2e8e6feb7fbaeec0501..f4aa574ca4bf3ea3287dabfe1842c394eefa9c64 100644 (file)
@@ -166,7 +166,7 @@ const float MASK_NORMAL                     = 4;
 const float RF_VIEWMODEL       = 1;
 const float RF_EXTERNALMODEL   = 2;
 const float RF_DEPTHHACK       = 4;
-const float RF_ADDATIVE                = 8;
+const float RF_ADDITIVE                = 8;
 const float RF_USEAXIS         = 16;
 
 const float VF_MIN             = 1;    //(vector)
@@ -194,7 +194,7 @@ const float VF_DRAWCROSSHAIR        = 21;   //(float)
 const float VF_CL_VIEWANGLES   = 33;   //(vector)
 const float VF_CL_VIEWANGLES_X = 34;   //(float)
 const float VF_CL_VIEWANGLES_Y = 35;   //(float)
-const float VF_CL_VIEWANGLES_Z = 36;   //(float) 
+const float VF_CL_VIEWANGLES_Z = 36;   //(float)
 
 const float VF_PERSPECTIVE      = 200;
 
@@ -291,7 +291,7 @@ const float TE_EXPLOSION2                                   = 12;
        const float TE_EXPLOSIONQUAD                            = 70;
        const float TE_SPIKEQUAD                                        = 58;
        const float TE_SUPERSPIKEQUAD                           = 59;
-       
+
 // PFlags for Dynamic Lights
 const float PFLAGS_NOSHADOW                                    = 1;
 const float PFLAGS_CORONA                                      = 2;
@@ -335,9 +335,9 @@ void(entity e, vector o) setorigin = #2;
 void(entity e, string m) setmodel = #3;
 void(entity e, vector min, vector max) setsize = #4;
 
-void() break = #6;
+void() break_to_debugger = #6;
 float() random = #7;
-void(entity e, float chan, string samp) sound = #8;
+void(entity e, float chan, string samp, float volume, float atten, ...) sound = #8;
 vector(vector v) normalize = #9;
 void(string e) error = #10;
 void(string e) objerror = #11;
@@ -421,6 +421,7 @@ float( float b, ... ) max = #95;
 float(float minimum, float val, float maximum) bound = #96;
 float(float f, float f) pow = #97;
 entity(entity start, .float fld, float match) findfloat = #98;
+entity(entity start, .entity fld, entity match) findentity = #98;
 float(string s) checkextension = #99;
 // FrikaC and Telejano range #100-#199
 
@@ -434,6 +435,7 @@ string(string s, float start, float length) substring = #116;
 vector(string) stov = #117;
 string(string s) strzone = #118;
 void(string s) strunzone = #119;
+void(string s, float chan, float vol) localsound = #177;
 
 // FTEQW range #200-#299
 
@@ -447,6 +449,7 @@ string(float ccase, float calpha, float cnum, string s, ...) strconv = #224;
 string(float chars, string s, ...) strpad = #225;
 string(string info, string key, string value, ...) infoadd = #226;
 string(string info, string key) infoget = #227;
+float(string s1, string s2) strcmp = #228;
 float(string s1, string s2, float len) strncmp = #228;
 float(string s1, string s2) strcasecmp = #229;
 float(string s1, string s2, float len) strncasecmp = #230;
@@ -468,7 +471,7 @@ void() R_EndPolygon = #308;
 vector (vector v) cs_unproject = #310;
 vector (vector v) cs_project = #311;
 
-void(float width, vector pos1, vector pos2, float flag) drawline = #315;
+void(float width, vector pos1, vector pos2, vector rgb, float alpha, float flag) drawline = #315;
 float(string name) iscachedpic = #316;
 string(string name, ...) precache_pic = #317;
 string(string name) precache_cubemap = #317;
@@ -484,7 +487,7 @@ float(vector position, string text, vector scale, float alpha, float flag) drawc
 vector(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawcolorcodedstring2 = #326;
 
 float(float stnum) getstatf = #330;
-float(float stnum) getstati = #331;
+float(float stnum, ...) getstati = #331; // can optionally take first bit and count
 string(float firststnum) getstats = #332;
 void(entity e, float mdlindex) setmodelindex = #333;
 string(float mdlindex) modelnameforindex = #334;
@@ -520,7 +523,7 @@ float() ReadAngle = #365;
 string() ReadString = #366;
 float() ReadFloat = #367;
 
-// LordHavoc's range #400-#499
+// LadyHavoc's range #400-#499
 void(entity from, entity to) copyentity = #400;
 
 entity(.string fld, string match) findchain = #402;
@@ -595,7 +598,7 @@ float(float t) atan = #473;
 float(float c, float s) atan2 = #474;
 float(float a) tan = #475;
 float(string s) strippedstringlen = #476;
-float(string s) strlennocol = #476; // This is the correct name for the function, but not removing the decolorizedstring mapping.
+float(string s) strlennocol = #476; // This is the correct name for the function, but not removing the strippedstringlen mapping.
 string(string s) decolorizedstring = #477;
 string(string s) strdecolorize = #477; // This is the correct name for the function, but not removing the decolorizedstring mapping.
 string(float uselocaltime, string format, ...) strftime = #478;
@@ -656,11 +659,11 @@ float PARTICLE_BEAM = 3;
 float particle_type; // one of PT_
 float particle_blendmode; // one of PBLEND_ values
 float particle_orientation; // one of PARTICLE_ values
-vector particle_color1; 
+vector particle_color1;
 vector particle_color2;
 float particle_tex; // number of chunk in particlefont
 float particle_size;
-float particle_sizeincrease; 
+float particle_sizeincrease;
 float particle_alpha;
 float particle_alphafade;
 float particle_time;
@@ -692,10 +695,10 @@ float(vector org, vector vel) spawnparticle = #527; // returns 0 when failed, 1
 float(vector org, vector vel, float theme) quickparticle = #527; // not reading globals, just theme, returns 0 when failed, 1 when spawned
 float(vector org, vector vel, float delay, float collisiondelay) delayedparticle = #528;
 float(vector org, vector vel, float delay, float collisiondelay, float theme) quickdelayedparticle = #528;
-// description: this builtin provides an easy and flexible way to spawn particles, 
-// it is not created as replace for DP_SV_POINTPARTICLES but as an addition to it. 
+// description: this builtin provides an easy and flexible way to spawn particles,
+// it is not created as replace for DP_SV_POINTPARTICLES but as an addition to it.
 // With this extension you can create a specific particles like rain particles, or entity particles
-// notes: 
+// notes:
 // 1) 0 is default particle template, it could be changed
 // 2) color vectors could have value 0-255 of each component
 // restrictions: max themes could be between 4 and 2048
@@ -805,7 +808,7 @@ vector(float entitynum, float fldnum) getentityvec = #504;
 //darkplaces implementation: Blub\0
 //console commands:
 //  loadfont fontname fontmaps size1 size2 ...
-//   A font can simply be gfx/tgafile (freetype fonts doent need extension), 
+//   A font can simply be gfx/tgafile (freetype fonts doent need extension),
 //   or alternatively you can specify multiple fonts and faces
 //   Like this: gfx/vera-sans:2,gfx/fallback:1
 //   to load face 2 of the font gfx/vera-sans and use face 1
@@ -834,7 +837,7 @@ float FONT_USER6 = 14;     // 'user6', userdefined fonts
 float FONT_USER7 = 15;     // 'user7' slot, userdefined fonts
 //builtin definitions:
 float findfont(string s) = #356; // find font by fontname and return it's index
-float loadfont(string fontname, string fontmaps, string sizes, float slot, float fix_scale, float fix_voffset) = #357; 
+float loadfont(string fontname, string fontmaps, string sizes, float slot, float fix_scale, float fix_voffset) = #357;
 // loads font immediately so stringwidth() function can be used just after builtin call
 // returns a font slotnum (which is used to set drawfont to)
 // first 3 parms are identical to "loadfont" console command ones
@@ -865,7 +868,7 @@ float stringwidth_menu(string text, float allowColorCodes, vector size) = #468;
 //   r_font_postprocess_shadow_y X  : font outline shadow y shift amount, applied during outlining
 //   r_font_postprocess_shadow_z X  : font outline shadow z shift amount, applied during blurring
 //description: engine support for truetype/freetype fonts
-//so .AFM+.PFB/.OTF/.TTF files could be stuffed as fontmaps in loadfont() 
+//so .AFM+.PFB/.OTF/.TTF files could be stuffed as fontmaps in loadfont()
 //(console command version will support them as well)
 
 //DP_CSQC_BINDMAPS
@@ -896,7 +899,7 @@ float(string url, float id, string content_type, string delim, float buf, float
 //constant definitions:
 const float VF_MAINVIEW         = 400;
 //use setproperty(VF_MAINVIEW, 1); before calling R_RenderView for the render
-//that shall become the "main" view, which is e.g. used by PRYDON_CLIENTCURSOR 
+//that shall become the "main" view, which is e.g. used by PRYDON_CLIENTCURSOR
 //this flag is set for the first scene, and not cleared by R_ClearScene
 //this flag is automatically cleared by R_RenderView
 //so when not using this extension, the first view rendered is the main view
@@ -910,6 +913,7 @@ const float VF_MINFPS_QUALITY   = 401;
 //1 should lead to an unmodified view
 
 //DP_CSQC_V_CALCREFDEF_WIP1
+//DP_CSQC_V_CALCREFDEF_WIP2
 //idea: divVerent
 //darkplaces implementation: divVerent
 //builtin definitions:
@@ -919,9 +923,13 @@ float PMF_DUCKED = 4;
 float PMF_ONGROUND = 8;
 float REFDEFFLAG_TELEPORTED = 1;
 float REFDEFFLAG_JUMPING = 2;
+float REFDEFFLAG_DEAD = 4;
+float REFDEFFLAG_INTERMISSION = 8;
 //- use this on the player entity after performing prediction
 //- pass REFDEFFLAG_TELEPORTED if the player teleported since last frame
 //- pass REFDEFFLAG_JUMPING if jump button is pressed
+//- pass REFDEFFLAG_DEAD if dead (DP_CSQC_V_CALCREFDEF_WIP2)
+//- pass REFDEFFLAG_INTERMISSION if in intermission (DP_CSQC_V_CALCREFDEF_WIP2)
 //- the player entity needs to have origin, velocity, pmove_flags set according
 //  to prediction (the above two PMF_ flags are used in the player's pmove_flags)
 //- NOTE: to check for this, ALSO OR a check with DP_CSQC_V_CALCREFDEF to also support
@@ -937,29 +945,31 @@ vector    drawgetimagesize(string pic) = #318;
 #define SPA_TEXCOORDS0 4
 #define SPA_LIGHTMAP0_TEXCOORDS 5
 #define SPA_LIGHTMAP_COLOR 6
-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;
-vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
+// 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;
+// vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
 float(entity e, float s) getsurfacenumtriangles = #628;
 vector(entity e, float s, float n) getsurfacetriangle = #629;
 
 //DP_QC_ASINACOSATANATAN2TAN
 //idea: Urre
-//darkplaces implementation: LordHavoc
+//darkplaces implementation: LadyHavoc
 //constant definitions:
 float DEG2RAD = 0.0174532925199432957692369076848861271344287188854172545609719144;
 float RAD2DEG = 57.2957795130823208767981548141051703324054724665643215491602438612;
 float PI      = 3.1415926535897932384626433832795028841971693993751058209749445923;
 //builtin definitions:
+/* -Wdouble-declaration
 float(float s) asin = #471; // returns angle in radians for a given sin() value, the result is in the range -PI*0.5 to PI*0.5
 float(float c) acos = #472; // returns angle in radians for a given cos() value, the result is in the range 0 to PI
 float(float t) atan = #473; // returns angle in radians for a given tan() value, the result is in the range -PI*0.5 to PI*0.5
 float(float c, float s) atan2 = #474; // returns angle in radians for a given cos() and sin() value pair, the result is in the range -PI to PI (this is identical to vectoyaw except it returns radians rather than degrees)
 float(float a) tan = #475; // returns tangent value (which is simply sin(a)/cos(a)) for the given angle in radians, the result is in the range -infinity to +infinity
+*/
 //description:
 //useful math functions for analyzing vectors, note that these all use angles in radians (just like the cos/sin functions) not degrees unlike makevectors/vectoyaw/vectoangles, so be sure to do the appropriate conversions (multiply by DEG2RAD or RAD2DEG as needed).
 //note: atan2 can take unnormalized vectors (just like vectoyaw), and the function was included only for completeness (more often you want vectoyaw or vectoangles), atan2(v_x,v_y) * RAD2DEG gives the same result as vectoyaw(v)
@@ -973,10 +983,10 @@ string(string format, ...) sprintf = #627;
 //you know sprintf :P
 //supported stuff:
 //  %
-//  optional: <argpos>$ for the argument to format
+//  optional: <argpos>$ for the argument to format (the arg counter then is not increased)
 //  flags: #0- +
-//  optional: <width>, *, or *<argpos>$ for the field width
-//  optional: .<precision>, .*, or .*<argpos>$ for the precision
+//  optional: <width>, *, or *<argpos>$ for the field width (width is read before value and precision)
+//  optional: .<precision>, .*, or .*<argpos>$ for the precision (precision is read before value)
 //  length modifiers: h for forcing a float, l for forcing an int/entity (by default, %d etc. cast a float to int)
 //  conversions:
 //    d takes a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an int
@@ -1013,8 +1023,8 @@ float GETTIME_CDTRACK = 4;
 //see DP_END_GETSOUNDTIME for similar functionality but for entity sound channels
 
 //DP_QC_TOKENIZEBYSEPARATOR
-//idea: Electro, SavageX, LordHavoc
-//darkplaces implementation: LordHavoc
+//idea: Electro, SavageX, LadyHavoc
+//darkplaces implementation: LadyHavoc
 //builtin definitions:
 float(string s, string separator1, ...) tokenizebyseparator = #479;
 //description:
@@ -1064,17 +1074,18 @@ float SOUNDFLAG_RELIABLE = 1;
 //- NOTE: to check for this, ALSO OR a check with DP_SND_SOUND7 to also support
 //  the finished extension once done
 
-//DP_MOVETYPEFLYWORLDONLY
-//idea: Samual
-//darkplaces implementation: Samual
-//movetype definitions:
-float MOVETYPE_FLY_WORLDONLY = 33;
-//description:
-//like MOVETYPE_FLY, but does all traces with MOVE_WORLDONLY, and is ignored by MOVETYPE_PUSH. Should only be combined with SOLID_NOT and SOLID_TRIGGER.
+//DP_PRECACHE_PIC_FLAGS
+//idea: divVerent
+//darkplaces implementation: divVerent
+//constant definitions:
+float PRECACHE_PIC_FROMWAD = 1; // this one actually is part of EXT_CSQC
+float PRECACHE_PIC_NOTPERSISTENT = 2; // picture may get deallocated when unused
+float PRECACHE_PIC_MIPMAP = 8; // mipmap the texture for possibly better downscaling at memory expense
+//notes: these constants are given as optional second argument to precache_pic()
 
 //DP_QC_TRACE_MOVETYPE_WORLDONLY
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
+//idea: LadyHavoc
+//darkplaces implementation: LadyHavoc
 //constant definitions:
 float MOVE_WORLDONLY = 3;
 //description:
@@ -1102,8 +1113,8 @@ float(string sample) soundlength = #534; // returns length of sound sample in se
 float(entity num) num_for_edict = #512;
 
 //DP_TRACE_HITCONTENTSMASK_SURFACEINFO
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
+//idea: LadyHavoc
+//darkplaces implementation: LadyHavoc
 //globals:
 .float dphitcontentsmask; // if non-zero on the entity passed to traceline/tracebox/tracetoss this will override the normal collidable contents rules and instead hit these contents values (for example AI can use tracelines that hit DONOTENTER if it wants to, by simply changing this field on the entity passed to traceline), this affects normal movement as well as trace calls
 float trace_dpstartcontents; // DPCONTENTS_ value at start position of trace
@@ -1204,6 +1215,239 @@ float log(float f) = #532;
 //description:
 //logarithm
 
+//FTE_CSQC_SKELETONOBJECTS
+//idea: Spike, LadyHavoc
+//darkplaces implementation: LadyHavoc
+//builtin definitions:
+// all skeleton numbers are 1-based (0 being no skeleton)
+// all bone numbers are 1-based (0 being invalid)
+float(float modlindex) skel_create = #263; // create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex, as the skeleton uses the hierarchy from the model.
+float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
+float(float skel) skel_get_numbones = #265; // returns how many bones exist in the created skeleton, 0 if skeleton does not exist
+string(float skel, float bonenum) skel_get_bonename = #266; // returns name of bone (as a tempstring), "" if invalid bonenum (< 1 for example) or skeleton does not exist
+float(float skel, float bonenum) skel_get_boneparent = #267; // returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
+float(float skel, string tagname) skel_find_bone = #268; // get number of bone with specified name, 0 on failure, bonenum (1-based) on success, same as using gettagindex but takes modelindex instead of entity
+vector(float skel, float bonenum) skel_get_bonerel = #269; // get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
+vector(float skel, float bonenum) skel_get_boneabs = #270; // get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
+void(float skel, float bonenum, vector org) skel_set_bone = #271; // set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
+void(float skel, float bonenum, vector org) skel_mul_bone = #272; // transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
+void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
+void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
+void(float skel) skel_delete = #275; // deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
+float(float modlindex, string framename) frameforname = #276; // finds number of a specified frame in the animation, returns -1 if no match found
+float(float modlindex, float framenum) frameduration = #277; // returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
+//fields:
+.float skeletonindex; // active skeleton overriding standard animation on model
+.float frame; // primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4)
+.float frame2; // secondary framegroup animation (strength = lerpfrac)
+.float frame3; // tertiary framegroup animation (strength = lerpfrac3)
+.float frame4; // quaternary framegroup animation (strength = lerpfrac4)
+.float lerpfrac; // strength of framegroup blend
+.float lerpfrac3; // strength of framegroup blend
+.float lerpfrac4; // strength of framegroup blend
+.float frame1time; // start time of framegroup animation
+.float frame2time; // start time of framegroup animation
+.float frame3time; // start time of framegroup animation
+.float frame4time; // start time of framegroup animation
+//description:
+//this extension provides a way to do complex skeletal animation on an entity.
+//
+//see also DP_SKELETONOBJECTS (this extension implemented on server as well as client)
+//
+//notes:
+//each model contains its own skeleton, reusing a skeleton with incompatible models will yield garbage (or not render).
+//each model contains its own animation data, you can use animations from other model files (for example saving out all character animations as separate model files).
+//if an engine supports loading an animation-only file format such as .md5anim in FTEQW, it can be used to animate any model with a compatible skeleton.
+//proper use of this extension may require understanding matrix transforms (v_forward, v_right, v_up, origin), and you must keep in mind that v_right is negative for this purpose.
+//
+//features include:
+//multiple animations blended together.
+//animating a model with animations from another model with a compatible skeleton.
+//restricting animation blends to certain bones of a model - for example independent animation of legs, torso, head.
+//custom bone controllers - for example making eyes track a target location.
+//
+//
+//
+//example code follows...
+//
+//this helper function lets you identify (by parentage) what group a bone
+//belongs to - for example "torso", "leftarm", would return 1 ("torso") for
+//all children of the bone named "torso", unless they are children of
+//"leftarm" (which is a child of "torso") which would return 2 instead...
+float(float skel, float bonenum, string g1, string g2, string g3, string g4, string g5, string g6) example_skel_findbonegroup =
+{
+       local string bonename;
+       while (bonenum >= 0)
+       {
+               bonename = skel_get_bonename(skel, bonenum);
+               if (bonename == g1) return 1;
+               if (bonename == g2) return 2;
+               if (bonename == g3) return 3;
+               if (bonename == g4) return 4;
+               if (bonename == g5) return 5;
+               if (bonename == g6) return 6;
+               bonenum = skel_get_boneparent(skel, bonenum);
+       }
+       return 0;
+};
+// create a skeletonindex for our player using current modelindex
+void() example_skel_player_setup =
+{
+       self.skeletonindex = skel_create(self.modelindex);
+};
+// setup bones of skeleton based on an animation
+// note: animmodelindex can be a different model than self.modelindex
+void(float animmodelindex, float framegroup, float framegroupstarttime) example_skel_player_update_begin =
+{
+       // start with our standard animation
+       self.frame = framegroup;
+       self.frame2 = 0;
+       self.frame3 = 0;
+       self.frame4 = 0;
+       self.frame1time = framegroupstarttime;
+       self.frame2time = 0;
+       self.frame3time = 0;
+       self.frame4time = 0;
+       self.lerpfrac = 0;
+       self.lerpfrac3 = 0;
+       self.lerpfrac4 = 0;
+       skel_build(self.skeletonindex, self, animmodelindex, 0, 0, 100000);
+};
+// apply a different framegroup animation to bones with a specified parent
+void(float animmodelindex, float framegroup, float framegroupstarttime, float blendalpha, string groupbonename, string excludegroupname1, string excludegroupname2) example_skel_player_update_applyoverride =
+{
+       local float bonenum;
+       local float numbones;
+       self.frame = framegroup;
+       self.frame2 = 0;
+       self.frame3 = 0;
+       self.frame4 = 0;
+       self.frame1time = framegroupstarttime;
+       self.frame2time = 0;
+       self.frame3time = 0;
+       self.frame4time = 0;
+       self.lerpfrac = 0;
+       self.lerpfrac3 = 0;
+       self.lerpfrac4 = 0;
+       bonenum = 0;
+       numbones = skel_get_numbones(self.skeletonindex);
+       while (bonenum < numbones)
+       {
+               if (example_skel_findbonegroup(self.skeletonindex, bonenum, groupbonename, excludegroupname1, excludegroupname2, "", "", "") == 1)
+                       skel_build(self.skeletonindex, self, animmodelindex, 1 - blendalpha, bonenum, bonenum + 1);
+               bonenum = bonenum + 1;
+       }
+};
+// make eyes point at a target location, be sure v_forward, v_right, v_up are set correctly before calling
+void(vector eyetarget, string bonename) example_skel_player_update_eyetarget =
+{
+       local float bonenum;
+       local vector ang;
+       local vector oldforward, oldright, oldup;
+       local vector relforward, relright, relup, relorg;
+       local vector boneforward, boneright, boneup, boneorg;
+       local vector parentforward, parentright, parentup, parentorg;
+       local vector u, v;
+       local vector modeleyetarget;
+       bonenum = skel_find_bone(self.skeletonindex, bonename) - 1;
+       if (bonenum < 0)
+               return;
+       oldforward = v_forward;
+       oldright = v_right;
+       oldup = v_up;
+       v = eyetarget - self.origin;
+       modeleyetarget_x =   v * v_forward;
+       modeleyetarget_y = 0-v * v_right;
+       modeleyetarget_z =   v * v_up;
+       // this is an eyeball, make it point at the target location
+       // first get all the data we can...
+       relorg = skel_get_bonerel(self.skeletonindex, bonenum);
+       relforward = v_forward;
+       relright = v_right;
+       relup = v_up;
+       boneorg = skel_get_boneabs(self.skeletonindex, bonenum);
+       boneforward = v_forward;
+       boneright = v_right;
+       boneup = v_up;
+       parentorg = skel_get_boneabs(self.skeletonindex, skel_get_boneparent(self.skeletonindex, bonenum));
+       parentforward = v_forward;
+       parentright = v_right;
+       parentup = v_up;
+       // get the vector from the eyeball to the target
+       u = modeleyetarget - boneorg;
+       // now transform it inversely by the parent matrix to produce new rel vectors
+       v_x = u * parentforward;
+       v_y = u * parentright;
+       v_z = u * parentup;
+       ang = vectoangles2(v, relup);
+       ang_x = 0 - ang_x;
+       makevectors(ang);
+       // set the relative bone matrix
+       skel_set_bone(self.skeletonindex, bonenum, relorg);
+       // restore caller's v_ vectors
+       v_forward = oldforward;
+       v_right = oldright;
+       v_up = oldup;
+};
+// delete skeleton when we're done with it
+// note: skeleton remains valid until next frame when it is really deleted
+void() example_skel_player_delete =
+{
+       skel_delete(self.skeletonindex);
+       self.skeletonindex = 0;
+};
+//
+// END OF EXAMPLES FOR FTE_CSQC_SKELETONOBJECTS
+//
+
+//DP_QC_ENTITYDATA
+//idea: KrimZon
+//darkplaces implementation: KrimZon
+//builtin definitions:
+float() numentityfields = #496;
+string(float fieldnum) entityfieldname = #497;
+float(float fieldnum) entityfieldtype = #498;
+string(float fieldnum, entity ent) getentityfieldstring = #499;
+float(float fieldnum, entity ent, string s) putentityfieldstring = #500;
+//constants:
+//Returned by entityfieldtype
+float FIELD_STRING   = 1;
+float FIELD_FLOAT    = 2;
+float FIELD_VECTOR   = 3;
+float FIELD_ENTITY   = 4;
+float FIELD_FUNCTION = 6;
+//description:
+//Versatile functions intended for storing data from specific entities between level changes, but can be customized for some kind of partial savegame.
+//WARNING: .entity fields cannot be saved and restored between map loads as they will leave dangling pointers.
+//numentityfields returns the number of entity fields. NOT offsets. Vectors comprise 4 fields: v, v_x, v_y and v_z.
+//entityfieldname returns the name as a string, eg. "origin" or "classname" or whatever.
+//entityfieldtype returns a value that the constants represent, but the field may be of another type in more exotic progs.dat formats or compilers.
+//getentityfieldstring returns data as would be written to a savegame, eg... "0.05" (float), "0 0 1" (vector), or "Hello World!" (string). Function names can also be returned.
+//putentityfieldstring puts the data returned by getentityfieldstring back into the entity.
+
+//DP_QC_ENTITYSTRING
+void(string s) loadfromdata = #529;
+void(string s) loadfromfile = #530;
+void(string s) callfunction = #605;
+void(float fh, entity e) writetofile = #606;
+float(string s) isfunction = #607;
+void(entity e, string s) parseentitydata = #608;
+
+//DP_COVERAGE
+//idea: divVerent
+//darkplaces implementation: divVerent
+//function definitions:
+void coverage() = #642;  // Reports a coverage event. The engine counts for each of the calls to this builtin whether it has been called.
+
+//DP_QC_FS_SEARCH_PACKFILE
+//idea: Mario
+//darkplaces implementation: Mario
+//builtin definitions:
+float(string pattern, float caseinsensitive, float quiet, string packfile) search_packfile_begin = #444;
+//description:
+//extension to search_begin (DP_QC_FS_SEARCH), performs a filename search with the specified pattern (for example "maps/*.bsp") and stores the results in a search slot (minimum of 128 supported by any engine with this extension), the other functions take this returned search slot number, be sure to search_free when done (they are also freed on progs reload).
+//only searches for files within the specified packfile, which is expected to match the results of whichpack().
+
 // assorted builtins
 const float            STAT_MOVEVARS_TICRATE           = 240;
 const float            STAT_MOVEVARS_TIMESCALE         = 241;
@@ -1215,5 +1459,20 @@ float PARTICLES_USEALPHA = 1;
 float particles_alphamin, particles_alphamax;
 float PARTICLES_USECOLOR = 2;
 vector particles_colormin, particles_colormax;
+float PARTICLES_USEFADE = 4;  // fades the COUNT (fade alpha using alphamin/alphamax)
+float particles_fade;
+float PARTICLES_DRAWASTRAIL = 128;
 void(float effectindex, entity own, vector org_from, vector org_to, vector dir_from, vector dir_to, float countmultiplier, float flags) boxparticles = #502;
 float trace_networkentity;
+const float RF_FULLBRIGHT      = 256;
+const float RF_NOSHADOW        = 512;
+float RF_DYNAMICMODELLIGHT = 8192;
+
+float gettaginfo_parent;
+string gettaginfo_name;
+vector gettaginfo_offset;
+vector gettaginfo_forward;
+vector gettaginfo_right;
+vector gettaginfo_up;
+float checkpvs(vector viewpos, entity viewee) = #240;
+float mod(float dividend, float divisor) = #245;