this patch may break things and needs testing
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 19 Feb 2007 01:33:38 +0000 (01:33 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 19 Feb 2007 01:33:38 +0000 (01:33 +0000)
major cleanup of csqc and ssqc builtin tables
minimized differences between csqc and ssqc builtin tables (everything that can be implemented in both is implemented in both)
added VM_SAFEPARMCOUNTRANGE to allow a function to have, for example, 2-4 parameters (where as VM_SAFEPARMCOUNT requires it to be an exact match)
added VM_SAFEPARMCOUNT or VM_SAFEPARMCOUNTRANGE to ALL builtins, this may break buggy qc (and it's possible that one or more of these checks are wrong)
replaced CL_TraceBox with CL_Move, this is a proper csqc-entity aware version akin to SV_Move, it has a ton of parameters due to support for network entity collisions as well (ideally this needs cleanup somehow but I have no idea how, as non-csqc network entities do not share the prvm_edict_t system and do not have entity numbers in the csqc world)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6862 d7cf8633-e32d-0410-b094-e92efae38249

22 files changed:
cl_collision.c
cl_collision.h
cl_input.c
cl_main.c
cl_particles.c
clvm_cmds.c
csprogs.c
gl_rmain.c
mvm_cmds.c
prvm_cmds.c
prvm_cmds.h
r_explosion.c
r_light.c
r_shadow.c
server.h
sv_main.c
sv_move.c
sv_phys.c
sv_user.c
svvm_cmds.c
todo
view.c

index 92d5b8d..82aa3ce 100644 (file)
@@ -2,182 +2,6 @@
 #include "quakedef.h"
 #include "cl_collision.h"
 
-/*
-// not yet used
-typedef struct physentity_s
-{
-       // this may be a entity_t, or a prvm_edict_t, or whatever
-       void *realentity;
-
-       // can be NULL if it is a bbox object
-       model_t *bmodel;
-
-       // node this entity crosses
-       // for avoiding unnecessary collisions
-       physnode_t *node;
-
-       // matrix for converting from model to world coordinates
-       double modeltoworldmatrix[3][4];
-
-       // matrix for converting from world to model coordinates
-       double worldtomodelmatrix[3][4];
-
-       // if this is a bmodel, this is used for culling it quickly
-       // if this is not a bmodel, this is used for actual collisions
-       double mins[3], maxs[3];
-}
-physentity_t;
-*/
-
-trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitbmodels, int *hitent, int hitsupercontentsmask, qboolean hitplayers)
-{
-       int n;
-       entity_render_t *ent;
-       vec3_t tracemins, tracemaxs;
-       trace_t cliptrace, trace;
-       vec3_t origin;
-       vec3_t starttransformed, endtransformed;
-       vec3_t entmins, entmaxs;
-       vec_t *playermins, *playermaxs;
-
-       memset (&cliptrace, 0 , sizeof(trace_t));
-       cliptrace.fraction = 1;
-       cliptrace.realfraction = 1;
-
-       if (cl.worldmodel && cl.worldmodel->TraceBox)
-               cl.worldmodel->TraceBox(cl.worldmodel, 0, &cliptrace, start, mins, maxs, end, hitsupercontentsmask);
-
-       if (hitent)
-               *hitent = 0;
-
-       if (hitbmodels && cl.num_brushmodel_entities)
-       {
-               tracemins[0] = min(start[0], end[0]) + mins[0];
-               tracemaxs[0] = max(start[0], end[0]) + maxs[0];
-               tracemins[1] = min(start[1], end[1]) + mins[1];
-               tracemaxs[1] = max(start[1], end[1]) + maxs[1];
-               tracemins[2] = min(start[2], end[2]) + mins[2];
-               tracemaxs[2] = max(start[2], end[2]) + maxs[2];
-
-               // look for embedded bmodels
-               for (n = 0;n < cl.num_brushmodel_entities;n++)
-               {
-                       ent = &cl.entities[cl.brushmodel_entities[n]].render;
-                       if (!BoxesOverlap(tracemins, tracemaxs, ent->mins, ent->maxs))
-                               continue;
-
-                       Matrix4x4_Transform(&ent->inversematrix, start, starttransformed);
-                       Matrix4x4_Transform(&ent->inversematrix, end, endtransformed);
-
-                       memset (&trace, 0 , sizeof(trace_t));
-                       trace.fraction = 1;
-                       trace.realfraction = 1;
-
-                       if (ent->model && ent->model->TraceBox)
-                               ent->model->TraceBox(ent->model, 0, &trace, starttransformed, mins, maxs, endtransformed, hitsupercontentsmask);
-
-                       // LordHavoc: take the 'best' answers from the new trace and combine with existing data
-                       if (trace.allsolid)
-                               cliptrace.allsolid = true;
-                       if (trace.startsolid)
-                       {
-                               cliptrace.startsolid = true;
-                               if (cliptrace.realfraction == 1)
-                                       if (hitent)
-                                               *hitent = cl.brushmodel_entities[n];
-                       }
-                       // don't set this except on the world, because it can easily confuse
-                       // monsters underwater if there's a bmodel involved in the trace
-                       // (inopen && inwater is how they check water visibility)
-                       //if (trace.inopen)
-                       //      cliptrace.inopen = true;
-                       if (trace.inwater)
-                               cliptrace.inwater = true;
-                       if (trace.realfraction < cliptrace.realfraction)
-                       {
-                               cliptrace.fraction = trace.fraction;
-                               cliptrace.realfraction = trace.realfraction;
-                               cliptrace.plane = trace.plane;
-                               if (hitent)
-                                       *hitent = cl.brushmodel_entities[n];
-                               Matrix4x4_Transform3x3(&ent->matrix, trace.plane.normal, cliptrace.plane.normal);
-                               cliptrace.hitsupercontents = trace.hitsupercontents;
-                               cliptrace.hitq3surfaceflags = trace.hitq3surfaceflags;
-                               cliptrace.hittexture = trace.hittexture;
-                       }
-                       cliptrace.startsupercontents |= trace.startsupercontents;
-               }
-       }
-       if (hitplayers)
-       {
-               tracemins[0] = min(start[0], end[0]) + mins[0];
-               tracemaxs[0] = max(start[0], end[0]) + maxs[0];
-               tracemins[1] = min(start[1], end[1]) + mins[1];
-               tracemaxs[1] = max(start[1], end[1]) + maxs[1];
-               tracemins[2] = min(start[2], end[2]) + mins[2];
-               tracemaxs[2] = max(start[2], end[2]) + maxs[2];
-
-               for (n = 1;n < cl.maxclients+1;n++)
-               {
-                       if (n != cl.playerentity)
-                       {
-                               ent = &cl.entities[n].render;
-                               // FIXME: crouch
-                               playermins = cl.playerstandmins;
-                               playermaxs = cl.playerstandmaxs;
-                               Matrix4x4_OriginFromMatrix(&ent->matrix, origin);
-                               VectorAdd(origin, playermins, entmins);
-                               VectorAdd(origin, playermaxs, entmaxs);
-                               if (!BoxesOverlap(tracemins, tracemaxs, entmins, entmaxs))
-                                       continue;
-
-                               memset (&trace, 0 , sizeof(trace_t));
-                               trace.fraction = 1;
-                               trace.realfraction = 1;
-
-                               Matrix4x4_Transform(&ent->inversematrix, start, starttransformed);
-                               Matrix4x4_Transform(&ent->inversematrix, end, endtransformed);
-                               Collision_ClipTrace_Box(&trace, playermins, playermaxs, starttransformed, mins, maxs, endtransformed, hitsupercontentsmask, SUPERCONTENTS_BODY, 0, NULL);
-
-                               // LordHavoc: take the 'best' answers from the new trace and combine with existing data
-                               if (trace.allsolid)
-                                       cliptrace.allsolid = true;
-                               if (trace.startsolid)
-                               {
-                                       cliptrace.startsolid = true;
-                                       if (cliptrace.realfraction == 1)
-                                               if (hitent)
-                                                       *hitent = n;
-                               }
-                               // don't set this except on the world, because it can easily confuse
-                               // monsters underwater if there's a bmodel involved in the trace
-                               // (inopen && inwater is how they check water visibility)
-                               //if (trace.inopen)
-                               //      cliptrace.inopen = true;
-                               if (trace.inwater)
-                                       cliptrace.inwater = true;
-                               if (trace.realfraction < cliptrace.realfraction)
-                               {
-                                       cliptrace.fraction = trace.fraction;
-                                       cliptrace.realfraction = trace.realfraction;
-                                       cliptrace.plane = trace.plane;
-                                       if (hitent)
-                                               *hitent = n;
-                                       Matrix4x4_Transform3x3(&ent->matrix, trace.plane.normal, cliptrace.plane.normal);
-                                       cliptrace.hitsupercontents = trace.hitsupercontents;
-                                       cliptrace.hitq3surfaceflags = trace.hitq3surfaceflags;
-                                       cliptrace.hittexture = trace.hittexture;
-                               }
-                               cliptrace.startsupercontents |= trace.startsupercontents;
-                       }
-               }
-       }
-       cliptrace.fraction = bound(0, cliptrace.fraction, 1);
-       cliptrace.realfraction = bound(0, cliptrace.realfraction, 1);
-       VectorLerp(start, cliptrace.fraction, end, cliptrace.endpos);
-       return cliptrace;
-}
-
 float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, vec3_t normal, int *hitent, entity_render_t *ignoreent)
 {
        float maxfrac, maxrealfrac;
@@ -260,8 +84,268 @@ void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius)
                cl.worldmodel->brush.FindNonSolidLocation(cl.worldmodel, in, out, radius);
 }
 
-int CL_PointSuperContents(const vec3_t p)
+model_t *CL_GetModelByIndex(int modelindex)
 {
-       return CL_TraceBox(p, vec3_origin, vec3_origin, p, true, NULL, 0, false).startsupercontents;
+       if(!modelindex)
+               return NULL;
+       if (modelindex < 0)
+       {
+               modelindex = -(modelindex+1);
+               if (modelindex < MAX_MODELS)
+                       return cl.csqc_model_precache[modelindex];
+       }
+       else
+       {
+               if(modelindex < MAX_MODELS)
+                       return cl.model_precache[modelindex];
+       }
+       return NULL;
+}
+
+model_t *CL_GetModelFromEdict(prvm_edict_t *ed)
+{
+       if (!ed || ed->priv.server->free)
+               return NULL;
+       return CL_GetModelByIndex((int)ed->fields.client->modelindex);
+}
+
+void CL_LinkEdict(prvm_edict_t *ent)
+{
+       if (ent == prog->edicts)
+               return;         // don't add the world
+
+       if (ent->priv.server->free)
+               return;
+
+       VectorAdd(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->absmin);
+       VectorAdd(ent->fields.client->origin, ent->fields.client->maxs, ent->fields.client->absmax);
+
+       World_LinkEdict(&cl.world, ent, ent->fields.client->absmin, ent->fields.client->absmax);
 }
 
+int CL_GenericHitSuperContentsMask(const prvm_edict_t *passedict)
+{
+       prvm_eval_t *val;
+       if (passedict)
+       {
+               val = PRVM_EDICTFIELDVALUE(passedict, prog->fieldoffsets.dphitcontentsmask);
+               if (val && val->_float)
+                       return (int)val->_float;
+               else if (passedict->fields.client->solid == SOLID_SLIDEBOX)
+               {
+                       if ((int)passedict->fields.client->flags & FL_MONSTER)
+                               return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_MONSTERCLIP;
+                       else
+                               return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP;
+               }
+               else if (passedict->fields.client->solid == SOLID_CORPSE)
+                       return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY;
+               else
+                       return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE;
+       }
+       else
+               return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE;
+}
+
+/*
+==================
+CL_Move
+==================
+*/
+extern cvar_t sv_debugmove;
+trace_t CL_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities)
+{
+       vec3_t hullmins, hullmaxs;
+       int i;
+       int passedictprog;
+       qboolean pointtrace;
+       prvm_edict_t *traceowner, *touch;
+       trace_t trace;
+       // bounding box of entire move area
+       vec3_t clipboxmins, clipboxmaxs;
+       // size of the moving object
+       vec3_t clipmins, clipmaxs;
+       // size when clipping against monsters
+       vec3_t clipmins2, clipmaxs2;
+       // start and end origin of move
+       vec3_t clipstart, clipend;
+       // trace results
+       trace_t cliptrace;
+       // matrices to transform into/out of other entity's space
+       matrix4x4_t matrix, imatrix;
+       // model of other entity
+       model_t *model;
+       // list of entities to test for collisions
+       int numtouchedicts;
+       prvm_edict_t *touchedicts[MAX_EDICTS];
+
+       if (hitnetworkentity)
+               *hitnetworkentity = 0;
+
+       VectorCopy(start, clipstart);
+       VectorCopy(end, clipend);
+       VectorCopy(mins, clipmins);
+       VectorCopy(maxs, clipmaxs);
+       VectorCopy(mins, clipmins2);
+       VectorCopy(maxs, clipmaxs2);
+#if COLLISIONPARANOID >= 3
+       Con_Printf("move(%f %f %f,%f %f %f)", clipstart[0], clipstart[1], clipstart[2], clipend[0], clipend[1], clipend[2]);
+#endif
+
+       // clip to world
+       Collision_ClipToWorld(&cliptrace, cl.worldmodel, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask);
+       cliptrace.bmodelstartsolid = cliptrace.startsolid;
+       if (cliptrace.startsolid || cliptrace.fraction < 1)
+               cliptrace.ent = prog ? prog->edicts : NULL;
+       if (type == MOVE_WORLDONLY)
+               return cliptrace;
+
+       if (type == MOVE_MISSILE)
+       {
+               // LordHavoc: modified this, was = -15, now -= 15
+               for (i = 0;i < 3;i++)
+               {
+                       clipmins2[i] -= 15;
+                       clipmaxs2[i] += 15;
+               }
+       }
+
+       // get adjusted box for bmodel collisions if the world is q1bsp or hlbsp
+       if (cl.worldmodel && cl.worldmodel->brush.RoundUpToHullSize)
+               cl.worldmodel->brush.RoundUpToHullSize(cl.worldmodel, clipmins, clipmaxs, hullmins, hullmaxs);
+       else
+       {
+               VectorCopy(clipmins, hullmins);
+               VectorCopy(clipmaxs, hullmaxs);
+       }
+
+       // create the bounding box of the entire move
+       for (i = 0;i < 3;i++)
+       {
+               clipboxmins[i] = min(clipstart[i], cliptrace.endpos[i]) + min(hullmins[i], clipmins2[i]) - 1;
+               clipboxmaxs[i] = max(clipstart[i], cliptrace.endpos[i]) + max(hullmaxs[i], clipmaxs2[i]) + 1;
+       }
+
+       // debug override to test against everything
+       if (sv_debugmove.integer)
+       {
+               clipboxmins[0] = clipboxmins[1] = clipboxmins[2] = -999999999;
+               clipboxmaxs[0] = clipboxmaxs[1] = clipboxmaxs[2] =  999999999;
+       }
+
+       // if the passedict is world, make it NULL (to avoid two checks each time)
+       // this checks prog because this function is often called without a CSQC
+       // VM context
+       if (prog == NULL || passedict == prog->edicts)
+               passedict = NULL;
+       // precalculate prog value for passedict for comparisons
+       passedictprog = prog != NULL ? PRVM_EDICT_TO_PROG(passedict) : 0;
+       // figure out whether this is a point trace for comparisons
+       pointtrace = VectorCompare(clipmins, clipmaxs);
+       // precalculate passedict's owner edict pointer for comparisons
+       traceowner = passedict ? PRVM_PROG_TO_EDICT(passedict->fields.client->owner) : 0;
+
+       // collide against network entities
+       if (hitnetworkbrushmodels)
+       {
+               for (i = 0;i < cl.num_brushmodel_entities;i++)
+               {
+                       entity_render_t *ent = &cl.entities[cl.brushmodel_entities[i]].render;
+                       if (!BoxesOverlap(clipboxmins, clipboxmaxs, ent->mins, ent->maxs))
+                               continue;
+                       Collision_ClipToGenericEntity(&trace, ent->model, ent->frame, vec3_origin, vec3_origin, 0, &ent->matrix, &ent->inversematrix, start, mins, maxs, end, hitsupercontentsmask);
+                       if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                               *hitnetworkentity = cl.brushmodel_entities[i];
+                       Collision_CombineTraces(&cliptrace, &trace, NULL, true);
+               }
+       }
+
+       // collide against player entities
+       if (hitnetworkplayers)
+       {
+               vec3_t origin, entmins, entmaxs;
+               matrix4x4_t entmatrix, entinversematrix;
+               for (i = 1;i < cl.maxclients+1;i++)
+               {
+                       entity_render_t *ent = &cl.entities[i].render;
+                       // don't hit ourselves
+                       if (i == cl.playerentity)
+                               continue;
+                       Matrix4x4_OriginFromMatrix(&ent->matrix, origin);
+                       VectorAdd(origin, cl.playerstandmins, entmins);
+                       VectorAdd(origin, cl.playerstandmaxs, entmaxs);
+                       if (!BoxesOverlap(clipboxmins, clipboxmaxs, entmins, entmaxs))
+                               continue;
+                       Matrix4x4_CreateTranslate(&entmatrix, origin[0], origin[1], origin[2]);
+                       Matrix4x4_CreateTranslate(&entinversematrix, -origin[0], -origin[1], -origin[2]);
+                       Collision_ClipToGenericEntity(&trace, NULL, 0, cl.playerstandmins, cl.playerstandmaxs, SUPERCONTENTS_BODY, &entmatrix, &entinversematrix, start, mins, maxs, end, hitsupercontentsmask);
+                       if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                               *hitnetworkentity = i;
+                       Collision_CombineTraces(&cliptrace, &trace, NULL, false);
+               }
+       }
+
+       // clip to entities
+       // because this uses World_EntitiestoBox, we know all entity boxes overlap
+       // the clip region, so we can skip culling checks in the loop below
+       // note: if prog is NULL then there won't be any linked entities
+       numtouchedicts = 0;
+       if (hitcsqcentities && prog != NULL)
+       {
+               numtouchedicts = World_EntitiesInBox(&cl.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
+               if (numtouchedicts > MAX_EDICTS)
+               {
+                       // this never happens
+                       Con_Printf("CL_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
+                       numtouchedicts = MAX_EDICTS;
+               }
+       }
+       for (i = 0;i < numtouchedicts;i++)
+       {
+               touch = touchedicts[i];
+
+               if (touch->fields.client->solid < SOLID_BBOX)
+                       continue;
+               if (type == MOVE_NOMONSTERS && touch->fields.client->solid != SOLID_BSP)
+                       continue;
+
+               if (passedict)
+               {
+                       // don't clip against self
+                       if (passedict == touch)
+                               continue;
+                       // don't clip owned entities against owner
+                       if (traceowner == touch)
+                               continue;
+                       // don't clip owner against owned entities
+                       if (passedictprog == touch->fields.client->owner)
+                               continue;
+                       // don't clip points against points (they can't collide)
+                       if (pointtrace && VectorCompare(touch->fields.client->mins, touch->fields.client->maxs) && (type != MOVE_MISSILE || !((int)touch->fields.client->flags & FL_MONSTER)))
+                               continue;
+               }
+
+               // might interact, so do an exact clip
+               model = NULL;
+               if ((int) touch->fields.client->solid == SOLID_BSP || type == MOVE_HITMODEL)
+               {
+                       unsigned int modelindex = (unsigned int)touch->fields.client->modelindex;
+                       // if the modelindex is 0, it shouldn't be SOLID_BSP!
+                       if (modelindex > 0 && modelindex < MAX_MODELS)
+                               model = CL_GetModelByIndex((int)touch->fields.client->modelindex);
+                       Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.client->origin[0], touch->fields.client->origin[1], touch->fields.client->origin[2], touch->fields.client->angles[0], touch->fields.client->angles[1], touch->fields.client->angles[2], 1);
+               }
+               else
+                       Matrix4x4_CreateTranslate(&matrix, touch->fields.client->origin[0], touch->fields.client->origin[1], touch->fields.client->origin[2]);
+               Matrix4x4_Invert_Simple(&imatrix, &matrix);
+               if ((int)touch->fields.client->flags & FL_MONSTER)
+                       Collision_ClipToGenericEntity(&trace, model, touch->fields.client->frame, touch->fields.client->mins, touch->fields.client->maxs, SUPERCONTENTS_BODY, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
+               else
+                       Collision_ClipToGenericEntity(&trace, model, touch->fields.client->frame, touch->fields.client->mins, touch->fields.client->maxs, SUPERCONTENTS_BODY, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask);
+               if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                       *hitnetworkentity = 0;
+               Collision_CombineTraces(&cliptrace, &trace, (void *)touch, touch->fields.client->solid == SOLID_BSP);
+       }
+
+       return cliptrace;
+}
index 740ec2a..f6837b7 100644 (file)
@@ -2,9 +2,15 @@
 #ifndef CL_COLLISION_H
 #define CL_COLLISION_H
 
-trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitbmodels, int *hitent, int hitsupercontentsmask, qboolean hitplayers);
 float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, vec3_t normal, int *hitent, entity_render_t *ignoreent);
 void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius);
-int CL_PointSuperContents(const vec3_t p);
+
+model_t *CL_GetModelByIndex(int modelindex);
+model_t *CL_GetModelFromEdict(prvm_edict_t *ed);
+
+void CL_LinkEdict(prvm_edict_t *ent);
+int CL_GenericHitSuperContentsMask(const prvm_edict_t *edict);
+trace_t CL_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities);
+#define CL_PointSuperContents(point) (CL_Move((point), vec3_origin, vec3_origin, (point), sv_gameplayfix_swiminbmodels.integer ? MOVE_NOMONSTERS : MOVE_WORLDONLY, NULL, 0, true, false, NULL, true).startsupercontents)
 
 #endif
index 8bdec9a..59eef71 100644 (file)
@@ -730,7 +730,7 @@ qboolean CL_ClientMovement_Unstick(cl_clientmovement_state_t *s)
        for (i = 0;i < NUMOFFSETS;i++)
        {
                VectorAdd(offsets[i], s->origin, neworigin);
-               if (!CL_TraceBox(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true).startsolid)
+               if (!CL_Move(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false).startsolid)
                {
                        VectorCopy(neworigin, s->origin);
                        return true;
@@ -761,7 +761,7 @@ void CL_ClientMovement_UpdateStatus(cl_clientmovement_state_t *s)
                // low ceiling first
                if (s->crouched)
                {
-                       trace = CL_TraceBox(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true);
+                       trace = CL_Move(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                        if (!trace.startsolid)
                                s->crouched = false;
                }
@@ -780,22 +780,22 @@ void CL_ClientMovement_UpdateStatus(cl_clientmovement_state_t *s)
        // set onground
        VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + 1);
        VectorSet(origin2, s->origin[0], s->origin[1], s->origin[2] - 2);
-       trace = CL_TraceBox(origin1, s->mins, s->maxs, origin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true);
+       trace = CL_Move(origin1, s->mins, s->maxs, origin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
        s->onground = trace.fraction < 1 && trace.plane.normal[2] > 0.7 && s->velocity[2] < cl_gravity.value * s->q.frametime;
 
        // set watertype/waterlevel
        VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + s->mins[2] + 1);
        s->waterlevel = WATERLEVEL_NONE;
-       s->watertype = CL_TraceBox(origin1, vec3_origin, vec3_origin, origin1, true, NULL, 0, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK;
+       s->watertype = CL_Move(origin1, vec3_origin, vec3_origin, origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK;
        if (s->watertype)
        {
                s->waterlevel = WATERLEVEL_WETFEET;
                origin1[2] = s->origin[2] + (s->mins[2] + s->maxs[2]) * 0.5f;
-               if (CL_TraceBox(origin1, vec3_origin, vec3_origin, origin1, true, NULL, 0, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
+               if (CL_Move(origin1, vec3_origin, vec3_origin, origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
                {
                        s->waterlevel = WATERLEVEL_SWIMMING;
                        origin1[2] = s->origin[2] + 22;
-                       if (CL_TraceBox(origin1, vec3_origin, vec3_origin, origin1, true, NULL, 0, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
+                       if (CL_Move(origin1, vec3_origin, vec3_origin, origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
                                s->waterlevel = WATERLEVEL_SUBMERGED;
                }
        }
@@ -822,20 +822,20 @@ void CL_ClientMovement_Move(cl_clientmovement_state_t *s)
        for (bump = 0, t = s->q.frametime;bump < 8 && VectorLength2(s->velocity) > 0;bump++)
        {
                VectorMA(s->origin, t, s->velocity, neworigin);
-               trace = CL_TraceBox(s->origin, s->mins, s->maxs, neworigin, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true);
+               trace = CL_Move(s->origin, s->mins, s->maxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                if (trace.fraction < 1 && trace.plane.normal[2] == 0)
                {
                        // may be a step or wall, try stepping up
                        // first move forward at a higher level
                        VectorSet(currentorigin2, s->origin[0], s->origin[1], s->origin[2] + s->movevars_stepheight);
                        VectorSet(neworigin2, neworigin[0], neworigin[1], s->origin[2] + s->movevars_stepheight);
-                       trace2 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true);
+                       trace2 = CL_Move(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                        if (!trace2.startsolid)
                        {
                                // then move down from there
                                VectorCopy(trace2.endpos, currentorigin2);
                                VectorSet(neworigin2, trace2.endpos[0], trace2.endpos[1], s->origin[2]);
-                               trace3 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true);
+                               trace3 = CL_Move(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                                //Con_Printf("%f %f %f %f : %f %f %f %f : %f %f %f %f\n", trace.fraction, trace.endpos[0], trace.endpos[1], trace.endpos[2], trace2.fraction, trace2.endpos[0], trace2.endpos[1], trace2.endpos[2], trace3.fraction, trace3.endpos[0], trace3.endpos[1], trace3.endpos[2]);
                                // accept the new trace if it made some progress
                                if (fabs(trace3.endpos[0] - trace.endpos[0]) >= 0.03125 || fabs(trace3.endpos[1] - trace.endpos[1]) >= 0.03125)
@@ -885,10 +885,10 @@ void CL_ClientMovement_Physics_Swim(cl_clientmovement_state_t *s)
                AngleVectors(yawangles, forward, NULL, NULL);
                VectorMA(s->origin, 24, forward, spot);
                spot[2] += 8;
-               if (CL_TraceBox(spot, vec3_origin, vec3_origin, spot, true, NULL, 0, false).startsolid)
+               if (CL_Move(spot, vec3_origin, vec3_origin, spot, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsolid)
                {
                        spot[2] += 24;
-                       if (!CL_TraceBox(spot, vec3_origin, vec3_origin, spot, true, NULL, 0, false).startsolid)
+                       if (!CL_Move(spot, vec3_origin, vec3_origin, spot, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsolid)
                        {
                                VectorScale(forward, 50, s->velocity);
                                s->velocity[2] = 310;
@@ -1017,9 +1017,9 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
                        VectorSet(neworigin2, s->origin[0] + s->velocity[0]*(16/f), s->origin[1] + s->velocity[1]*(16/f), s->origin[2] + s->mins[2]);
                        VectorSet(neworigin3, neworigin2[0], neworigin2[1], neworigin2[2] - 34);
                        if (cls.protocol == PROTOCOL_QUAKEWORLD)
-                               trace = CL_TraceBox(neworigin2, s->mins, s->maxs, neworigin3, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true);
+                               trace = CL_Move(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                        else
-                               trace = CL_TraceBox(neworigin2, vec3_origin, vec3_origin, neworigin3, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true);
+                               trace = CL_Move(neworigin2, vec3_origin, vec3_origin, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                        if (trace.fraction == 1 && !trace.startsolid)
                                friction *= s->movevars_edgefriction;
                }
index 05a36f5..f362053 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -1230,7 +1230,7 @@ void CL_LinkNetworkEntity(entity_t *e)
                trace_t trace;
                matrix4x4_t tempmatrix;
                Matrix4x4_Transform(&e->render.matrix, muzzleflashorigin, v2);
-               trace = CL_TraceBox(origin, vec3_origin, vec3_origin, v2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, false);
+               trace = CL_Move(origin, vec3_origin, vec3_origin, v2, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, true, false, NULL, false);
                Matrix4x4_Normalize(&tempmatrix, &e->render.matrix);
                Matrix4x4_SetOrigin(&tempmatrix, trace.endpos[0], trace.endpos[1], trace.endpos[2]);
                Matrix4x4_Scale(&tempmatrix, 150, 1);
index 8b80cad..d658b7b 100644 (file)
@@ -521,7 +521,7 @@ void CL_SpawnDecalParticleForPoint(const vec3_t org, float maxdist, float size,
        {
                VectorRandom(org2);
                VectorMA(org, maxdist, org2, org2);
-               trace = CL_TraceBox(org, vec3_origin, vec3_origin, org2, true, &hitent, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, false);
+               trace = CL_Move(org, vec3_origin, vec3_origin, org2, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, true, false, &hitent, false);
                // take the closest trace result that doesn't end up hitting a NOMARKS
                // surface (sky for example)
                if (bestfrac > trace.fraction && !(trace.hitq3surfaceflags & Q3SURFACEFLAG_NOMARKS))
@@ -1324,7 +1324,7 @@ void CL_ParticleExplosion (const vec3_t org)
                                                v[0] = org[0] + lhrandom(-48, 48);
                                                v[1] = org[1] + lhrandom(-48, 48);
                                                v[2] = org[2] + lhrandom(-48, 48);
-                                               trace = CL_TraceBox(org, vec3_origin, vec3_origin, v, true, NULL, SUPERCONTENTS_SOLID, false);
+                                               trace = CL_Move(org, vec3_origin, vec3_origin, v, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false);
                                                if (trace.fraction >= 0.1)
                                                        break;
                                        }
@@ -1534,7 +1534,7 @@ void CL_MoveParticles (void)
                        VectorCopy(p->org, org);
                        if (p->bounce)
                        {
-                               trace = CL_TraceBox(oldorg, vec3_origin, vec3_origin, p->org, true, &hitent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | (p->type == particletype + pt_rain ? SUPERCONTENTS_LIQUIDSMASK : 0), false);
+                               trace = CL_Move(oldorg, vec3_origin, vec3_origin, p->org, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | (p->type == particletype + pt_rain ? SUPERCONTENTS_LIQUIDSMASK : 0), true, false, &hitent, false);
                                // if the trace started in or hit something of SUPERCONTENTS_NODROP
                                // or if the trace hit something flagged as NOIMPACT
                                // then remove the particle
index 21626ad..43ca54a 100644 (file)
 //4 feature darkplaces csqc: add builtins to clientside qc for gl calls
 
 sfx_t *S_FindName(const char *name);
-void PF_registercvar (void);
 int Sbar_GetPlayer (int index);
 void Sbar_SortFrags (void);
 void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius);
 void CSQC_RelinkAllEntities (int drawmask);
 void CSQC_RelinkCSQCEntities (void);
 char *Key_GetBind (int key);
-model_t *CSQC_GetModelByIndex(int modelindex);
-model_t *CSQC_GetModelFromEntity(prvm_edict_t *ed);
-void CL_LinkEdict(prvm_edict_t *ed);
 
 
 
@@ -34,17 +30,18 @@ void CL_LinkEdict(prvm_edict_t *ed);
 
 
 // #1 void(vector ang) makevectors
-void VM_CL_makevectors (void)
+static void VM_CL_makevectors (void)
 {
        VM_SAFEPARMCOUNT(1, VM_CL_makevectors);
        AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up);
 }
 
 // #2 void(entity e, vector o) setorigin
-void VM_CL_setorigin (void)
+static void VM_CL_setorigin (void)
 {
        prvm_edict_t    *e;
        float   *org;
+       VM_SAFEPARMCOUNT(2, VM_CL_setorigin);
 
        e = PRVM_G_EDICT(OFS_PARM0);
        if (e == prog->edicts)
@@ -63,7 +60,7 @@ void VM_CL_setorigin (void)
 }
 
 // #3 void(entity e, string m) setmodel
-void VM_CL_setmodel (void)
+static void VM_CL_setmodel (void)
 {
        prvm_edict_t    *e;
        const char              *m;
@@ -100,7 +97,7 @@ void VM_CL_setmodel (void)
 }
 
 // #4 void(entity e, vector min, vector max) setsize
-void VM_CL_setsize (void)
+static void VM_CL_setsize (void)
 {
        prvm_edict_t    *e;
        float                   *min, *max;
@@ -127,8 +124,8 @@ void VM_CL_setsize (void)
        CL_LinkEdict(e);
 }
 
-// #8 void(entity e, float chan, string samp) sound
-void VM_CL_sound (void)
+// #8 void(entity e, float chan, string samp, float volume, float atten) sound
+static void VM_CL_sound (void)
 {
        const char                      *sample;
        int                                     channel;
@@ -166,7 +163,7 @@ void VM_CL_sound (void)
 }
 
 // #14 entity() spawn
-void VM_CL_spawn (void)
+static void VM_CL_spawn (void)
 {
        prvm_edict_t *ed;
        ed = PRVM_ED_Alloc();
@@ -174,41 +171,141 @@ void VM_CL_spawn (void)
        VM_RETURN_EDICT(ed);
 }
 
-// #16 float(vector v1, vector v2, float tryents) traceline
-void VM_CL_traceline (void)
+// #16 float(vector v1, vector v2, float movetype, entity ignore) traceline
+static void VM_CL_traceline (void)
 {
        float   *v1, *v2;
        trace_t trace;
-       int             ent;
+       int             move;
+       prvm_edict_t    *ent;
+
+       VM_SAFEPARMCOUNTRANGE(4, 8, VM_CL_traceline); // allow more parameters for future expansion
+
+       prog->xfunction->builtinsprofile += 30;
 
        v1 = PRVM_G_VECTOR(OFS_PARM0);
        v2 = PRVM_G_VECTOR(OFS_PARM1);
+       move = (int)PRVM_G_FLOAT(OFS_PARM2);
+       ent = PRVM_G_EDICT(OFS_PARM3);
+
+       if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
+               PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
+
+       trace = CL_Move(v1, vec3_origin, vec3_origin, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+
+       VM_SetTraceGlobals(&trace);
+}
+
+/*
+=================
+VM_CL_tracebox
+
+Used for use tracing and shot targeting
+Traces are blocked by bbox and exact bsp entityes, and also slide box entities
+if the tryents flag is set.
+
+tracebox (vector1, vector mins, vector maxs, vector2, tryents)
+=================
+*/
+// LordHavoc: added this for my own use, VERY useful, similar to traceline
+static void VM_CL_tracebox (void)
+{
+       float   *v1, *v2, *m1, *m2;
+       trace_t trace;
+       int             move;
+       prvm_edict_t    *ent;
+
+       VM_SAFEPARMCOUNTRANGE(6, 8, VM_CL_tracebox); // allow more parameters for future expansion
+
+       prog->xfunction->builtinsprofile += 30;
+
+       v1 = PRVM_G_VECTOR(OFS_PARM0);
+       m1 = PRVM_G_VECTOR(OFS_PARM1);
+       m2 = PRVM_G_VECTOR(OFS_PARM2);
+       v2 = PRVM_G_VECTOR(OFS_PARM3);
+       move = (int)PRVM_G_FLOAT(OFS_PARM4);
+       ent = PRVM_G_EDICT(OFS_PARM5);
+
+       if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
+               PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
 
-       trace = CL_TraceBox(v1, vec3_origin, vec3_origin, v2, 1, &ent, 1, false);
-
-       prog->globals.client->trace_allsolid = trace.allsolid;
-       prog->globals.client->trace_startsolid = trace.startsolid;
-       prog->globals.client->trace_fraction = trace.fraction;
-       prog->globals.client->trace_inwater = trace.inwater;
-       prog->globals.client->trace_inopen = trace.inopen;
-       VectorCopy (trace.endpos, prog->globals.client->trace_endpos);
-       VectorCopy (trace.plane.normal, prog->globals.client->trace_plane_normal);
-       prog->globals.client->trace_plane_dist =  trace.plane.dist;
-       if (ent)
-               prog->globals.client->trace_ent = ent;
+       trace = CL_Move(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+
+       VM_SetTraceGlobals(&trace);
+}
+
+extern cvar_t cl_gravity;
+trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
+{
+       int i;
+       float gravity;
+       vec3_t move, end;
+       vec3_t original_origin;
+       vec3_t original_velocity;
+       vec3_t original_angles;
+       vec3_t original_avelocity;
+       prvm_eval_t *val;
+       trace_t trace;
+
+       VectorCopy(tossent->fields.client->origin   , original_origin   );
+       VectorCopy(tossent->fields.client->velocity , original_velocity );
+       VectorCopy(tossent->fields.client->angles   , original_angles   );
+       VectorCopy(tossent->fields.client->avelocity, original_avelocity);
+
+       val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
+       if (val != NULL && val->_float != 0)
+               gravity = val->_float;
        else
-               prog->globals.client->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
+               gravity = 1.0;
+       gravity *= cl_gravity.value * 0.05;
+
+       for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
+       {
+               tossent->fields.client->velocity[2] -= gravity;
+               VectorMA (tossent->fields.client->angles, 0.05, tossent->fields.client->avelocity, tossent->fields.client->angles);
+               VectorScale (tossent->fields.client->velocity, 0.05, move);
+               VectorAdd (tossent->fields.client->origin, move, end);
+               trace = CL_Move (tossent->fields.client->origin, tossent->fields.client->mins, tossent->fields.client->maxs, end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), true, true, NULL, true);
+               VectorCopy (trace.endpos, tossent->fields.client->origin);
+
+               if (trace.fraction < 1)
+                       break;
+       }
+
+       VectorCopy(original_origin   , tossent->fields.client->origin   );
+       VectorCopy(original_velocity , tossent->fields.client->velocity );
+       VectorCopy(original_angles   , tossent->fields.client->angles   );
+       VectorCopy(original_avelocity, tossent->fields.client->avelocity);
+
+       return trace;
 }
 
-// #19 void(string s) precache_sound
-void VM_CL_precache_sound (void)
+static void VM_CL_tracetoss (void)
 {
-       VM_SAFEPARMCOUNT(1, VM_CL_precache_sound);
-       S_PrecacheSound(PRVM_G_STRING(OFS_PARM0), true, false);
+       trace_t trace;
+       prvm_edict_t    *ent;
+       prvm_edict_t    *ignore;
+
+       prog->xfunction->builtinsprofile += 600;
+
+       VM_SAFEPARMCOUNT(2, VM_CL_tracetoss);
+
+       ent = PRVM_G_EDICT(OFS_PARM0);
+       if (ent == prog->edicts)
+       {
+               VM_Warning("tracetoss: can not use world entity\n");
+               return;
+       }
+       ignore = PRVM_G_EDICT(OFS_PARM1);
+
+       trace = CL_Trace_Toss (ent, ignore);
+
+       VM_SetTraceGlobals(&trace);
 }
 
+
 // #20 void(string s) precache_model
-void VM_CL_precache_model (void)
+static void VM_CL_precache_model (void)
 {
        const char      *name;
        int                     i;
@@ -263,7 +360,7 @@ int CSQC_EntitiesInBox (vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **li
 }
 
 // #22 entity(vector org, float rad) findradius
-void VM_CL_findradius (void)
+static void VM_CL_findradius (void)
 {
        prvm_edict_t    *ent, *chain;
        vec_t                   radius, radius2;
@@ -271,6 +368,8 @@ void VM_CL_findradius (void)
        int                             i, numtouchedicts;
        prvm_edict_t    *touchedicts[MAX_EDICTS];
 
+       VM_SAFEPARMCOUNT(2, VM_CL_findradius);
+
        chain = (prvm_edict_t *)prog->edicts;
 
        VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
@@ -320,12 +419,14 @@ void VM_CL_findradius (void)
 }
 
 // #34 float() droptofloor
-void VM_CL_droptofloor (void)
+static void VM_CL_droptofloor (void)
 {
        prvm_edict_t            *ent;
+       prvm_eval_t                     *val;
        vec3_t                          end;
        trace_t                         trace;
-       int                                     i;
+
+       VM_SAFEPARMCOUNTRANGE(0, 2, VM_CL_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
 
        // assume failure if it returns early
        PRVM_G_FLOAT(OFS_RETURN) = 0;
@@ -345,13 +446,14 @@ void VM_CL_droptofloor (void)
        VectorCopy (ent->fields.client->origin, end);
        end[2] -= 256;
 
-       trace = CL_TraceBox(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, 1, &i, 1, false);
+       trace = CL_Move(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
 
        if (trace.fraction != 1)
        {
                VectorCopy (trace.endpos, ent->fields.client->origin);
                ent->fields.client->flags = (int)ent->fields.client->flags | FL_ONGROUND;
-//             ent->fields.client->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
+               if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.groundentity)))
+                       val->edict = PRVM_EDICT_TO_PROG(trace.ent);
                PRVM_G_FLOAT(OFS_RETURN) = 1;
                // if support is destroyed, keep suspended (gross hack for floating items in various maps)
 //             ent->priv.server->suspendedinairflag = true;
@@ -359,7 +461,7 @@ void VM_CL_droptofloor (void)
 }
 
 // #35 void(float style, string value) lightstyle
-void VM_CL_lightstyle (void)
+static void VM_CL_lightstyle (void)
 {
        int                     i;
        const char      *c;
@@ -379,13 +481,13 @@ void VM_CL_lightstyle (void)
 }
 
 // #40 float(entity e) checkbottom
-void VM_CL_checkbottom (void)
+static void VM_CL_checkbottom (void)
 {
        static int              cs_yes, cs_no;
        prvm_edict_t    *ent;
        vec3_t                  mins, maxs, start, stop;
        trace_t                 trace;
-       int                             x, y, hit;
+       int                             x, y;
        float                   mid, bottom;
 
        VM_SAFEPARMCOUNT(1, VM_CL_checkbottom);
@@ -423,7 +525,7 @@ realcheck:
        start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
        start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
        stop[2] = start[2] - 2*sv_stepheight.value;
-       trace = CL_TraceBox (start, vec3_origin, vec3_origin, stop, 1, &hit, 1, true);
+       trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
 
        if (trace.fraction == 1.0)
                return;
@@ -437,7 +539,7 @@ realcheck:
                        start[0] = stop[0] = x ? maxs[0] : mins[0];
                        start[1] = stop[1] = y ? maxs[1] : mins[1];
 
-                       trace = CL_TraceBox (start, vec3_origin, vec3_origin, stop, 1, &hit, 1, true);
+                       trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
 
                        if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
                                bottom = trace.endpos[2];
@@ -450,14 +552,14 @@ realcheck:
 }
 
 // #41 float(vector v) pointcontents
-void VM_CL_pointcontents (void)
+static void VM_CL_pointcontents (void)
 {
        VM_SAFEPARMCOUNT(1, VM_CL_pointcontents);
        PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, CL_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
 }
 
 // #48 void(vector o, vector d, float color, float count) particle
-void VM_CL_particle (void)
+static void VM_CL_particle (void)
 {
        float   *org, *dir;
        int             count;
@@ -471,41 +573,8 @@ void VM_CL_particle (void)
        CL_ParticleEffect(EFFECT_SVC_PARTICLE, count, org, org, dir, dir, NULL, color);
 }
 
-// #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
-void VM_CL_tracetoss (void)
-{
-/*     trace_t trace;
-       prvm_edict_t    *ent;
-       prvm_edict_t    *ignore;
-
-       ent = PRVM_G_EDICT(OFS_PARM0);
-       if (ent == prog->edicts)
-       {
-               VM_Warning("tracetoss: can not use world entity\n");
-               return;
-       }
-       ignore = PRVM_G_EDICT(OFS_PARM1);
-
-//FIXME
-       trace = SV_Trace_Toss (ent, ignore);
-
-       prog->globals.server->trace_allsolid = trace.allsolid;
-       prog->globals.server->trace_startsolid = trace.startsolid;
-       prog->globals.server->trace_fraction = trace.fraction;
-       prog->globals.server->trace_inwater = trace.inwater;
-       prog->globals.server->trace_inopen = trace.inopen;
-       VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
-       VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
-       prog->globals.server->trace_plane_dist =  trace.plane.dist;
-       if (trace.ent)
-               prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
-       else
-               prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
-*/
-}
-
 // #74 void(vector pos, string samp, float vol, float atten) ambientsound
-void VM_CL_ambientsound (void)
+static void VM_CL_ambientsound (void)
 {
        float   *f;
        sfx_t   *s;
@@ -515,36 +584,8 @@ void VM_CL_ambientsound (void)
        S_StaticSound (s, f, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3)*64);
 }
 
-// #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
-void VM_CL_tracebox (void)
-{
-       float   *v1, *v2, *m1, *m2;
-       trace_t trace;
-       int             ent;
-
-       v1 = PRVM_G_VECTOR(OFS_PARM0);
-       m1 = PRVM_G_VECTOR(OFS_PARM1);
-       m2 = PRVM_G_VECTOR(OFS_PARM2);
-       v2 = PRVM_G_VECTOR(OFS_PARM3);
-
-       trace = CL_TraceBox(v1, m1, m2, v2, 1, &ent, 1, false);
-
-       prog->globals.client->trace_allsolid = trace.allsolid;
-       prog->globals.client->trace_startsolid = trace.startsolid;
-       prog->globals.client->trace_fraction = trace.fraction;
-       prog->globals.client->trace_inwater = trace.inwater;
-       prog->globals.client->trace_inopen = trace.inopen;
-       VectorCopy (trace.endpos, prog->globals.client->trace_endpos);
-       VectorCopy (trace.plane.normal, prog->globals.client->trace_plane_normal);
-       prog->globals.client->trace_plane_dist =  trace.plane.dist;
-       if (ent)
-               prog->globals.client->trace_ent = ent;
-       else
-               prog->globals.client->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
-}
-
 // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
-void VM_CL_getlight (void)
+static void VM_CL_getlight (void)
 {
        vec3_t ambientcolor, diffusecolor, diffusenormal;
        vec_t *p;
@@ -577,9 +618,9 @@ static void CSQC_R_RecalcView (void)
 
 void CL_RelinkLightFlashes(void);
 //#300 void() clearscene (EXT_CSQC)
-void VM_R_ClearScene (void)
+static void VM_CL_R_ClearScene (void)
 {
-       VM_SAFEPARMCOUNT(0, VM_R_ClearScene);
+       VM_SAFEPARMCOUNT(0, VM_CL_R_ClearScene);
        // clear renderable entity and light lists
        r_refdef.numentities = 0;
        r_refdef.numlights = 0;
@@ -588,11 +629,11 @@ void VM_R_ClearScene (void)
 //#301 void(float mask) addentities (EXT_CSQC)
 extern void CSQC_Predraw (prvm_edict_t *ed);//csprogs.c
 extern void CSQC_Think (prvm_edict_t *ed);//csprogs.c
-void VM_R_AddEntities (void)
+static void VM_CL_R_AddEntities (void)
 {
        int                     i, drawmask;
        prvm_edict_t *ed;
-       VM_SAFEPARMCOUNT(1, VM_R_AddEntities);
+       VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntities);
        drawmask = (int)PRVM_G_FLOAT(OFS_PARM0);
        CSQC_RelinkAllEntities(drawmask);
        CL_RelinkLightFlashes();
@@ -619,21 +660,20 @@ void VM_R_AddEntities (void)
 }
 
 //#302 void(entity ent) addentity (EXT_CSQC)
-void VM_R_AddEntity (void)
+static void VM_CL_R_AddEntity (void)
 {
-       VM_SAFEPARMCOUNT(1, VM_R_AddEntity);
+       VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntity);
        CSQC_AddRenderEdict(PRVM_G_EDICT(OFS_PARM0));
 }
 
 //#303 float(float property, ...) setproperty (EXT_CSQC)
-void VM_R_SetView (void)
+static void VM_CL_R_SetView (void)
 {
        int             c;
        float   *f;
        float   k;
 
-       if(prog->argc < 2)
-               VM_SAFEPARMCOUNT(2, VM_R_SetView);
+       VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_R_SetView);
 
        c = (int)PRVM_G_FLOAT(OFS_PARM0);
        f = PRVM_G_VECTOR(OFS_PARM1);
@@ -712,7 +752,7 @@ void VM_R_SetView (void)
                                                        break;
 
        default:                                PRVM_G_FLOAT(OFS_RETURN) = 0;
-                                                       VM_Warning("VM_R_SetView : unknown parm %i\n", c);
+                                                       VM_Warning("VM_CL_R_SetView : unknown parm %i\n", c);
                                                        return;
        }
        PRVM_G_FLOAT(OFS_RETURN) = 1;
@@ -720,10 +760,10 @@ void VM_R_SetView (void)
 
 extern void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit);
 //#304 void() renderscene (EXT_CSQC)
-void VM_R_RenderScene (void) //#134
+static void VM_CL_R_RenderScene (void)
 {
        int i;
-       VM_SAFEPARMCOUNT(0, VM_R_RenderScene);
+       VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene);
        // we need to update any RENDER_VIEWMODEL entities at this point because
        // csqc supplies its own view matrix
        for (i = 1;i < cl.num_entities;i++)
@@ -742,11 +782,11 @@ void VM_R_RenderScene (void) //#134
 }
 
 //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
-void VM_R_AddDynamicLight (void)
+static void VM_CL_R_AddDynamicLight (void)
 {
        float           *pos, *col;
        matrix4x4_t     matrix;
-       VM_SAFEPARMCOUNT(3, VM_R_AddDynamicLight);
+       VM_SAFEPARMCOUNTRANGE(3, 8, VM_CL_R_AddDynamicLight); // allow more than 3 because we may extend this in the future
 
        // if we've run out of dlights, just return
        if (r_refdef.numlights >= MAX_DLIGHTS)
@@ -761,7 +801,7 @@ void VM_R_AddDynamicLight (void)
 //============================================================================
 
 //#310 vector (vector v) cs_unproject (EXT_CSQC)
-void VM_CL_unproject (void)
+static void VM_CL_unproject (void)
 {
        float   *f;
        vec3_t  temp;
@@ -773,7 +813,7 @@ void VM_CL_unproject (void)
 }
 
 //#311 vector (vector v) cs_project (EXT_CSQC)
-void VM_CL_project (void)
+static void VM_CL_project (void)
 {
        float   *f;
        vec3_t  v;
@@ -787,7 +827,7 @@ void VM_CL_project (void)
 }
 
 //#330 float(float stnum) getstatf (EXT_CSQC)
-void VM_CL_getstatf (void)
+static void VM_CL_getstatf (void)
 {
        int i;
        union
@@ -807,7 +847,7 @@ void VM_CL_getstatf (void)
 }
 
 //#331 float(float stnum) getstati (EXT_CSQC)
-void VM_CL_getstati (void)
+static void VM_CL_getstati (void)
 {
        int i, index;
        VM_SAFEPARMCOUNT(1, VM_CL_getstati);
@@ -823,7 +863,7 @@ void VM_CL_getstati (void)
 }
 
 //#332 string(float firststnum) getstats (EXT_CSQC)
-void VM_CL_getstats (void)
+static void VM_CL_getstats (void)
 {
        int i;
        char t[17];
@@ -840,7 +880,7 @@ void VM_CL_getstats (void)
 }
 
 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
-void VM_CL_setmodelindex (void)
+static void VM_CL_setmodelindex (void)
 {
        int                             i;
        prvm_edict_t    *t;
@@ -858,7 +898,7 @@ void VM_CL_setmodelindex (void)
        if (!i)
                return;
 
-       model = CSQC_GetModelByIndex(i);
+       model = CL_GetModelByIndex(i);
        if (!model)
        {
                VM_Warning("VM_CL_setmodelindex: null model\n");
@@ -869,19 +909,19 @@ void VM_CL_setmodelindex (void)
 }
 
 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
-void VM_CL_modelnameforindex (void)
+static void VM_CL_modelnameforindex (void)
 {
        model_t *model;
 
        VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex);
 
        PRVM_G_INT(OFS_RETURN) = OFS_NULL;
-       model = CSQC_GetModelByIndex((int)PRVM_G_FLOAT(OFS_PARM0));
+       model = CL_GetModelByIndex((int)PRVM_G_FLOAT(OFS_PARM0));
        PRVM_G_INT(OFS_RETURN) = model ? PRVM_SetEngineString(model->name) : 0;
 }
 
 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
-void VM_CL_particleeffectnum (void)
+static void VM_CL_particleeffectnum (void)
 {
        int                     i;
        VM_SAFEPARMCOUNT(1, VM_CL_particleeffectnum);
@@ -892,53 +932,43 @@ void VM_CL_particleeffectnum (void)
 }
 
 // #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC)
-void VM_CL_trailparticles (void)
+static void VM_CL_trailparticles (void)
 {
        int                             i;
        float                   *start, *end;
        prvm_edict_t    *t;
-       VM_SAFEPARMCOUNT(4, VM_CL_trailparticles);
+       VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_trailparticles);
 
        t = PRVM_G_EDICT(OFS_PARM0);
        i               = (int)PRVM_G_FLOAT(OFS_PARM1);
        start   = PRVM_G_VECTOR(OFS_PARM2);
        end             = PRVM_G_VECTOR(OFS_PARM3);
 
-       CL_ParticleEffect(i, VectorDistance(start, end), start, end, t->fields.client->velocity, t->fields.client->velocity, NULL, (int)PRVM_G_FLOAT(OFS_PARM4));
+       CL_ParticleEffect(i, VectorDistance(start, end), start, end, t->fields.client->velocity, t->fields.client->velocity, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0);
 }
 
-//#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
-void VM_CL_pointparticles (void)
+//#337 void(float effectnum, vector origin, vector dir, float count[, float color]) pointparticles (EXT_CSQC)
+static void VM_CL_pointparticles (void)
 {
        int                     i, n;
        float           *f, *v;
-       VM_SAFEPARMCOUNT(4, VM_CL_pointparticles);
+       VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_pointparticles);
        i = (int)PRVM_G_FLOAT(OFS_PARM0);
        f = PRVM_G_VECTOR(OFS_PARM1);
        v = PRVM_G_VECTOR(OFS_PARM2);
        n = (int)PRVM_G_FLOAT(OFS_PARM3);
-       CL_ParticleEffect(i, n, f, f, v, v, NULL, 0);
-}
-
-//#338 void(string s) cprint (EXT_CSQC)
-void VM_CL_centerprint (void)
-{
-       char s[VM_STRINGTEMP_LENGTH];
-       if(prog->argc < 1)
-               VM_SAFEPARMCOUNT(1, VM_CL_centerprint);
-       VM_VarString(0, s, sizeof(s));
-       SCR_CenterPrint(s);
+       CL_ParticleEffect(i, n, f, f, v, v, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0);
 }
 
 //#342 string(float keynum) getkeybind (EXT_CSQC)
-void VM_CL_getkeybind (void)
+static void VM_CL_getkeybind (void)
 {
        VM_SAFEPARMCOUNT(1, VM_CL_getkeybind);
        PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0)));
 }
 
 //#343 void(float usecursor) setcursormode (EXT_CSQC)
-void VM_CL_setcursormode (void)
+static void VM_CL_setcursormode (void)
 {
        VM_SAFEPARMCOUNT(1, VM_CL_setcursormode);
        cl.csqc_wantsmousemove = PRVM_G_FLOAT(OFS_PARM0);
@@ -946,7 +976,7 @@ void VM_CL_setcursormode (void)
 }
 
 //#345 float(float framenum) getinputstate (EXT_CSQC)
-void VM_CL_getinputstate (void)
+static void VM_CL_getinputstate (void)
 {
        int i, frame;
        VM_SAFEPARMCOUNT(1, VM_CL_getinputstate);
@@ -972,19 +1002,19 @@ void VM_CL_getinputstate (void)
 }
 
 //#346 void(float sens) setsensitivityscaler (EXT_CSQC)
-void VM_CL_setsensitivityscale (void)
+static void VM_CL_setsensitivityscale (void)
 {
        VM_SAFEPARMCOUNT(1, VM_CL_setsensitivityscale);
        cl.sensitivityscale = PRVM_G_FLOAT(OFS_PARM0);
 }
 
 //#347 void() runstandardplayerphysics (EXT_CSQC)
-void VM_CL_runplayerphysics (void)
+static void VM_CL_runplayerphysics (void)
 {
 }
 
 //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
-void VM_CL_getplayerkey (void)
+static void VM_CL_getplayerkey (void)
 {
        int                     i;
        char            t[128];
@@ -1032,13 +1062,14 @@ void VM_CL_getplayerkey (void)
 }
 
 //#349 float() isdemo (EXT_CSQC)
-void VM_CL_isdemo (void)
+static void VM_CL_isdemo (void)
 {
+       VM_SAFEPARMCOUNT(0, VM_CL_isdemo);
        PRVM_G_FLOAT(OFS_RETURN) = cls.demoplayback;
 }
 
 //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
-void VM_CL_setlistener (void)
+static void VM_CL_setlistener (void)
 {
        VM_SAFEPARMCOUNT(4, VM_CL_setlistener);
        Matrix4x4_FromVectors(&csqc_listenermatrix, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_VECTOR(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0));
@@ -1046,7 +1077,7 @@ void VM_CL_setlistener (void)
 }
 
 //#352 void(string cmdname) registercommand (EXT_CSQC)
-void VM_CL_registercmd (void)
+static void VM_CL_registercmd (void)
 {
        char *t;
        VM_SAFEPARMCOUNT(1, VM_CL_registercmd);
@@ -1064,84 +1095,190 @@ void VM_CL_registercmd (void)
 
 }
 
-//#354 float() playernum (EXT_CSQC)
-void VM_CL_playernum (void)
-{
-       int i, k;
-
-       VM_SAFEPARMCOUNT(0, VM_CL_playernum);
-
-       for(i=k=0 ; i<cl.maxclients ; i++)
-               if(cl.scores[i].name[0])
-                       k++;
-       PRVM_G_FLOAT(OFS_RETURN) = k;
-}
-
-//#355 float() cl_onground (EXT_CSQC)
-void VM_CL_onground (void)
-{
-       PRVM_G_FLOAT(OFS_RETURN) = cl.onground;
-}
-
 //#360 float() readbyte (EXT_CSQC)
-void VM_CL_ReadByte (void)
+static void VM_CL_ReadByte (void)
 {
+       VM_SAFEPARMCOUNT(0, VM_CL_ReadByte);
        PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadByte();
 }
 
 //#361 float() readchar (EXT_CSQC)
-void VM_CL_ReadChar (void)
+static void VM_CL_ReadChar (void)
 {
+       VM_SAFEPARMCOUNT(0, VM_CL_ReadChar);
        PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadChar();
 }
 
 //#362 float() readshort (EXT_CSQC)
-void VM_CL_ReadShort (void)
+static void VM_CL_ReadShort (void)
 {
+       VM_SAFEPARMCOUNT(0, VM_CL_ReadShort);
        PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadShort();
 }
 
 //#363 float() readlong (EXT_CSQC)
-void VM_CL_ReadLong (void)
+static void VM_CL_ReadLong (void)
 {
+       VM_SAFEPARMCOUNT(0, VM_CL_ReadLong);
        PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadLong();
 }
 
 //#364 float() readcoord (EXT_CSQC)
-void VM_CL_ReadCoord (void)
+static void VM_CL_ReadCoord (void)
 {
+       VM_SAFEPARMCOUNT(0, VM_CL_ReadCoord);
        PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadCoord(cls.protocol);
 }
 
 //#365 float() readangle (EXT_CSQC)
-void VM_CL_ReadAngle (void)
+static void VM_CL_ReadAngle (void)
 {
+       VM_SAFEPARMCOUNT(0, VM_CL_ReadAngle);
        PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadAngle(cls.protocol);
 }
 
 //#366 string() readstring (EXT_CSQC)
-void VM_CL_ReadString (void)
+static void VM_CL_ReadString (void)
 {
+       VM_SAFEPARMCOUNT(0, VM_CL_ReadString);
        PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(MSG_ReadString());
 }
 
 //#367 float() readfloat (EXT_CSQC)
-void VM_CL_ReadFloat (void)
+static void VM_CL_ReadFloat (void)
 {
+       VM_SAFEPARMCOUNT(0, VM_CL_ReadFloat);
        PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadFloat();
 }
 
+//////////////////////////////////////////////////////////
+
+static void VM_CL_makestatic (void)
+{
+       prvm_edict_t *ent;
+
+       VM_SAFEPARMCOUNT(1, VM_CL_makestatic);
+
+       ent = PRVM_G_EDICT(OFS_PARM0);
+       if (ent == prog->edicts)
+       {
+               VM_Warning("makestatic: can not modify world entity\n");
+               return;
+       }
+       if (ent->priv.server->free)
+       {
+               VM_Warning("makestatic: can not modify free entity\n");
+               return;
+       }
+
+       if (cl.num_static_entities < cl.max_static_entities)
+       {
+               int renderflags;
+               prvm_eval_t *val;
+               entity_t *staticent = &cl.static_entities[cl.num_static_entities++];
+
+               // copy it to the current state
+               staticent->render.model = CL_GetModelByIndex((int)ent->fields.client->modelindex);
+               staticent->render.frame = staticent->render.frame1 = staticent->render.frame2 = (int)ent->fields.client->frame;
+               staticent->render.framelerp = 0;
+               // make torchs play out of sync
+               staticent->render.frame1time = staticent->render.frame2time = lhrandom(-10, -1);
+               staticent->render.colormap = (int)ent->fields.client->colormap; // no special coloring
+               staticent->render.skinnum = (int)ent->fields.client->skin;
+               staticent->render.effects = (int)ent->fields.client->effects;
+               staticent->render.alpha = 1;
+               if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.alpha)) && val->_float) staticent->render.alpha = val->_float;
+               staticent->render.scale = 1;
+               if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)) && val->_float) staticent->render.scale = val->_float;
+               if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.colormod)) && VectorLength2(val->vector)) VectorCopy(val->vector, staticent->render.colormod);
+
+               renderflags = 0;
+               if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && val->_float) renderflags = (int)val->_float;
+               if (renderflags & RF_USEAXIS)
+               {
+                       vec3_t left;
+                       VectorNegate(prog->globals.client->v_right, left);
+                       Matrix4x4_FromVectors(&staticent->render.matrix, prog->globals.client->v_forward, left, prog->globals.client->v_up, ent->fields.client->origin);
+                       Matrix4x4_Scale(&staticent->render.matrix, staticent->render.scale, 1);
+               }
+               else
+                       Matrix4x4_CreateFromQuakeEntity(&staticent->render.matrix, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], staticent->render.scale);
+               CL_UpdateRenderEntity(&staticent->render);
+
+               // transparent stuff can't be lit during the opaque stage
+               if (staticent->render.effects & (EF_ADDITIVE | EF_NODEPTHTEST) || staticent->render.alpha < 1)
+                       staticent->render.flags |= RENDER_TRANSPARENT;
+               // double sided rendering mode causes backfaces to be visible
+               // (mostly useful on transparent stuff)
+               if (staticent->render.effects & EF_DOUBLESIDED)
+                       staticent->render.flags |= RENDER_NOCULLFACE;
+               // either fullbright or lit
+               if (!(staticent->render.effects & EF_FULLBRIGHT) && !r_fullbright.integer)
+                       staticent->render.flags |= RENDER_LIGHT;
+               // turn off shadows from transparent objects
+               if (!(staticent->render.effects & EF_NOSHADOW)
+                && !(staticent->render.flags & RENDER_TRANSPARENT))
+                       staticent->render.flags |= RENDER_SHADOW;
+       }
+       else
+               Con_Printf("Too many static entities");
+
+// throw the entity away now
+       PRVM_ED_Free (ent);
+}
+
+//=================================================================//
+
+/*
+=================
+VM_CL_copyentity
+
+copies data from one entity to another
+
+copyentity(src, dst)
+=================
+*/
+static void VM_CL_copyentity (void)
+{
+       prvm_edict_t *in, *out;
+       VM_SAFEPARMCOUNT(2, VM_CL_copyentity);
+       in = PRVM_G_EDICT(OFS_PARM0);
+       if (in == prog->edicts)
+       {
+               VM_Warning("copyentity: can not read world entity\n");
+               return;
+       }
+       if (in->priv.server->free)
+       {
+               VM_Warning("copyentity: can not read free entity\n");
+               return;
+       }
+       out = PRVM_G_EDICT(OFS_PARM1);
+       if (out == prog->edicts)
+       {
+               VM_Warning("copyentity: can not modify world entity\n");
+               return;
+       }
+       if (out->priv.server->free)
+       {
+               VM_Warning("copyentity: can not modify free entity\n");
+               return;
+       }
+       memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
+       CL_LinkEdict(out);
+}
+
 //=================================================================//
 
 // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
-void VM_CL_effect (void)
+static void VM_CL_effect (void)
 {
        VM_SAFEPARMCOUNT(5, VM_CL_effect);
        CL_Effect(PRVM_G_VECTOR(OFS_PARM0), (int)PRVM_G_FLOAT(OFS_PARM1), (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
 }
 
 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
-void VM_CL_te_blood (void)
+static void VM_CL_te_blood (void)
 {
        float   *pos;
        vec3_t  pos2;
@@ -1154,7 +1291,7 @@ void VM_CL_te_blood (void)
 }
 
 // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
-void VM_CL_te_bloodshower (void)
+static void VM_CL_te_bloodshower (void)
 {
        vec_t speed;
        vec3_t vel1, vel2;
@@ -1172,7 +1309,7 @@ void VM_CL_te_bloodshower (void)
 }
 
 // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
-void VM_CL_te_explosionrgb (void)
+static void VM_CL_te_explosionrgb (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1186,28 +1323,28 @@ void VM_CL_te_explosionrgb (void)
 }
 
 // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
-void VM_CL_te_particlecube (void)
+static void VM_CL_te_particlecube (void)
 {
        VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube);
        CL_ParticleCube(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), PRVM_G_FLOAT(OFS_PARM5), PRVM_G_FLOAT(OFS_PARM6));
 }
 
 // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
-void VM_CL_te_particlerain (void)
+static void VM_CL_te_particlerain (void)
 {
        VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain);
        CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 0);
 }
 
 // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
-void VM_CL_te_particlesnow (void)
+static void VM_CL_te_particlesnow (void)
 {
        VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow);
        CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 1);
 }
 
 // #411 void(vector org, vector vel, float howmany) te_spark
-void VM_CL_te_spark (void)
+static void VM_CL_te_spark (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1219,7 +1356,7 @@ void VM_CL_te_spark (void)
 }
 
 // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
-void VM_CL_te_gunshotquad (void)
+static void VM_CL_te_gunshotquad (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1231,7 +1368,7 @@ void VM_CL_te_gunshotquad (void)
 }
 
 // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
-void VM_CL_te_spikequad (void)
+static void VM_CL_te_spikequad (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1252,7 +1389,7 @@ void VM_CL_te_spikequad (void)
 }
 
 // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
-void VM_CL_te_superspikequad (void)
+static void VM_CL_te_superspikequad (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1273,7 +1410,7 @@ void VM_CL_te_superspikequad (void)
 }
 
 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
-void VM_CL_te_explosionquad (void)
+static void VM_CL_te_explosionquad (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1286,7 +1423,7 @@ void VM_CL_te_explosionquad (void)
 }
 
 // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
-void VM_CL_te_smallflash (void)
+static void VM_CL_te_smallflash (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1298,7 +1435,7 @@ void VM_CL_te_smallflash (void)
 }
 
 // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
-void VM_CL_te_customflash (void)
+static void VM_CL_te_customflash (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1312,7 +1449,7 @@ void VM_CL_te_customflash (void)
 }
 
 // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_gunshot (void)
+static void VM_CL_te_gunshot (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1324,7 +1461,7 @@ void VM_CL_te_gunshot (void)
 }
 
 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_spike (void)
+static void VM_CL_te_spike (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1345,7 +1482,7 @@ void VM_CL_te_spike (void)
 }
 
 // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_superspike (void)
+static void VM_CL_te_superspike (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1366,7 +1503,7 @@ void VM_CL_te_superspike (void)
 }
 
 // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_explosion (void)
+static void VM_CL_te_explosion (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1379,7 +1516,7 @@ void VM_CL_te_explosion (void)
 }
 
 // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_tarexplosion (void)
+static void VM_CL_te_tarexplosion (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1392,7 +1529,7 @@ void VM_CL_te_tarexplosion (void)
 }
 
 // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_wizspike (void)
+static void VM_CL_te_wizspike (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1405,7 +1542,7 @@ void VM_CL_te_wizspike (void)
 }
 
 // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_knightspike (void)
+static void VM_CL_te_knightspike (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1418,21 +1555,21 @@ void VM_CL_te_knightspike (void)
 }
 
 // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_lavasplash (void)
+static void VM_CL_te_lavasplash (void)
 {
        VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash);
        CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
 }
 
 // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_teleport (void)
+static void VM_CL_te_teleport (void)
 {
        VM_SAFEPARMCOUNT(1, VM_CL_te_teleport);
        CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
 }
 
 // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_explosion2 (void)
+static void VM_CL_te_explosion2 (void)
 {
        float           *pos;
        vec3_t          pos2, color;
@@ -1457,35 +1594,35 @@ void VM_CL_te_explosion2 (void)
 
 
 // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_lightning1 (void)
+static void VM_CL_te_lightning1 (void)
 {
        VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1);
        CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
 }
 
 // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_lightning2 (void)
+static void VM_CL_te_lightning2 (void)
 {
        VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2);
        CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
 }
 
 // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_lightning3 (void)
+static void VM_CL_te_lightning3 (void)
 {
        VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3);
        CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
 }
 
 // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_beam (void)
+static void VM_CL_te_beam (void)
 {
        VM_SAFEPARMCOUNT(3, VM_CL_te_beam);
        CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
 }
 
 // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
-void VM_CL_te_plasmaburn (void)
+static void VM_CL_te_plasmaburn (void)
 {
        float           *pos;
        vec3_t          pos2;
@@ -1496,6 +1633,19 @@ void VM_CL_te_plasmaburn (void)
        CL_ParticleEffect(EFFECT_TE_PLASMABURN, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
 }
 
+// #457 void(vector org, vector velocity, float howmany) te_flamejet (DP_TE_FLAMEJET)
+static void VM_CL_te_flamejet (void)
+{
+       float *pos;
+       vec3_t pos2;
+       VM_SAFEPARMCOUNT(3, VM_CL_te_flamejet);
+       if (PRVM_G_FLOAT(OFS_PARM2) < 1)
+               return;
+       pos = PRVM_G_VECTOR(OFS_PARM0);
+       CL_FindNonSolidLocation(pos, pos2, 4);
+       CL_ParticleEffect(EFFECT_TE_FLAMEJET, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
+}
+
 
 //====================================================================
 //DP_QC_GETSURFACE
@@ -1510,12 +1660,13 @@ static msurface_t *cl_getsurface(model_t *model, int surfacenum)
 }
 
 // #434 float(entity e, float s) getsurfacenumpoints
-void VM_CL_getsurfacenumpoints(void)
+static void VM_CL_getsurfacenumpoints(void)
 {
-       model_t *model = CSQC_GetModelFromEntity(PRVM_G_EDICT(OFS_PARM0));
+       model_t *model;
        msurface_t *surface;
+       VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenumpoints);
        // return 0 if no such surface
-       if (!model || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+       if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
        {
                PRVM_G_FLOAT(OFS_RETURN) = 0;
                return;
@@ -1526,15 +1677,16 @@ void VM_CL_getsurfacenumpoints(void)
 }
 
 // #435 vector(entity e, float s, float n) getsurfacepoint
-void VM_CL_getsurfacepoint(void)
+static void VM_CL_getsurfacepoint(void)
 {
        prvm_edict_t *ed;
        model_t *model;
        msurface_t *surface;
        int pointnum;
+       VM_SAFEPARMCOUNT(3, VM_CL_getsurfacenumpoints);
        VectorClear(PRVM_G_VECTOR(OFS_RETURN));
        ed = PRVM_G_EDICT(OFS_PARM0);
-       if (!(model = CSQC_GetModelFromEntity(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+       if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
                return;
        // note: this (incorrectly) assumes it is a simple polygon
        pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
@@ -1545,13 +1697,14 @@ void VM_CL_getsurfacepoint(void)
 }
 
 // #436 vector(entity e, float s) getsurfacenormal
-void VM_CL_getsurfacenormal(void)
+static void VM_CL_getsurfacenormal(void)
 {
        model_t *model;
        msurface_t *surface;
        vec3_t normal;
+       VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenormal);
        VectorClear(PRVM_G_VECTOR(OFS_RETURN));
-       if (!(model = CSQC_GetModelFromEntity(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+       if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
                return;
        // FIXME: implement rotation/scaling
        // note: this (incorrectly) assumes it is a simple polygon
@@ -1563,18 +1716,19 @@ void VM_CL_getsurfacenormal(void)
 }
 
 // #437 string(entity e, float s) getsurfacetexture
-void VM_CL_getsurfacetexture(void)
+static void VM_CL_getsurfacetexture(void)
 {
        model_t *model;
        msurface_t *surface;
+       VM_SAFEPARMCOUNT(2, VM_CL_getsurfacetexture);
        PRVM_G_INT(OFS_RETURN) = OFS_NULL;
-       if (!(model = CSQC_GetModelFromEntity(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+       if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
                return;
        PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
 }
 
 // #438 float(entity e, vector p) getsurfacenearpoint
-void VM_CL_getsurfacenearpoint(void)
+static void VM_CL_getsurfacenearpoint(void)
 {
        int surfacenum, best;
        vec3_t clipped, p;
@@ -1583,9 +1737,10 @@ void VM_CL_getsurfacenearpoint(void)
        model_t *model = NULL;
        msurface_t *surface;
        vec_t *point;
+       VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenearpoint);
        PRVM_G_FLOAT(OFS_RETURN) = -1;
        ed = PRVM_G_EDICT(OFS_PARM0);
-       if(!(model = CSQC_GetModelFromEntity(ed)) || !model->num_surfaces)
+       if(!(model = CL_GetModelFromEdict(ed)) || !model->num_surfaces)
                return;
 
        // FIXME: implement rotation/scaling
@@ -1619,15 +1774,16 @@ void VM_CL_getsurfacenearpoint(void)
 }
 
 // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint
-void VM_CL_getsurfaceclippedpoint(void)
+static void VM_CL_getsurfaceclippedpoint(void)
 {
        prvm_edict_t *ed;
        model_t *model;
        msurface_t *surface;
        vec3_t p, out;
+       VM_SAFEPARMCOUNT(3, VM_CL_getsurfaceclippedpoint);
        VectorClear(PRVM_G_VECTOR(OFS_RETURN));
        ed = PRVM_G_EDICT(OFS_PARM0);
-       if (!(model = CSQC_GetModelFromEntity(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+       if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
                return;
        // FIXME: implement rotation/scaling
        VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.client->origin, p);
@@ -1637,14 +1793,19 @@ void VM_CL_getsurfaceclippedpoint(void)
 }
 
 // #443 void(entity e, entity tagentity, string tagname) setattachment
-void VM_CL_setattachment (void)
+static void VM_CL_setattachment (void)
 {
-       prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
-       prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
-       const char *tagname = PRVM_G_STRING(OFS_PARM2);
+       prvm_edict_t *e;
+       prvm_edict_t *tagentity;
+       const char *tagname;
        prvm_eval_t *v;
        int modelindex;
        model_t *model;
+       VM_SAFEPARMCOUNT(3, VM_CL_setattachment);
+
+       e = PRVM_G_EDICT(OFS_PARM0);
+       tagentity = PRVM_G_EDICT(OFS_PARM1);
+       tagname = PRVM_G_STRING(OFS_PARM2);
 
        if (e == prog->edicts)
        {
@@ -1670,7 +1831,7 @@ void VM_CL_setattachment (void)
        if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
        {
                modelindex = (int)tagentity->fields.client->modelindex;
-               model = CSQC_GetModelByIndex(modelindex);
+               model = CL_GetModelByIndex(modelindex);
                if (model)
                {
                        v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.client->skin, tagname);
@@ -1687,7 +1848,7 @@ void VM_CL_setattachment (void)
 
 int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
 {
-       model_t *model = CSQC_GetModelFromEntity(e);
+       model_t *model = CL_GetModelFromEdict(e);
        if (model)
                return Mod_Alias_GetTagIndexForName(model, (int)e->fields.client->skin, tagname);
        else
@@ -1719,7 +1880,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
        if (ent->priv.server->free)
                return 2;
 
-       model = CSQC_GetModelFromEntity(ent);
+       model = CL_GetModelFromEdict(ent);
 
        if(!model)
                return 3;
@@ -1747,7 +1908,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                        attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
                        val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index);
 
-                       model = CSQC_GetModelFromEntity(attachent);
+                       model = CL_GetModelFromEdict(attachent);
 
                        if (model && val->_float >= 1 && model->animscenes && attachent->fields.client->frame >= 0 && attachent->fields.client->frame < model->numframes)
                                Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.client->frame].firstframe, (int)val->_float - 1, &attachmatrix);
@@ -1820,12 +1981,16 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
 }
 
 // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
-void VM_CL_gettagindex (void)
+static void VM_CL_gettagindex (void)
 {
-       prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
-       const char *tag_name = PRVM_G_STRING(OFS_PARM1);
+       prvm_edict_t *ent;
+       const char *tag_name;
        int modelindex, tag_index;
 
+       VM_SAFEPARMCOUNT(2, VM_CL_gettagindex);
+
+       ent = PRVM_G_EDICT(OFS_PARM0);
+       tag_name = PRVM_G_STRING(OFS_PARM1);
        if (ent == prog->edicts)
        {
                VM_Warning("gettagindex: can't affect world entity\n");
@@ -1853,13 +2018,17 @@ void VM_CL_gettagindex (void)
 }
 
 // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
-void VM_CL_gettaginfo (void)
+static void VM_CL_gettaginfo (void)
 {
-       prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
-       int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
+       prvm_edict_t *e;
+       int tagindex;
        matrix4x4_t tag_matrix;
        int returncode;
 
+       VM_SAFEPARMCOUNT(2, VM_CL_gettaginfo);
+
+       e = PRVM_G_EDICT(OFS_PARM0);
+       tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
        returncode = CL_GetTagMatrix(&tag_matrix, e, tagindex);
        Matrix4x4_ToVectors(&tag_matrix, prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN));
 
@@ -1883,451 +2052,1037 @@ void VM_CL_gettaginfo (void)
        }
 }
 
-//=================================================
-//[515]: here goes test/unfinished/etc.
+//============================================================================
+
+//====================
+//QC POLYGON functions
+//====================
 
-//[515]: check if it is what it should be
-void VM_WasFreed (void)
+typedef struct
 {
-       prvm_edict_t    *e;
-       VM_SAFEPARMCOUNT(1, VM_WasFreed);
+       rtexture_t              *tex;
+       float                   data[36];       //[515]: enough for polygons
+       unsigned char                   flags;  //[515]: + VM_POLYGON_2D and VM_POLYGON_FL4V flags
+}vm_polygon_t;
 
-       e = PRVM_G_EDICT(OFS_PARM0);
-       if (!e->priv.required->free || (e->priv.required->free && (e->priv.required->freetime < 2 || (prog->globals.client->time - e->priv.required->freetime) > 0.5 )))
-               PRVM_G_FLOAT(OFS_RETURN) = false;
+//static float                 vm_polygon_linewidth = 1;
+static mempool_t               *vm_polygons_pool = NULL;
+static unsigned char                   vm_current_vertices = 0;
+static qboolean                        vm_polygons_initialized = false;
+static vm_polygon_t            *vm_polygons = NULL;
+static unsigned long   vm_polygons_num = 0, vm_drawpolygons_num = 0;   //[515]: ok long on 64bit ?
+static qboolean                        vm_polygonbegin = false;        //[515]: for "no-crap-on-the-screen" check
+#define VM_DEFPOLYNUM 64       //[515]: enough for default ?
+
+#define VM_POLYGON_FL3V                16      //more than 2 vertices (used only for lines)
+#define VM_POLYGON_FLLINES     32
+#define VM_POLYGON_FL2D                64
+#define VM_POLYGON_FL4V                128     //4 vertices
+
+static void VM_InitPolygons (void)
+{
+       vm_polygons_pool = Mem_AllocPool("VMPOLY", 0, NULL);
+       vm_polygons = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
+       memset(vm_polygons, 0, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
+       vm_polygons_num = VM_DEFPOLYNUM;
+       vm_drawpolygons_num = 0;
+       vm_polygonbegin = false;
+       vm_polygons_initialized = true;
+}
+
+static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
+{
+       int surfacelistindex;
+       // LordHavoc: FIXME: this is stupid code
+       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+       {
+               const vm_polygon_t      *p = &vm_polygons[surfacelist[surfacelistindex]];
+               int                                     flags = p->flags & 0x0f;
+
+               if(flags == DRAWFLAG_ADDITIVE)
+                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+               else if(flags == DRAWFLAG_MODULATE)
+                       GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
+               else if(flags == DRAWFLAG_2XMODULATE)
+                       GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
+               else
+                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+               R_Mesh_TexBind(0, R_GetTexture(p->tex));
+
+               CHECKGLERROR
+               //[515]: is speed is max ?
+               if(p->flags & VM_POLYGON_FLLINES)       //[515]: lines
+               {
+                       qglLineWidth(p->data[13]);CHECKGLERROR
+                       qglBegin(GL_LINE_LOOP);
+                               qglTexCoord1f   (p->data[12]);
+                               qglColor4f              (p->data[20], p->data[21], p->data[22], p->data[23]);
+                               qglVertex3f             (p->data[0] , p->data[1],  p->data[2]);
+
+                               qglTexCoord1f   (p->data[14]);
+                               qglColor4f              (p->data[24], p->data[25], p->data[26], p->data[27]);
+                               qglVertex3f             (p->data[3] , p->data[4],  p->data[5]);
+
+                               if(p->flags & VM_POLYGON_FL3V)
+                               {
+                                       qglTexCoord1f   (p->data[16]);
+                                       qglColor4f              (p->data[28], p->data[29], p->data[30], p->data[31]);
+                                       qglVertex3f             (p->data[6] , p->data[7],  p->data[8]);
+
+                                       if(p->flags & VM_POLYGON_FL4V)
+                                       {
+                                               qglTexCoord1f   (p->data[18]);
+                                               qglColor4f              (p->data[32], p->data[33], p->data[34], p->data[35]);
+                                               qglVertex3f             (p->data[9] , p->data[10],  p->data[11]);
+                                       }
+                               }
+                       qglEnd();
+                       CHECKGLERROR
+               }
+               else
+               {
+                       qglBegin(GL_POLYGON);
+                               qglTexCoord2f   (p->data[12], p->data[13]);
+                               qglColor4f              (p->data[20], p->data[21], p->data[22], p->data[23]);
+                               qglVertex3f             (p->data[0] , p->data[1],  p->data[2]);
+
+                               qglTexCoord2f   (p->data[14], p->data[15]);
+                               qglColor4f              (p->data[24], p->data[25], p->data[26], p->data[27]);
+                               qglVertex3f             (p->data[3] , p->data[4],  p->data[5]);
+
+                               qglTexCoord2f   (p->data[16], p->data[17]);
+                               qglColor4f              (p->data[28], p->data[29], p->data[30], p->data[31]);
+                               qglVertex3f             (p->data[6] , p->data[7],  p->data[8]);
+
+                               if(p->flags & VM_POLYGON_FL4V)
+                               {
+                                       qglTexCoord2f   (p->data[18], p->data[19]);
+                                       qglColor4f              (p->data[32], p->data[33], p->data[34], p->data[35]);
+                                       qglVertex3f             (p->data[9] , p->data[10],  p->data[11]);
+                               }
+                       qglEnd();
+                       CHECKGLERROR
+               }
+       }
+}
+
+static void VM_CL_AddPolygonTo2DScene (vm_polygon_t *p)
+{
+       drawqueuemesh_t mesh;
+       static int              picelements[6] = {0, 1, 2, 0, 2, 3};
+
+       mesh.texture = p->tex;
+       mesh.data_element3i = picelements;
+       mesh.data_vertex3f = p->data;
+       mesh.data_texcoord2f = p->data + 12;
+       mesh.data_color4f = p->data + 20;
+       if(p->flags & VM_POLYGON_FL4V)
+       {
+               mesh.num_vertices = 4;
+               mesh.num_triangles = 2;
+       }
        else
-               PRVM_G_FLOAT(OFS_RETURN) = true;
+       {
+               mesh.num_vertices = 3;
+               mesh.num_triangles = 1;
+       }
+       if(p->flags & VM_POLYGON_FLLINES)       //[515]: lines
+               DrawQ_LineLoop (&mesh, (p->flags&0x0f));
+       else
+               DrawQ_Mesh (&mesh, (p->flags&0x0f));
 }
 
-void VM_CL_select_cube (void)
+void VM_CL_AddPolygonsToMeshQueue (void)
 {
-       int             i;
-       float   *mins2, *maxs2;
-       prvm_edict_t    *ent, *chain;
-       vec3_t  mins1, maxs1;
+       int i;
+       if(!vm_drawpolygons_num)
+               return;
+       R_Mesh_Matrix(&identitymatrix);
+       GL_CullFace(GL_NONE);
+       for(i = 0;i < (int)vm_drawpolygons_num;i++)
+               VM_DrawPolygonCallback(NULL, NULL, 1, &i);
+       vm_drawpolygons_num = 0;
+}
 
-       VM_SAFEPARMCOUNT(2, VM_CL_select_cube);
+//void(string texturename, float flag[, float 2d[, float lines]]) R_BeginPolygon
+static void VM_CL_R_PolygonBegin (void)
+{
+       vm_polygon_t    *p;
+       const char              *picname;
+       VM_SAFEPARMCOUNTRANGE(2, 4, VM_CL_R_PolygonBegin);
 
-       if (prog->fieldoffsets.chain < 0)
-               PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
+       if(!vm_polygons_initialized)
+               VM_InitPolygons();
+       if(vm_polygonbegin)
+       {
+               VM_Warning("VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonEnd after first\n");
+               return;
+       }
+       if(vm_drawpolygons_num >= vm_polygons_num)
+       {
+               p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t));
+               memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t));
+               memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t));
+               Mem_Free(vm_polygons);
+               vm_polygons = p;
+               vm_polygons_num *= 2;
+       }
+       p = &vm_polygons[vm_drawpolygons_num];
+       picname = PRVM_G_STRING(OFS_PARM0);
+       if(picname[0])
+               p->tex = Draw_CachePic(picname, true)->tex;
+       else
+               p->tex = r_texture_white;
+       p->flags = (unsigned char)PRVM_G_FLOAT(OFS_PARM1);
+       vm_current_vertices = 0;
+       vm_polygonbegin = true;
+       if(prog->argc >= 3)
+       {
+               if(PRVM_G_FLOAT(OFS_PARM2))
+                       p->flags |= VM_POLYGON_FL2D;
+               if(prog->argc >= 4 && PRVM_G_FLOAT(OFS_PARM3))
+               {
+                       p->data[13] = PRVM_G_FLOAT(OFS_PARM3);  //[515]: linewidth
+                       p->flags |= VM_POLYGON_FLLINES;
+               }
+       }
+}
 
-       chain = prog->edicts;
+//void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
+static void VM_CL_R_PolygonVertex (void)
+{
+       float                   *coords, *tx, *rgb, alpha;
+       vm_polygon_t    *p;
+       VM_SAFEPARMCOUNT(4, VM_CL_R_PolygonVertex);
 
-       mins2 = PRVM_G_VECTOR(OFS_PARM0);
-       maxs2 = PRVM_G_VECTOR(OFS_PARM1);
+       if(!vm_polygonbegin)
+       {
+               VM_Warning("VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n");
+               return;
+       }
+       coords  = PRVM_G_VECTOR(OFS_PARM0);
+       tx              = PRVM_G_VECTOR(OFS_PARM1);
+       rgb             = PRVM_G_VECTOR(OFS_PARM2);
+       alpha = PRVM_G_FLOAT(OFS_PARM3);
 
-       ent = PRVM_NEXT_EDICT(prog->edicts);
-       for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
+       p = &vm_polygons[vm_drawpolygons_num];
+       if(vm_current_vertices > 4)
        {
-               if (ent->priv.required->free)
-                       continue;
-               VectorCopy(ent->fields.client->origin, mins1);
-               VectorAdd(mins1, ent->fields.client->maxs, maxs1);
-               VectorAdd(mins1, ent->fields.client->mins, mins1);
-               if (mins1[0] > maxs2[0] || mins1[1] > maxs2[1] || mins1[2] > maxs2[2])
-                       continue;
-               if (maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2])
-                       continue;
-               PRVM_EDICTFIELDVALUE(ent,prog->fieldoffsets.chain)->edict = PRVM_NUM_FOR_EDICT(chain);
-               chain = ent;
+               VM_Warning("VM_CL_R_PolygonVertex: may have 4 vertices max\n");
+               return;
        }
 
-       VM_RETURN_EDICT(chain);
+       p->data[vm_current_vertices*3]          = coords[0];
+       p->data[1+vm_current_vertices*3]        = coords[1];
+       p->data[2+vm_current_vertices*3]        = coords[2];
+
+       p->data[12+vm_current_vertices*2]       = tx[0];
+       if(!(p->flags & VM_POLYGON_FLLINES))
+               p->data[13+vm_current_vertices*2]       = tx[1];
+
+       p->data[20+vm_current_vertices*4]       = rgb[0];
+       p->data[21+vm_current_vertices*4]       = rgb[1];
+       p->data[22+vm_current_vertices*4]       = rgb[2];
+       p->data[23+vm_current_vertices*4]       = alpha;
+
+       vm_current_vertices++;
+       if(vm_current_vertices == 4)
+               p->flags |= VM_POLYGON_FL4V;
+       else
+               if(vm_current_vertices == 3)
+                       p->flags |= VM_POLYGON_FL3V;
 }
 
-void VM_CL_select_super (void)
+//void() R_EndPolygon
+static void VM_CL_R_PolygonEnd (void)
 {
-/*     int             i;
-       float   *v[8];
-       prvm_edict_t    *ent, *chain;
-       vec3_t  mins1, maxs1;
+       VM_SAFEPARMCOUNT(0, VM_CL_R_PolygonEnd);
+       if(!vm_polygonbegin)
+       {
+               VM_Warning("VM_CL_R_PolygonEnd: VM_CL_R_PolygonBegin wasn't called\n");
+               return;
+       }
+       vm_polygonbegin = false;
+       if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES))
+       {
+               if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D)    //[515]: don't use qcpolygons memory if 2D
+                       VM_CL_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]);
+               else
+                       vm_drawpolygons_num++;
+       }
+       else
+               VM_Warning("VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices);
+}
 
-       VM_SAFEPARMCOUNT(8, VM_findchain);
-       for(i=0;i<8;i++)
-               v[i] = PRVM_G_VECTOR(OFS_PARM0+i*3);
+void Debug_PolygonBegin(const char *picname, int flags, qboolean draw2d, float linewidth)
+{
+       vm_polygon_t    *p;
 
-       if (prog->fieldoffsets.chain < 0)
-               PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
+       if(!vm_polygons_initialized)
+               VM_InitPolygons();
+       if(vm_polygonbegin)
+       {
+               Con_Printf("Debug_PolygonBegin: called twice without Debug_PolygonEnd after first\n");
+               return;
+       }
+       // limit polygons to a vaguely sane amount, beyond this each one just
+       // replaces the last one
+       vm_drawpolygons_num = min(vm_drawpolygons_num, (1<<20)-1);
+       if(vm_drawpolygons_num >= vm_polygons_num)
+       {
+               p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t));
+               memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t));
+               memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t));
+               Mem_Free(vm_polygons);
+               vm_polygons = p;
+               vm_polygons_num *= 2;
+       }
+       p = &vm_polygons[vm_drawpolygons_num];
+       if(picname && picname[0])
+               p->tex = Draw_CachePic(picname, true)->tex;
+       else
+               p->tex = r_texture_white;
+       p->flags = flags;
+       vm_current_vertices = 0;
+       vm_polygonbegin = true;
+       if(draw2d)
+               p->flags |= VM_POLYGON_FL2D;
+       if(linewidth)
+       {
+               p->data[13] = linewidth;        //[515]: linewidth
+               p->flags |= VM_POLYGON_FLLINES;
+       }
+}
 
-       chain = prog->edicts;
+void Debug_PolygonVertex(float x, float y, float z, float s, float t, float r, float g, float b, float a)
+{
+       vm_polygon_t    *p;
 
-       mins2 = PRVM_G_VECTOR(OFS_PARM0);
-       maxs2 = PRVM_G_VECTOR(OFS_PARM1);
+       if(!vm_polygonbegin)
+       {
+               Con_Printf("Debug_PolygonVertex: Debug_PolygonBegin wasn't called\n");
+               return;
+       }
 
-       ent = PRVM_NEXT_EDICT(prog->edicts);
-       for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
+       p = &vm_polygons[vm_drawpolygons_num];
+       if(vm_current_vertices > 4)
        {
-               if (ent->priv.required->free)
-                       continue;
-               VectorCopy(ent->fields.client->origin, mins1);
-               VectorAdd(mins1, ent->fields.client->maxs, maxs1);
-               VectorAdd(mins1, ent->fields.client->mins, mins1);
-               if (mins1[0] > maxs2[0] || mins1[1] > maxs2[1] || mins1[2] > maxs2[2])
-                       continue;
-               if (maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2])
-                       continue;
-               PRVM_EDICTFIELDVALUE(ent,prog->fieldoffsets.chain)->edict = PRVM_NUM_FOR_EDICT(chain);
-               chain = ent;
+               Con_Printf("Debug_PolygonVertex: may have 4 vertices max\n");
+               return;
        }
 
-       VM_RETURN_EDICT(chain);*/
+       p->data[vm_current_vertices*3]          = x;
+       p->data[1+vm_current_vertices*3]        = y;
+       p->data[2+vm_current_vertices*3]        = z;
+
+       p->data[12+vm_current_vertices*2]       = s;
+       if(!(p->flags & VM_POLYGON_FLLINES))
+               p->data[13+vm_current_vertices*2]       = t;
+
+       p->data[20+vm_current_vertices*4]       = r;
+       p->data[21+vm_current_vertices*4]       = g;
+       p->data[22+vm_current_vertices*4]       = b;
+       p->data[23+vm_current_vertices*4]       = a;
+
+       vm_current_vertices++;
+       if(vm_current_vertices == 4)
+               p->flags |= VM_POLYGON_FL4V;
+       else
+               if(vm_current_vertices == 3)
+                       p->flags |= VM_POLYGON_FL3V;
 }
 
-static int Is_Text_Color (char c, char t)
+void Debug_PolygonEnd(void)
 {
-       int a = 0;
-       char c2 = c - (c & 128);
-       char t2 = t - (t & 128);
+       if(!vm_polygonbegin)
+       {
+               Con_Printf("Debug_PolygonEnd: Debug_PolygonBegin wasn't called\n");
+               return;
+       }
+       vm_polygonbegin = false;
+       if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES))
+       {
+               if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D)    //[515]: don't use qcpolygons memory if 2D
+                       VM_CL_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]);
+               else
+                       vm_drawpolygons_num++;
+       }
+       else
+               Con_Printf("Debug_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices);
+}
 
-       if(c != STRING_COLOR_TAG && c2 != STRING_COLOR_TAG)             return 0;
-       if(t >= '0' && t <= '9')                a = 1;
-       if(t2 >= '0' && t2 <= '9')              a = 1;
-/*     if(t >= 'A' && t <= 'Z')                a = 2;
-       if(t2 >= 'A' && t2 <= 'Z')              a = 2;
+/*
+=============
+CL_CheckBottom
 
-       if(a == 1 && scr_colortext.integer > 0)
-               return 1;
-       if(a == 2 && scr_multifonts.integer > 0)
-               return 2;
+Returns false if any part of the bottom of the entity is off an edge that
+is not a staircase.
+
+=============
 */
-       return a;
+qboolean CL_CheckBottom (prvm_edict_t *ent)
+{
+       vec3_t  mins, maxs, start, stop;
+       trace_t trace;
+       int             x, y;
+       float   mid, bottom;
+
+       VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins);
+       VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs);
+
+// if all of the points under the corners are solid world, don't bother
+// with the tougher checks
+// the corners must be within 16 of the midpoint
+       start[2] = mins[2] - 1;
+       for     (x=0 ; x<=1 ; x++)
+               for     (y=0 ; y<=1 ; y++)
+               {
+                       start[0] = x ? maxs[0] : mins[0];
+                       start[1] = y ? maxs[1] : mins[1];
+                       if (!(CL_PointSuperContents(start) & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY)))
+                               goto realcheck;
+               }
+
+       return true;            // we got out easy
+
+realcheck:
+//
+// check it for real...
+//
+       start[2] = mins[2];
+
+// the midpoint must be within 16 of the bottom
+       start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
+       start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
+       stop[2] = start[2] - 2*sv_stepheight.value;
+       trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+
+       if (trace.fraction == 1.0)
+               return false;
+       mid = bottom = trace.endpos[2];
+
+// the corners must be within 16 of the midpoint
+       for     (x=0 ; x<=1 ; x++)
+               for     (y=0 ; y<=1 ; y++)
+               {
+                       start[0] = stop[0] = x ? maxs[0] : mins[0];
+                       start[1] = stop[1] = y ? maxs[1] : mins[1];
+
+                       trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+
+                       if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
+                               bottom = trace.endpos[2];
+                       if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value)
+                               return false;
+               }
+
+       return true;
 }
 
-void VM_uncolorstring (void) //#170
+/*
+=============
+CL_movestep
+
+Called by monster program code.
+The move will be adjusted for slopes and stairs, but if the move isn't
+possible, no move is done and false is returned
+=============
+*/
+qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean settrace)
 {
-       const char      *in;
-       char            out[VM_STRINGTEMP_LENGTH];
-       int                     k = 0, i = 0;
+       float           dz;
+       vec3_t          oldorg, neworg, end, traceendpos;
+       trace_t         trace;
+       int                     i;
+       prvm_edict_t            *enemy;
+       prvm_eval_t     *val;
 
-       VM_SAFEPARMCOUNT(1, VM_uncolorstring);
-       in = PRVM_G_STRING(OFS_PARM0);
-       VM_CheckEmptyString (in);
+// try the move
+       VectorCopy (ent->fields.client->origin, oldorg);
+       VectorAdd (ent->fields.client->origin, move, neworg);
 
-       while (in[k])
+// flying monsters don't step up
+       if ( (int)ent->fields.client->flags & (FL_SWIM | FL_FLY) )
        {
-               if(in[k+1])
-               if(Is_Text_Color(in[k], in[k+1]) == 1/* || (in[k] == '&' && in[k+1] == 'r')*/)
+       // try one move with vertical motion, then one without
+               for (i=0 ; i<2 ; i++)
                {
-                       k += 2;
-                       continue;
+                       VectorAdd (ent->fields.client->origin, move, neworg);
+                       enemy = PRVM_PROG_TO_EDICT(ent->fields.client->enemy);
+                       if (i == 0 && enemy != prog->edicts)
+                       {
+                               dz = ent->fields.client->origin[2] - PRVM_PROG_TO_EDICT(ent->fields.client->enemy)->fields.client->origin[2];
+                               if (dz > 40)
+                                       neworg[2] -= 8;
+                               if (dz < 30)
+                                       neworg[2] += 8;
+                       }
+                       trace = CL_Move (ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+                       if (settrace)
+                               VM_SetTraceGlobals(&trace);
+
+                       if (trace.fraction == 1)
+                       {
+                               VectorCopy(trace.endpos, traceendpos);
+                               if (((int)ent->fields.client->flags & FL_SWIM) && !(CL_PointSuperContents(traceendpos) & SUPERCONTENTS_LIQUIDSMASK))
+                                       return false;   // swim monster left water
+
+                               VectorCopy (traceendpos, ent->fields.client->origin);
+                               if (relink)
+                                       CL_LinkEdict(ent);
+                               return true;
+                       }
+
+                       if (enemy == prog->edicts)
+                               break;
+               }
+
+               return false;
+       }
+
+// push down from a step height above the wished position
+       neworg[2] += sv_stepheight.value;
+       VectorCopy (neworg, end);
+       end[2] -= sv_stepheight.value*2;
+
+       trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+       if (settrace)
+               VM_SetTraceGlobals(&trace);
+
+       if (trace.startsolid)
+       {
+               neworg[2] -= sv_stepheight.value;
+               trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+               if (settrace)
+                       VM_SetTraceGlobals(&trace);
+               if (trace.startsolid)
+                       return false;
+       }
+       if (trace.fraction == 1)
+       {
+       // if monster had the ground pulled out, go ahead and fall
+               if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
+               {
+                       VectorAdd (ent->fields.client->origin, move, ent->fields.client->origin);
+                       if (relink)
+                               CL_LinkEdict(ent);
+                       ent->fields.client->flags = (int)ent->fields.client->flags & ~FL_ONGROUND;
+                       return true;
+               }
+
+               return false;           // walked off an edge
+       }
+
+// check point traces down for dangling corners
+       VectorCopy (trace.endpos, ent->fields.client->origin);
+
+       if (!CL_CheckBottom (ent))
+       {
+               if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
+               {       // entity had floor mostly pulled out from underneath it
+                       // and is trying to correct
+                       if (relink)
+                               CL_LinkEdict(ent);
+                       return true;
                }
-               out[i] = in[k];
-               ++k;
-               ++i;
+               VectorCopy (oldorg, ent->fields.client->origin);
+               return false;
        }
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(out);
+
+       if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
+               ent->fields.client->flags = (int)ent->fields.client->flags & ~FL_PARTIALGROUND;
+
+       if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.groundentity)))
+               val->edict = PRVM_EDICT_TO_PROG(trace.ent);
+
+// the move is ok
+       if (relink)
+               CL_LinkEdict(ent);
+       return true;
 }
 
-void VM_CL_selecttraceline (void)
+/*
+===============
+VM_CL_walkmove
+
+float(float yaw, float dist[, settrace]) walkmove
+===============
+*/
+static void VM_CL_walkmove (void)
 {
-       float   *v1, *v2;
-       int             ent, ignore, csqcents;
+       prvm_edict_t    *ent;
+       float   yaw, dist;
+       vec3_t  move;
+       mfunction_t     *oldf;
+       int     oldself;
+       qboolean        settrace;
 
-       v1 = PRVM_G_VECTOR(OFS_PARM0);
-       v2 = PRVM_G_VECTOR(OFS_PARM1);
-       ignore = (int)PRVM_G_FLOAT(OFS_PARM2);
-       csqcents = (int)PRVM_G_FLOAT(OFS_PARM3);
-       ent = 0;
+       VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_walkmove);
 
-       if (csqcents)
+       // assume failure if it returns early
+       PRVM_G_FLOAT(OFS_RETURN) = 0;
+
+       ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
+       if (ent == prog->edicts)
        {
-               VM_Warning("VM_CL_selecttraceline: csqcents flag not supported anymore, and this function is deprecated\n");
+               VM_Warning("walkmove: can not modify world entity\n");
                return;
        }
-       prog->globals.client->trace_fraction = CL_SelectTraceLine(v1, v2, prog->globals.client->trace_endpos, prog->globals.client->trace_plane_normal, &ent, &cl.entities[ignore].render);
-       PRVM_G_FLOAT(OFS_RETURN) = ent;
-}
+       if (ent->priv.server->free)
+       {
+               VM_Warning("walkmove: can not modify free entity\n");
+               return;
+       }
+       yaw = PRVM_G_FLOAT(OFS_PARM0);
+       dist = PRVM_G_FLOAT(OFS_PARM1);
+       settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
 
-void VM_charindex (void)
-{
-       const char *s;
-       s = PRVM_G_STRING(OFS_PARM0);
-       if((unsigned)PRVM_G_FLOAT(OFS_PARM1) > strlen(s))
+       if ( !( (int)ent->fields.client->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
                return;
-       PRVM_G_FLOAT(OFS_RETURN) = (unsigned char)s[(int)PRVM_G_FLOAT(OFS_PARM1)];
-}
 
-//#223 string(float c, ...) chr2str (FTE_STRINGS)
-void VM_chr2str (void)
-{
-       char    t[128];
-       int             i;
-       for(i = 0;i < prog->argc && i < (int)sizeof(t) - 1;i++)
-               t[i] = (unsigned char)PRVM_G_FLOAT(OFS_PARM0+i*3);
-       t[i] = 0;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
+       yaw = yaw*M_PI*2 / 360;
+
+       move[0] = cos(yaw)*dist;
+       move[1] = sin(yaw)*dist;
+       move[2] = 0;
+
+// save program state, because CL_movestep may call other progs
+       oldf = prog->xfunction;
+       oldself = prog->globals.client->self;
+
+       PRVM_G_FLOAT(OFS_RETURN) = CL_movestep(ent, move, true, false, settrace);
+
+
+// restore program state
+       prog->xfunction = oldf;
+       prog->globals.client->self = oldself;
 }
 
-//#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
-void VM_strncmp (void)
+/*
+===============
+VM_CL_serverkey
+
+string(string key) serverkey
+===============
+*/
+void VM_CL_serverkey(void)
 {
-       const char *s1, *s2;
-       VM_SAFEPARMCOUNT(1, VM_strncmp);
-       s1 = PRVM_G_STRING(OFS_PARM0);
-       s2 = PRVM_G_STRING(OFS_PARM1);
-       PRVM_G_FLOAT(OFS_RETURN) = strncmp(s1, s2, (size_t)PRVM_G_FLOAT(OFS_PARM2));
+       char string[VM_STRINGTEMP_LENGTH];
+       VM_SAFEPARMCOUNT(1, VM_CL_serverkey);
+       InfoString_GetValue(cl.qw_serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
 }
 
 //============================================================================
-//============================================================================
 
 prvm_builtin_t vm_cl_builtins[] = {
-0,  // to be consistent with the old vm
-VM_CL_makevectors,                     // #1 void(vector ang) makevectors
-VM_CL_setorigin,                       // #2 void(entity e, vector o) setorigin
-VM_CL_setmodel,                                // #3 void(entity e, string m) setmodel
-VM_CL_setsize,                         // #4 void(entity e, vector min, vector max) setsize
-0,
-VM_break,                                      // #6 void() break
-VM_random,                                     // #7 float() random
-VM_CL_sound,                           // #8 void(entity e, float chan, string samp) sound
-VM_normalize,                          // #9 vector(vector v) normalize
-VM_error,                                      // #10 void(string e) error
-VM_objerror,                           // #11 void(string e) objerror
-VM_vlen,                                       // #12 float(vector v) vlen
-VM_vectoyaw,                           // #13 float(vector v) vectoyaw
-VM_CL_spawn,                           // #14 entity() spawn
-VM_remove,                                     // #15 void(entity e) remove
-VM_CL_traceline,                       // #16 float(vector v1, vector v2, float tryents) traceline
-0,
-VM_find,                                       // #18 entity(entity start, .string fld, string match) find
-VM_CL_precache_sound,          // #19 void(string s) precache_sound
-VM_CL_precache_model,          // #20 void(string s) precache_model
-0,
-VM_CL_findradius,                      // #22 entity(vector org, float rad) findradius
-0,
-0,
-VM_dprint,                                     // #25 void(string s) dprint
-VM_ftos,                                       // #26 void(string s) ftos
-VM_vtos,                                       // #27 void(string s) vtos
-VM_coredump,                           // #28 void() coredump
-VM_traceon,                                    // #29 void() traceon
-VM_traceoff,                           // #30 void() traceoff
-VM_eprint,                                     // #31 void(entity e) eprint
-0,
-NULL,                                          // #33
-VM_CL_droptofloor,                     // #34 float() droptofloor
-VM_CL_lightstyle,                      // #35 void(float style, string value) lightstyle
-VM_rint,                                       // #36 float(float v) rint
-VM_floor,                                      // #37 float(float v) floor
-VM_ceil,                                       // #38 float(float v) ceil
-NULL,                                          // #39
-VM_CL_checkbottom,                     // #40 float(entity e) checkbottom
-VM_CL_pointcontents,           // #41 float(vector v) pointcontents
-NULL,                                          // #42
-VM_fabs,                                       // #43 float(float f) fabs
-0,
-VM_cvar,                                       // #45 float(string s) cvar
-VM_localcmd,                           // #46 void(string s) localcmd
-VM_nextent,                                    // #47 entity(entity e) nextent
-VM_CL_particle,                                // #48 void(vector o, vector d, float color, float count) particle
-VM_changeyaw,                          // #49 void(entity ent) ChangeYaw
-NULL,                                          // #50
-VM_vectoangles,                                // #51 vector(vector v) vectoangles
-0,                     // #52 void(float to, float f) WriteByte
-0,                     // #53 void(float to, float f) WriteChar
-0,                     // #54 void(float to, float f) WriteShort
-0,                     // #55 void(float to, float f) WriteLong
-0,                     // #56 void(float to, float f) WriteCoord
-0,                     // #57 void(float to, float f) WriteAngle
-0,                     // #58 void(float to, string s) WriteString
-0,
-VM_sin,                                                // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
-VM_cos,                                                // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
-VM_sqrt,                                       // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
-VM_changepitch,                                // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
-VM_CL_tracetoss,                       // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
-VM_etos,                                       // #65 string(entity ent) etos (DP_QC_ETOS)
-NULL,                                          // #66
-0,                                                             // #67
-0,                                                             // #68
-0,                                                             // #69
-0,                                                             // #70
-NULL,                                          // #71
-VM_cvar_set,                           // #72 void(string var, string val) cvar_set
-0,                                                             // #73
-VM_CL_ambientsound,                    // #74 void(vector pos, string samp, float vol, float atten) ambientsound
-VM_CL_precache_model,          // #75 string(string s) precache_model2
-VM_CL_precache_sound,          // #76 string(string s) precache_sound2
-0,                                                             // #77
-VM_chr,                                                // #78
-NULL,                                          // #79
-NULL,                                          // #80
-VM_stof,                                       // #81 float(string s) stof (FRIK_FILE)
-NULL,                                          // #82
-NULL,                                          // #83
-NULL,                                          // #84
-NULL,                                          // #85
-NULL,                                          // #86
-NULL,                                          // #87
-NULL,                                          // #88
-NULL,                                          // #89
-VM_CL_tracebox,                                // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
-VM_randomvec,                          // #91 vector() randomvec (DP_QC_RANDOMVEC)
-VM_CL_getlight,                                // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
-PF_registercvar,                       // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
-VM_min,                                                // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
-VM_max,                                                // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
-VM_bound,                                      // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
-VM_pow,                                                // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
-VM_findfloat,                          // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
-VM_checkextension,                     // #99 float(string s) checkextension (the basis of the extension system)
-NULL,                                          // #100
-NULL,                                          // #101
-NULL,                                          // #102
-NULL,                                          // #103
-NULL,                                          // #104
-NULL,                                          // #105
-NULL,                                          // #106
-NULL,                                          // #107
-NULL,                                          // #108
-NULL,                                          // #109
-VM_fopen,                                      // #110 float(string filename, float mode) fopen (FRIK_FILE)
-VM_fclose,                                     // #111 void(float fhandle) fclose (FRIK_FILE)
-VM_fgets,                                      // #112 string(float fhandle) fgets (FRIK_FILE)
-VM_fputs,                                      // #113 void(float fhandle, string s) fputs (FRIK_FILE)
-VM_strlen,                                     // #114 float(string s) strlen (FRIK_FILE)
-VM_strcat,                                     // #115 string(string s1, string s2) strcat (FRIK_FILE)
-VM_substring,                          // #116 string(string s, float start, float length) substring (FRIK_FILE)
-VM_stov,                                       // #117 vector(string) stov (FRIK_FILE)
-VM_strzone,                                    // #118 string(string s) strzone (FRIK_FILE)
-VM_strunzone,                          // #119 void(string s) strunzone (FRIK_FILE)
-
-e10, e10, e10, e10, e10, e10, e10, e10,                // #120-199
-e10,   //#200-209
-0,     //#210
-0,     //#211
-0,     //#212
-0,     //#213
-0,     //#214
-0,     //#215
-0,     //#216
-0,     //#217
-VM_bitshift,                           //#218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
-0,     //#219
-0,     //#220
-0,     //#221
-VM_charindex,                          //#222 float(string str, float ofs) str2chr (FTE_STRINGS)
-VM_chr2str,                                    //#223 string(float c, ...) chr2str (FTE_STRINGS)
-0,     //#224
-0,     //#225
-0,     //#226
-0,     //#227
-VM_strncmp,                                    //#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
-0,
-e10, e10, e10, e10, e10, e10, e10,     // #230-299
-
-//======CSQC start=======//
-//3d world (buffer/buffering) operations
-VM_R_ClearScene,                       //#300 void() clearscene (EXT_CSQC)
-VM_R_AddEntities,                      //#301 void(float mask) addentities (EXT_CSQC)
-VM_R_AddEntity,                                //#302 void(entity ent) addentity (EXT_CSQC)
-VM_R_SetView,                          //#303 float(float property, ...) setproperty (EXT_CSQC)
-VM_R_RenderScene,                      //#304 void() renderscene (EXT_CSQC)
-VM_R_AddDynamicLight,          //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
-VM_R_PolygonBegin,                     //#306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
-VM_R_PolygonVertex,                    //#307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
-VM_R_PolygonEnd,                       //#308 void() R_EndPolygon
-0,                     //#309
-
-//maths stuff that uses the current view settings
-VM_CL_unproject,                       //#310 vector (vector v) cs_unproject (EXT_CSQC)
-VM_CL_project,                         //#311 vector (vector v) cs_project (EXT_CSQC)
-0,                     //#312
-0,                     //#313
-0,                     //#314
-
-//2d (immediate) operations
-VM_drawline,                           //#315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
-VM_iscachedpic,                                //#316 float(string name) iscachedpic (EXT_CSQC)
-VM_precache_pic,                       //#317 string(string name, float trywad) precache_pic (EXT_CSQC)
-VM_getimagesize,                       //#318 vector(string picname) draw_getimagesize (EXT_CSQC)
-VM_freepic,                                    //#319 void(string name) freepic (EXT_CSQC)
-VM_drawcharacter,                      //#320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
-VM_drawstring,                         //#321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
-VM_drawpic,                                    //#322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
-VM_drawfill,                           //#323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
-VM_drawsetcliparea,                    //#324 void(float x, float y, float width, float height) drawsetcliparea
-VM_drawresetcliparea,          //#325 void(void) drawresetcliparea
-0,                     //#326
-0,                     //#327
-0,                     //#328
-0,                     //#329
-
-VM_CL_getstatf,                                //#330 float(float stnum) getstatf (EXT_CSQC)
-VM_CL_getstati,                                //#331 float(float stnum) getstati (EXT_CSQC)
-VM_CL_getstats,                                //#332 string(float firststnum) getstats (EXT_CSQC)
-VM_CL_setmodelindex,           //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
-VM_CL_modelnameforindex,       //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
-VM_CL_particleeffectnum,       //#335 float(string effectname) particleeffectnum (EXT_CSQC)
-VM_CL_trailparticles,          //#336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
-VM_CL_pointparticles,          //#337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
-VM_CL_centerprint,                     //#338 void(string s) cprint (EXT_CSQC)
-VM_print,                                      //#339 void(string s) print (EXT_CSQC)
-VM_keynumtostring,                     //#340 string(float keynum) keynumtostring (EXT_CSQC)
-VM_stringtokeynum,                     //#341 float(string keyname) stringtokeynum (EXT_CSQC)
-VM_CL_getkeybind,                      //#342 string(float keynum) getkeybind (EXT_CSQC)
-VM_CL_setcursormode,           //#343 void(float usecursor) setcursormode (EXT_CSQC)
-VM_getmousepos,                                //#344 vector() getmousepos (EXT_CSQC)
-VM_CL_getinputstate,           //#345 float(float framenum) getinputstate (EXT_CSQC)
-VM_CL_setsensitivityscale,     //#346 void(float sens) setsensitivityscaler (EXT_CSQC)
-VM_CL_runplayerphysics,                //#347 void() runstandardplayerphysics (EXT_CSQC)
-VM_CL_getplayerkey,                    //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
-VM_CL_isdemo,                          //#349 float() isdemo (EXT_CSQC)
-VM_isserver,                           //#350 float() isserver (EXT_CSQC)
-VM_CL_setlistener,                     //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
-VM_CL_registercmd,                     //#352 void(string cmdname) registercommand (EXT_CSQC)
-VM_WasFreed,                           //#353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
-VM_CL_playernum,                       //#354 float() playernum
-VM_CL_onground,                                //#355 float() cl_onground (EXT_CSQC)
-VM_charindex,                          //#356 float(string s, float num) charindex
-VM_CL_selecttraceline,         //#357 float(vector start, vector end, float ignore, float csqcents) selecttraceline
-0,                     //#358
-0,                     //#359
-VM_CL_ReadByte,                                //#360 float() readbyte (EXT_CSQC)
-VM_CL_ReadChar,                                //#361 float() readchar (EXT_CSQC)
-VM_CL_ReadShort,                       //#362 float() readshort (EXT_CSQC)
-VM_CL_ReadLong,                                //#363 float() readlong (EXT_CSQC)
-VM_CL_ReadCoord,                       //#364 float() readcoord (EXT_CSQC)
-VM_CL_ReadAngle,                       //#365 float() readangle (EXT_CSQC)
-VM_CL_ReadString,                      //#366 string() readstring (EXT_CSQC)
-VM_CL_ReadFloat,                       //#367 float() readfloat (EXT_CSQC)
-0,                     //#368
-0,                     //#369
-0,                     //#370
-0,                     //#371
-0,                     //#372
-0,                     //#373
-0,                     //#374
-0,                     //#375
-0,                     //#376
-0,                     //#377
-0,                     //#378
-0,                     //#379
-0,                     //#380
-0,                     //#381
-0,                     //#382
-0,                     //#383
-0,                     //#384
-0,                     //#385
-0,                     //#386
-0,                     //#387
-0,                     //#388
-0,                     //#389
-0,                     //#390
-0,                     //#391
-0,                     //#392
-0,                     //#393
-0,                     //#394
-0,                     //#395
-0,                     //#396
-0,                     //#397
-0,                     //#398
-0,                     //#399
-//=========CSQC end========//
-
-VM_copyentity,                                 // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
-0,
+NULL,                                                  // #0 NULL function (not callable) (QUAKE)
+VM_CL_makevectors,                             // #1 void(vector ang) makevectors (QUAKE)
+VM_CL_setorigin,                               // #2 void(entity e, vector o) setorigin (QUAKE)
+VM_CL_setmodel,                                        // #3 void(entity e, string m) setmodel (QUAKE)
+VM_CL_setsize,                                 // #4 void(entity e, vector min, vector max) setsize (QUAKE)
+NULL,                                                  // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
+VM_break,                                              // #6 void() break (QUAKE)
+VM_random,                                             // #7 float() random (QUAKE)
+VM_CL_sound,                                   // #8 void(entity e, float chan, string samp) sound (QUAKE)
+VM_normalize,                                  // #9 vector(vector v) normalize (QUAKE)
+VM_error,                                              // #10 void(string e) error (QUAKE)
+VM_objerror,                                   // #11 void(string e) objerror (QUAKE)
+VM_vlen,                                               // #12 float(vector v) vlen (QUAKE)
+VM_vectoyaw,                                   // #13 float(vector v) vectoyaw (QUAKE)
+VM_CL_spawn,                                   // #14 entity() spawn (QUAKE)
+VM_remove,                                             // #15 void(entity e) remove (QUAKE)
+VM_CL_traceline,                               // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE)
+NULL,                                                  // #17 entity() checkclient (QUAKE)
+VM_find,                                               // #18 entity(entity start, .string fld, string match) find (QUAKE)
+VM_precache_sound,                             // #19 void(string s) precache_sound (QUAKE)
+VM_CL_precache_model,                  // #20 void(string s) precache_model (QUAKE)
+NULL,                                                  // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
+VM_CL_findradius,                              // #22 entity(vector org, float rad) findradius (QUAKE)
+NULL,                                                  // #23 void(string s, ...) bprint (QUAKE)
+NULL,                                                  // #24 void(entity client, string s, ...) sprint (QUAKE)
+VM_dprint,                                             // #25 void(string s, ...) dprint (QUAKE)
+VM_ftos,                                               // #26 string(float f) ftos (QUAKE)
+VM_vtos,                                               // #27 string(vector v) vtos (QUAKE)
+VM_coredump,                                   // #28 void() coredump (QUAKE)
+VM_traceon,                                            // #29 void() traceon (QUAKE)
+VM_traceoff,                                   // #30 void() traceoff (QUAKE)
+VM_eprint,                                             // #31 void(entity e) eprint (QUAKE)
+VM_CL_walkmove,                                        // #32 float(float yaw, float dist) walkmove (QUAKE)
+NULL,                                                  // #33 (QUAKE)
+VM_CL_droptofloor,                             // #34 float() droptofloor (QUAKE)
+VM_CL_lightstyle,                              // #35 void(float style, string value) lightstyle (QUAKE)
+VM_rint,                                               // #36 float(float v) rint (QUAKE)
+VM_floor,                                              // #37 float(float v) floor (QUAKE)
+VM_ceil,                                               // #38 float(float v) ceil (QUAKE)
+NULL,                                                  // #39 (QUAKE)
+VM_CL_checkbottom,                             // #40 float(entity e) checkbottom (QUAKE)
+VM_CL_pointcontents,                   // #41 float(vector v) pointcontents (QUAKE)
+NULL,                                                  // #42 (QUAKE)
+VM_fabs,                                               // #43 float(float f) fabs (QUAKE)
+NULL,                                                  // #44 vector(entity e, float speed) aim (QUAKE)
+VM_cvar,                                               // #45 float(string s) cvar (QUAKE)
+VM_localcmd,                                   // #46 void(string s) localcmd (QUAKE)
+VM_nextent,                                            // #47 entity(entity e) nextent (QUAKE)
+VM_CL_particle,                                        // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
+VM_changeyaw,                                  // #49 void() ChangeYaw (QUAKE)
+NULL,                                                  // #50 (QUAKE)
+VM_vectoangles,                                        // #51 vector(vector v) vectoangles (QUAKE)
+NULL,                                                  // #52 void(float to, float f) WriteByte (QUAKE)
+NULL,                                                  // #53 void(float to, float f) WriteChar (QUAKE)
+NULL,                                                  // #54 void(float to, float f) WriteShort (QUAKE)
+NULL,                                                  // #55 void(float to, float f) WriteLong (QUAKE)
+NULL,                                                  // #56 void(float to, float f) WriteCoord (QUAKE)
+NULL,                                                  // #57 void(float to, float f) WriteAngle (QUAKE)
+NULL,                                                  // #58 void(float to, string s) WriteString (QUAKE)
+NULL,                                                  // #59 (QUAKE)
+VM_sin,                                                        // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
+VM_cos,                                                        // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
+VM_sqrt,                                               // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
+VM_changepitch,                                        // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
+VM_CL_tracetoss,                               // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
+VM_etos,                                               // #65 string(entity ent) etos (DP_QC_ETOS)
+NULL,                                                  // #66 (QUAKE)
+NULL,                                                  // #67 void(float step) movetogoal (QUAKE)
+VM_precache_file,                              // #68 string(string s) precache_file (QUAKE)
+VM_CL_makestatic,                              // #69 void(entity e) makestatic (QUAKE)
+NULL,                                                  // #70 void(string s) changelevel (QUAKE)
+NULL,                                                  // #71 (QUAKE)
+VM_cvar_set,                                   // #72 void(string var, string val) cvar_set (QUAKE)
+NULL,                                                  // #73 void(entity client, strings) centerprint (QUAKE)
+VM_CL_ambientsound,                            // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
+VM_CL_precache_model,                  // #75 string(string s) precache_model2 (QUAKE)
+VM_precache_sound,                             // #76 string(string s) precache_sound2 (QUAKE)
+VM_precache_file,                              // #77 string(string s) precache_file2 (QUAKE)
+NULL,                                                  // #78 void(entity e) setspawnparms (QUAKE)
+NULL,                                                  // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
+NULL,                                                  // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
+VM_stof,                                               // #81 float(string s) stof (FRIK_FILE)
+NULL,                                                  // #82 void(vector where, float set) multicast (QUAKEWORLD)
+NULL,                                                  // #83 (QUAKE)
+NULL,                                                  // #84 (QUAKE)
+NULL,                                                  // #85 (QUAKE)
+NULL,                                                  // #86 (QUAKE)
+NULL,                                                  // #87 (QUAKE)
+NULL,                                                  // #88 (QUAKE)
+NULL,                                                  // #89 (QUAKE)
+VM_CL_tracebox,                                        // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
+VM_randomvec,                                  // #91 vector() randomvec (DP_QC_RANDOMVEC)
+VM_CL_getlight,                                        // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
+VM_registercvar,                               // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
+VM_min,                                                        // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
+VM_max,                                                        // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
+VM_bound,                                              // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
+VM_pow,                                                        // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
+VM_findfloat,                                  // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
+VM_checkextension,                             // #99 float(string s) checkextension (the basis of the extension system)
+// FrikaC and Telejano range #100-#199
+NULL,                                                  // #100
+NULL,                                                  // #101
+NULL,                                                  // #102
+NULL,                                                  // #103
+NULL,                                                  // #104
+NULL,                                                  // #105
+NULL,                                                  // #106
+NULL,                                                  // #107
+NULL,                                                  // #108
+NULL,                                                  // #109
+VM_fopen,                                              // #110 float(string filename, float mode) fopen (FRIK_FILE)
+VM_fclose,                                             // #111 void(float fhandle) fclose (FRIK_FILE)
+VM_fgets,                                              // #112 string(float fhandle) fgets (FRIK_FILE)
+VM_fputs,                                              // #113 void(float fhandle, string s) fputs (FRIK_FILE)
+VM_strlen,                                             // #114 float(string s) strlen (FRIK_FILE)
+VM_strcat,                                             // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
+VM_substring,                                  // #116 string(string s, float start, float length) substring (FRIK_FILE)
+VM_stov,                                               // #117 vector(string) stov (FRIK_FILE)
+VM_strzone,                                            // #118 string(string s) strzone (FRIK_FILE)
+VM_strunzone,                                  // #119 void(string s) strunzone (FRIK_FILE)
+NULL,                                                  // #120
+NULL,                                                  // #121
+NULL,                                                  // #122
+NULL,                                                  // #123
+NULL,                                                  // #124
+NULL,                                                  // #125
+NULL,                                                  // #126
+NULL,                                                  // #127
+NULL,                                                  // #128
+NULL,                                                  // #129
+NULL,                                                  // #130
+NULL,                                                  // #131
+NULL,                                                  // #132
+NULL,                                                  // #133
+NULL,                                                  // #134
+NULL,                                                  // #135
+NULL,                                                  // #136
+NULL,                                                  // #137
+NULL,                                                  // #138
+NULL,                                                  // #139
+NULL,                                                  // #140
+NULL,                                                  // #141
+NULL,                                                  // #142
+NULL,                                                  // #143
+NULL,                                                  // #144
+NULL,                                                  // #145
+NULL,                                                  // #146
+NULL,                                                  // #147
+NULL,                                                  // #148
+NULL,                                                  // #149
+NULL,                                                  // #150
+NULL,                                                  // #151
+NULL,                                                  // #152
+NULL,                                                  // #153
+NULL,                                                  // #154
+NULL,                                                  // #155
+NULL,                                                  // #156
+NULL,                                                  // #157
+NULL,                                                  // #158
+NULL,                                                  // #159
+NULL,                                                  // #160
+NULL,                                                  // #161
+NULL,                                                  // #162
+NULL,                                                  // #163
+NULL,                                                  // #164
+NULL,                                                  // #165
+NULL,                                                  // #166
+NULL,                                                  // #167
+NULL,                                                  // #168
+NULL,                                                  // #169
+NULL,                                                  // #170
+NULL,                                                  // #171
+NULL,                                                  // #172
+NULL,                                                  // #173
+NULL,                                                  // #174
+NULL,                                                  // #175
+NULL,                                                  // #176
+NULL,                                                  // #177
+NULL,                                                  // #178
+NULL,                                                  // #179
+NULL,                                                  // #180
+NULL,                                                  // #181
+NULL,                                                  // #182
+NULL,                                                  // #183
+NULL,                                                  // #184
+NULL,                                                  // #185
+NULL,                                                  // #186
+NULL,                                                  // #187
+NULL,                                                  // #188
+NULL,                                                  // #189
+NULL,                                                  // #190
+NULL,                                                  // #191
+NULL,                                                  // #192
+NULL,                                                  // #193
+NULL,                                                  // #194
+NULL,                                                  // #195
+NULL,                                                  // #196
+NULL,                                                  // #197
+NULL,                                                  // #198
+NULL,                                                  // #199
+// FTEQW range #200-#299
+NULL,                                                  // #200
+NULL,                                                  // #201
+NULL,                                                  // #202
+NULL,                                                  // #203
+NULL,                                                  // #204
+NULL,                                                  // #205
+NULL,                                                  // #206
+NULL,                                                  // #207
+NULL,                                                  // #208
+NULL,                                                  // #209
+NULL,                                                  // #210
+NULL,                                                  // #211
+NULL,                                                  // #212
+NULL,                                                  // #213
+NULL,                                                  // #214
+NULL,                                                  // #215
+NULL,                                                  // #216
+NULL,                                                  // #217
+VM_bitshift,                                   // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
+NULL,                                                  // #219
+NULL,                                                  // #220
+NULL,                                                  // #221
+VM_str2chr,                                            // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
+VM_chr2str,                                            // #223 string(float c, ...) chr2str (FTE_STRINGS)
+NULL,                                                  // #224
+NULL,                                                  // #225
+NULL,                                                  // #226
+NULL,                                                  // #227
+VM_strncmp,                                            // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
+NULL,                                                  // #229
+NULL,                                                  // #230
+NULL,                                                  // #231
+NULL,                                                  // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
+NULL,                                                  // #233
+NULL,                                                  // #234
+NULL,                                                  // #235
+NULL,                                                  // #236
+NULL,                                                  // #237
+NULL,                                                  // #238
+NULL,                                                  // #239
+NULL,                                                  // #240
+NULL,                                                  // #241
+NULL,                                                  // #242
+NULL,                                                  // #243
+NULL,                                                  // #244
+NULL,                                                  // #245
+NULL,                                                  // #246
+NULL,                                                  // #247
+NULL,                                                  // #248
+NULL,                                                  // #249
+NULL,                                                  // #250
+NULL,                                                  // #251
+NULL,                                                  // #252
+NULL,                                                  // #253
+NULL,                                                  // #254
+NULL,                                                  // #255
+NULL,                                                  // #256
+NULL,                                                  // #257
+NULL,                                                  // #258
+NULL,                                                  // #259
+NULL,                                                  // #260
+NULL,                                                  // #261
+NULL,                                                  // #262
+NULL,                                                  // #263
+NULL,                                                  // #264
+NULL,                                                  // #265
+NULL,                                                  // #266
+NULL,                                                  // #267
+NULL,                                                  // #268
+NULL,                                                  // #269
+NULL,                                                  // #270
+NULL,                                                  // #271
+NULL,                                                  // #272
+NULL,                                                  // #273
+NULL,                                                  // #274
+NULL,                                                  // #275
+NULL,                                                  // #276
+NULL,                                                  // #277
+NULL,                                                  // #278
+NULL,                                                  // #279
+NULL,                                                  // #280
+NULL,                                                  // #281
+NULL,                                                  // #282
+NULL,                                                  // #283
+NULL,                                                  // #284
+NULL,                                                  // #285
+NULL,                                                  // #286
+NULL,                                                  // #287
+NULL,                                                  // #288
+NULL,                                                  // #289
+NULL,                                                  // #290
+NULL,                                                  // #291
+NULL,                                                  // #292
+NULL,                                                  // #293
+NULL,                                                  // #294
+NULL,                                                  // #295
+NULL,                                                  // #296
+NULL,                                                  // #297
+NULL,                                                  // #298
+NULL,                                                  // #299
+// CSQC range #300-#399
+VM_CL_R_ClearScene,                            // #300 void() clearscene (EXT_CSQC)
+VM_CL_R_AddEntities,                   // #301 void(float mask) addentities (EXT_CSQC)
+VM_CL_R_AddEntity,                             // #302 void(entity ent) addentity (EXT_CSQC)
+VM_CL_R_SetView,                               // #303 float(float property, ...) setproperty (EXT_CSQC)
+VM_CL_R_RenderScene,                   // #304 void() renderscene (EXT_CSQC)
+VM_CL_R_AddDynamicLight,               // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
+VM_CL_R_PolygonBegin,                  // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
+VM_CL_R_PolygonVertex,                 // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
+VM_CL_R_PolygonEnd,                            // #308 void() R_EndPolygon
+NULL,                                                  // #309
+VM_CL_unproject,                               // #310 vector (vector v) cs_unproject (EXT_CSQC)
+VM_CL_project,                                 // #311 vector (vector v) cs_project (EXT_CSQC)
+NULL,                                                  // #312
+NULL,                                                  // #313
+NULL,                                                  // #314
+VM_drawline,                                   // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
+VM_iscachedpic,                                        // #316 float(string name) iscachedpic (EXT_CSQC)
+VM_precache_pic,                               // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
+VM_getimagesize,                               // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
+VM_freepic,                                            // #319 void(string name) freepic (EXT_CSQC)
+VM_drawcharacter,                              // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
+VM_drawstring,                                 // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
+VM_drawpic,                                            // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
+VM_drawfill,                                   // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
+VM_drawsetcliparea,                            // #324 void(float x, float y, float width, float height) drawsetcliparea
+VM_drawresetcliparea,                  // #325 void(void) drawresetcliparea
+NULL,                                                  // #326
+NULL,                                                  // #327
+NULL,                                                  // #328
+NULL,                                                  // #329
+VM_CL_getstatf,                                        // #330 float(float stnum) getstatf (EXT_CSQC)
+VM_CL_getstati,                                        // #331 float(float stnum) getstati (EXT_CSQC)
+VM_CL_getstats,                                        // #332 string(float firststnum) getstats (EXT_CSQC)
+VM_CL_setmodelindex,                   // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
+VM_CL_modelnameforindex,               // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
+VM_CL_particleeffectnum,               // #335 float(string effectname) particleeffectnum (EXT_CSQC)
+VM_CL_trailparticles,                  // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
+VM_CL_pointparticles,                  // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
+VM_centerprint,                                        // #338 void(string s, ...) centerprint (EXT_CSQC)
+VM_print,                                              // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
+VM_keynumtostring,                             // #340 string(float keynum) keynumtostring (EXT_CSQC)
+VM_stringtokeynum,                             // #341 float(string keyname) stringtokeynum (EXT_CSQC)
+VM_CL_getkeybind,                              // #342 string(float keynum) getkeybind (EXT_CSQC)
+VM_CL_setcursormode,                   // #343 void(float usecursor) setcursormode (EXT_CSQC)
+VM_getmousepos,                                        // #344 vector() getmousepos (EXT_CSQC)
+VM_CL_getinputstate,                   // #345 float(float framenum) getinputstate (EXT_CSQC)
+VM_CL_setsensitivityscale,             // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
+VM_CL_runplayerphysics,                        // #347 void() runstandardplayerphysics (EXT_CSQC)
+VM_CL_getplayerkey,                            // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
+VM_CL_isdemo,                                  // #349 float() isdemo (EXT_CSQC)
+VM_isserver,                                   // #350 float() isserver (EXT_CSQC)
+VM_CL_setlistener,                             // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
+VM_CL_registercmd,                             // #352 void(string cmdname) registercommand (EXT_CSQC)
+VM_wasfreed,                                   // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
+VM_CL_serverkey,                               // #354 string(string key) serverkey (EXT_CSQC)
+NULL,                                                  // #355
+NULL,                                                  // #356
+NULL,                                                  // #357
+NULL,                                                  // #358
+NULL,                                                  // #359
+VM_CL_ReadByte,                                        // #360 float() readbyte (EXT_CSQC)
+VM_CL_ReadChar,                                        // #361 float() readchar (EXT_CSQC)
+VM_CL_ReadShort,                               // #362 float() readshort (EXT_CSQC)
+VM_CL_ReadLong,                                        // #363 float() readlong (EXT_CSQC)
+VM_CL_ReadCoord,                               // #364 float() readcoord (EXT_CSQC)
+VM_CL_ReadAngle,                               // #365 float() readangle (EXT_CSQC)
+VM_CL_ReadString,                              // #366 string() readstring (EXT_CSQC)
+VM_CL_ReadFloat,                               // #367 float() readfloat (EXT_CSQC)
+NULL,                                                  // #368
+NULL,                                                  // #369
+NULL,                                                  // #370
+NULL,                                                  // #371
+NULL,                                                  // #372
+NULL,                                                  // #373
+NULL,                                                  // #374
+NULL,                                                  // #375
+NULL,                                                  // #376
+NULL,                                                  // #377
+NULL,                                                  // #378
+NULL,                                                  // #379
+NULL,                                                  // #380
+NULL,                                                  // #381
+NULL,                                                  // #382
+NULL,                                                  // #383
+NULL,                                                  // #384
+NULL,                                                  // #385
+NULL,                                                  // #386
+NULL,                                                  // #387
+NULL,                                                  // #388
+NULL,                                                  // #389
+NULL,                                                  // #390
+NULL,                                                  // #391
+NULL,                                                  // #392
+NULL,                                                  // #393
+NULL,                                                  // #394
+NULL,                                                  // #395
+NULL,                                                  // #396
+NULL,                                                  // #397
+NULL,                                                  // #398
+NULL,                                                  // #399
+// LordHavoc's range #400-#499
+VM_CL_copyentity,                              // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
+NULL,                                                  // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
 VM_findchain,                                  // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
 VM_findchainfloat,                             // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
 VM_CL_effect,                                  // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
@@ -2366,56 +3121,86 @@ VM_CL_getsurfacenormal,                 // #436 vector(entity e, float s) getsurfacenormal (DP
 VM_CL_getsurfacetexture,               // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
 VM_CL_getsurfacenearpoint,             // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
 VM_CL_getsurfaceclippedpoint,  // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
-0,                                                                     // #440
-VM_tokenize,                           // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
-VM_argv,                                       // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
-VM_CL_setattachment,           // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
-VM_search_begin,                       // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
-VM_search_end,                         // #445 void(float handle) search_end (DP_FS_SEARCH)
-VM_search_getsize,                     // #446 float(float handle) search_getsize (DP_FS_SEARCH)
-VM_search_getfilename,         // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
-VM_cvar_string,                                // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
-VM_findflags,                          // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
-VM_findchainflags,                     // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
-VM_CL_gettagindex,                     // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
-VM_CL_gettaginfo,                      // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
-0,                                                             // #453
-0,                                                             // #454
-0,                                                             // #455
-NULL,                                          // #456
-NULL,                                          // #457
-NULL,                                          // #458
-NULL,                                          // #459
-VM_buf_create,                         // #460 float() buf_create (DP_QC_STRINGBUFFERS)
-VM_buf_del,                                    // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
-VM_buf_getsize,                                // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
-VM_buf_copy,                           // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
-VM_buf_sort,                           // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
-VM_buf_implode,                                // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
-VM_bufstr_get,                         // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
-VM_bufstr_set,                         // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
-VM_bufstr_add,                         // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
-VM_bufstr_free,                                // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
-NULL,                                          // #470
-VM_asin,                                       // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
-VM_acos,                                       // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
-VM_atan,                                       // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
-VM_atan2,                                      // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
-VM_tan,                                                // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
-VM_strlennocol,                                // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
-VM_strdecolorize,                      // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS)
-VM_strftime,                           // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
-NULL,                                          // #479
-e10, e10                       // #480-499 (LordHavoc)
+NULL,                                                  // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
+VM_tokenize,                                   // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
+VM_argv,                                               // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
+VM_CL_setattachment,                   // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
+VM_search_begin,                               // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
+VM_search_end,                                 // #445 void(float handle) search_end (DP_FS_SEARCH)
+VM_search_getsize,                             // #446 float(float handle) search_getsize (DP_FS_SEARCH)
+VM_search_getfilename,                 // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
+VM_cvar_string,                                        // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
+VM_findflags,                                  // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
+VM_findchainflags,                             // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
+VM_CL_gettagindex,                             // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
+VM_CL_gettaginfo,                              // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
+NULL,                                                  // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
+NULL,                                                  // #454 entity() spawnclient (DP_SV_BOTCLIENT)
+NULL,                                                  // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
+NULL,                                                  // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
+VM_CL_te_flamejet,                             // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
+NULL,                                                  // #458
+VM_ftoe,                                               // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
+VM_buf_create,                                 // #460 float() buf_create (DP_QC_STRINGBUFFERS)
+VM_buf_del,                                            // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
+VM_buf_getsize,                                        // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
+VM_buf_copy,                                   // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
+VM_buf_sort,                                   // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
+VM_buf_implode,                                        // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
+VM_bufstr_get,                                 // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
+VM_bufstr_set,                                 // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
+VM_bufstr_add,                                 // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
+VM_bufstr_free,                                        // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
+NULL,                                                  // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
+VM_asin,                                               // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
+VM_acos,                                               // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
+VM_atan,                                               // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
+VM_atan2,                                              // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
+VM_tan,                                                        // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
+VM_strlennocol,                                        // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
+VM_strdecolorize,                              // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS)
+VM_strftime,                                   // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
+NULL,                                                  // #479
+NULL,                                                  // #480
+NULL,                                                  // #481
+NULL,                                                  // #482
+NULL,                                                  // #483
+NULL,                                                  // #484
+NULL,                                                  // #485
+NULL,                                                  // #486
+NULL,                                                  // #487
+NULL,                                                  // #488
+NULL,                                                  // #489
+NULL,                                                  // #490
+NULL,                                                  // #491
+NULL,                                                  // #492
+NULL,                                                  // #493
+NULL,                                                  // #494
+NULL,                                                  // #495
+NULL,                                                  // #496
+NULL,                                                  // #497
+NULL,                                                  // #498
+NULL,                                                  // #499
 };
 
 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
 
 void VM_CL_Cmd_Init(void)
 {
+       // TODO: replace vm_polygons stuff with a more general debugging polygon system, and make vm_polygons functions use that system
+       if(vm_polygons_initialized)
+       {
+               Mem_FreePool(&vm_polygons_pool);
+               vm_polygons_initialized = false;
+       }
 }
 
 void VM_CL_Cmd_Reset(void)
 {
+       if(vm_polygons_initialized)
+       {
+               Mem_FreePool(&vm_polygons_pool);
+               vm_polygons_initialized = false;
+       }
 }
 
index 343f8a1..1268888 100644 (file)
--- a/csprogs.c
+++ b/csprogs.c
@@ -2,6 +2,7 @@
 #include "progsvm.h"
 #include "clprogdefs.h"
 #include "csprogs.h"
+#include "cl_collision.h"
 
 //============================================================================
 // Client prog handling
@@ -56,31 +57,6 @@ void CL_VM_Error (const char *format, ...)   //[515]: hope it will be never execut
        Host_Error(va("CL_VM_Error: %s", errorstring));
 }
 
-model_t *CSQC_GetModelByIndex(int modelindex)
-{
-       if(!modelindex)
-               return NULL;
-       if (modelindex < 0)
-       {
-               modelindex = -(modelindex+1);
-               if (modelindex < MAX_MODELS)
-                       return cl.csqc_model_precache[modelindex];
-       }
-       else
-       {
-               if(modelindex < MAX_MODELS)
-                       return cl.model_precache[modelindex];
-       }
-       return NULL;
-}
-
-model_t *CSQC_GetModelFromEntity(prvm_edict_t *ed)
-{
-       if (!ed || ed->priv.server->free)
-               return NULL;
-       return CSQC_GetModelByIndex((int)ed->fields.client->modelindex);
-}
-
 //[515]: set globals before calling R_UpdateView, WEIRD CRAP
 static void CSQC_SetGlobals (void)
 {
@@ -140,7 +116,7 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed)
        model_t *model;
        matrix4x4_t tagmatrix, matrix2;
 
-       model = CSQC_GetModelFromEntity(ed);
+       model = CL_GetModelFromEdict(ed);
        if (!model)
                return false;
 
@@ -154,14 +130,8 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed)
        e->render.skinnum = (int)ed->fields.client->skin;
        e->render.effects |= e->render.model->flags2 & (EF_FULLBRIGHT | EF_ADDITIVE);
        scale = 1;
-       // FIXME: renderflags should be in the cl_entvars_t
-#if 1
        renderflags = 0;
        if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.renderflags)) && val->_float)     renderflags = (int)val->_float;
-#else
-       renderflags = (int)ed->fields.client->renderflags;
-#endif
-
        if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.alpha)) && val->_float)           e->render.alpha = val->_float;
        if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.scale)) && val->_float)           e->render.scale = scale = val->_float;
        if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.colormod)) && VectorLength2(val->vector)) VectorCopy(val->vector, e->render.colormod);
@@ -184,6 +154,7 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed)
                vec3_t left;
                VectorNegate(prog->globals.client->v_right, left);
                Matrix4x4_FromVectors(&matrix2, prog->globals.client->v_forward, left, prog->globals.client->v_up, ed->fields.client->origin);
+               Matrix4x4_Scale(&matrix2, scale, 1);
        }
        else
        {
@@ -474,20 +445,6 @@ void CSQC_ReadEntities (void)
        CSQC_END
 }
 
-void CL_LinkEdict(prvm_edict_t *ent)
-{
-       if (ent == prog->edicts)
-               return;         // don't add the world
-
-       if (ent->priv.server->free)
-               return;
-
-       VectorAdd(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->absmin);
-       VectorAdd(ent->fields.client->origin, ent->fields.client->maxs, ent->fields.client->absmax);
-
-       World_LinkEdict(&cl.world, ent, ent->fields.client->absmin, ent->fields.client->absmax);
-}
-
 void CL_VM_CB_BeginIncreaseEdicts(void)
 {
        int i;
index dd4cfb3..f6475aa 100644 (file)
@@ -1212,7 +1212,7 @@ void GL_Init (void)
        VID_CheckExtensions();
 
        // LordHavoc: report supported extensions
-       Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
+       Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
 
        // clear to black (loading plaque will be seen over this)
        CHECKGLERROR
@@ -2107,7 +2107,7 @@ void R_RenderView(void)
 }
 
 extern void R_DrawLightningBeams (void);
-extern void VM_AddPolygonsToMeshQueue (void);
+extern void VM_CL_AddPolygonsToMeshQueue (void);
 extern void R_DrawPortals (void);
 void R_RenderScene(void)
 {
@@ -2197,7 +2197,7 @@ void R_RenderScene(void)
        {
                qglUseProgramObjectARB(0);CHECKGLERROR
        }
-       VM_AddPolygonsToMeshQueue();
+       VM_CL_AddPolygonsToMeshQueue();
 
        if (r_drawportals.integer)
        {
index b53f528..abd29d4 100644 (file)
@@ -14,57 +14,6 @@ char *vm_m_extensions =
 
 /*
 =========
-VM_M_precache_file
-
-string precache_file(string)
-=========
-*/
-void VM_M_precache_file (void)
-{      // precache_file is only used to copy files with qcc, it does nothing
-       VM_SAFEPARMCOUNT(1,VM_precache_file);
-
-       PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
-}
-
-/*
-=========
-VM_M_preache_error
-
-used instead of the other VM_precache_* functions in the builtin list
-=========
-*/
-
-void VM_M_precache_error (void)
-{
-       PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
-}
-
-/*
-=========
-VM_M_precache_sound
-
-string precache_sound (string sample)
-=========
-*/
-void VM_M_precache_sound (void)
-{
-       const char      *s;
-
-       VM_SAFEPARMCOUNT(1, VM_precache_sound);
-
-       s = PRVM_G_STRING(OFS_PARM0);
-       PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
-       VM_CheckEmptyString (s);
-
-       if(snd_initialized.integer && !S_PrecacheSound (s,true, true))
-       {
-               VM_Warning("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
-               return;
-       }
-}
-
-/*
-=========
 VM_M_setmousetarget
 
 setmousetarget(float target)
@@ -179,8 +128,7 @@ void VM_M_callfunction(void)
        mfunction_t *func;
        const char *s;
 
-       if(prog->argc == 0)
-               PRVM_ERROR("VM_M_callfunction: 1 parameter is required !");
+       VM_SAFEPARMCOUNTRANGE(1, 8, VM_M_callfunction);
 
        s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
 
@@ -237,37 +185,6 @@ void VM_M_isfunction(void)
 
 /*
 =========
-VM_M_writetofile
-
-       writetofile(float fhandle, entity ent)
-=========
-*/
-void VM_M_writetofile(void)
-{
-       prvm_edict_t * ent;
-       qfile_t *file;
-
-       VM_SAFEPARMCOUNT(2, VM_M_writetofile);
-
-       file = VM_GetFileHandle( (int)PRVM_G_FLOAT(OFS_PARM0) );
-       if( !file )
-       {
-               VM_Warning("VM_M_writetofile: invalid or closed file handle\n");
-               return;
-       }
-
-       ent = PRVM_G_EDICT(OFS_PARM1);
-       if(ent->priv.required->free)
-       {
-               VM_Warning("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
-               return;
-       }
-
-       PRVM_ED_Write (file, ent);
-}
-
-/*
-=========
 VM_M_getresolution
 
 vector getresolution(float number)
@@ -386,6 +303,7 @@ resetserverlistmasks()
 */
 void VM_M_resetserverlistmasks( void )
 {
+       VM_SAFEPARMCOUNT(0, VM_M_resetserverlistmasks);
        ServerList_ResetMasks();
 }
 
@@ -511,6 +429,7 @@ resortserverlist
 */
 void VM_M_resortserverlist( void )
 {
+       VM_SAFEPARMCOUNT(0, VM_M_resortserverlist);
        ServerList_RebuildViewList();
 }
 
@@ -690,7 +609,7 @@ void VM_M_addwantedserverlistkey( void )
 MESSAGE WRITING
 
 used only for client and menu
-severs uses VM_SV_...
+server uses VM_SV_...
 
 Write*(* data, float type, float to)
 
@@ -702,13 +621,13 @@ Write*(* data, float type, float to)
 #define        MSG_ALL                 2               // reliable to all
 #define        MSG_INIT                3               // write to the init string
 
-sizebuf_t *VM_WriteDest (void)
+sizebuf_t *VM_M_WriteDest (void)
 {
        int             dest;
        int             destclient;
 
        if(!sv.active)
-               PRVM_ERROR("VM_WriteDest: game is not server (%s)", PRVM_NAME);
+               PRVM_ERROR("VM_M_WriteDest: game is not server (%s)", PRVM_NAME);
 
        dest = (int)PRVM_G_FLOAT(OFS_PARM1);
        switch (dest)
@@ -739,42 +658,50 @@ sizebuf_t *VM_WriteDest (void)
 
 void VM_M_WriteByte (void)
 {
-       MSG_WriteByte (VM_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
+       VM_SAFEPARMCOUNT(1, VM_M_WriteByte);
+       MSG_WriteByte (VM_M_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
 }
 
 void VM_M_WriteChar (void)
 {
-       MSG_WriteChar (VM_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
+       VM_SAFEPARMCOUNT(1, VM_M_WriteChar);
+       MSG_WriteChar (VM_M_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
 }
 
 void VM_M_WriteShort (void)
 {
-       MSG_WriteShort (VM_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
+       VM_SAFEPARMCOUNT(1, VM_M_WriteShort);
+       MSG_WriteShort (VM_M_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
 }
 
 void VM_M_WriteLong (void)
 {
-       MSG_WriteLong (VM_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
+       VM_SAFEPARMCOUNT(1, VM_M_WriteLong);
+       MSG_WriteLong (VM_M_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
 }
 
 void VM_M_WriteAngle (void)
 {
-       MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
+       VM_SAFEPARMCOUNT(1, VM_M_WriteAngle);
+       MSG_WriteAngle (VM_M_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
 }
 
 void VM_M_WriteCoord (void)
 {
-       MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
+       VM_SAFEPARMCOUNT(1, VM_M_WriteCoord);
+       MSG_WriteCoord (VM_M_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
 }
 
 void VM_M_WriteString (void)
 {
-       MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
+       VM_SAFEPARMCOUNT(1, VM_M_WriteString);
+       MSG_WriteString (VM_M_WriteDest(), PRVM_G_STRING(OFS_PARM0));
 }
 
 void VM_M_WriteEntity (void)
 {
-       MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
+       VM_SAFEPARMCOUNT(1, VM_M_WriteEntity);
+       MSG_WriteShort (VM_M_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
 }
 
 //string(void) getextresponse = #624; // returns the next extResponse packet that was sent to this client
@@ -793,174 +720,650 @@ void VM_M_getextresponse (void)
        }
 }
 
+/*
+=================
+VM_M_copyentity
+
+copies data from one entity to another
+
+copyentity(entity src, entity dst)
+=================
+*/
+static void VM_M_copyentity (void)
+{
+       prvm_edict_t *in, *out;
+       VM_SAFEPARMCOUNT(2,VM_M_copyentity);
+       in = PRVM_G_EDICT(OFS_PARM0);
+       out = PRVM_G_EDICT(OFS_PARM1);
+       memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
+}
+
 prvm_builtin_t vm_m_builtins[] = {
-       0, // to be consistent with the old vm
-       // common builtings (mostly)
-       VM_checkextension,
-       VM_error,
-       VM_objerror,
-       VM_print,
-       VM_bprint,
-       VM_sprint,
-       VM_centerprint,
-       VM_normalize,
-       VM_vlen,
-       VM_vectoyaw,    // #10
-       VM_vectoangles,
-       VM_random,
-       VM_localcmd,
-       VM_cvar,
-       VM_cvar_set,
-       VM_dprint,
-       VM_ftos,
-       VM_fabs,
-       VM_vtos,
-       VM_etos,                // 20
-       VM_stof,
-       VM_spawn,
-       VM_remove,
-       VM_find,
-       VM_findfloat,
-       VM_findchain,
-       VM_findchainfloat,
-       VM_M_precache_file,
-       VM_M_precache_sound,
-       VM_coredump,    // 30
-       VM_traceon,
-       VM_traceoff,
-       VM_eprint,
-       VM_rint,
-       VM_floor,
-       VM_ceil,
-       VM_nextent,
-       VM_sin,
-       VM_cos,
-       VM_sqrt,                // 40
-       VM_randomvec,
-       VM_registercvar,
-       VM_min,
-       VM_max,
-       VM_bound,
-       VM_pow,
-       VM_copyentity,
-       VM_fopen,
-       VM_fclose,
-       VM_fgets,               // 50
-       VM_fputs,
-       VM_strlen,
-       VM_strcat,
-       VM_substring,
-       VM_stov,
-       VM_strzone,
-       VM_strunzone,
-       VM_tokenize,
-       VM_argv,
-       VM_isserver,    // 60
-       VM_clientcount,
-       VM_clientstate,
-       VM_clcommand,
-       VM_changelevel,
-       VM_localsound,
-       VM_getmousepos,
-       VM_gettime,
-       VM_loadfromdata,
-       VM_loadfromfile,
-       VM_modulo,              // 70
-       VM_cvar_string,
-       VM_crash,
-       VM_stackdump,   // 73
-       VM_search_begin,
-       VM_search_end,
-       VM_search_getsize,
-       VM_search_getfilename, // 77
-       VM_chr,
-       VM_itof,
-       VM_ftoe,                // 80
-       VM_itof,                // isString
-       VM_altstr_count,
-       VM_altstr_prepare,
-       VM_altstr_get,
-       VM_altstr_set,
-       VM_altstr_ins,
-       VM_findflags,
-       VM_findchainflags,
-       VM_cvar_defstring, // 89
-       0, // 90
-       e10,                    // 100
-       e100,                   // 200
-       e100,                   // 300
-       e100,                   // 400
-       // msg functions
-       VM_M_WriteByte,
-       VM_M_WriteChar,
-       VM_M_WriteShort,
-       VM_M_WriteLong,
-       VM_M_WriteAngle,
-       VM_M_WriteCoord,
-       VM_M_WriteString,
-       VM_M_WriteEntity,       // 408
-       0,
-       0,                              // 410
-       e10,                    // 420
-       e10,                    // 430
-       e10,                    // 440
-       e10,                    // 450
-       // draw functions
-       VM_iscachedpic,
-       VM_precache_pic,
-       VM_freepic,
-       VM_drawcharacter,
-       VM_drawstring,
-       VM_drawpic,
-       VM_drawfill,
-       VM_drawsetcliparea,
-       VM_drawresetcliparea,
-       VM_getimagesize,// 460
-       VM_cin_open,
-       VM_cin_close,
-       VM_cin_setstate,
-       VM_cin_getstate,
-       VM_cin_restart, // 465
-       VM_drawline,    // 466
-       0,0,0,0,        // 470
-       VM_asin,                                        // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
-       VM_acos,                                        // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
-       VM_atan,                                        // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
-       VM_atan2,                                       // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
-       VM_tan,                                         // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
-       VM_strlennocol,                         // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
-       VM_strdecolorize,                       // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS)
-       VM_strftime,                            // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
-       0,                              // 479
-       0,                              // 480
-       e10,                    // 490
-       e10,                    // 500
-       e100,                   // 600
-       // menu functions
-       VM_M_setkeydest,
-       VM_M_getkeydest,
-       VM_M_setmousetarget,
-       VM_M_getmousetarget,
-       VM_M_callfunction,
-       VM_M_writetofile,
-       VM_M_isfunction,
-       VM_M_getresolution,
-       VM_keynumtostring,
-       VM_M_findkeysforcommand,// 610
-       VM_M_getserverliststat,
-       VM_M_getserverliststring,
-       VM_parseentitydata,
-       VM_stringtokeynum,
-       VM_M_resetserverlistmasks,
-       VM_M_setserverlistmaskstring,
-       VM_M_setserverlistmasknumber,
-       VM_M_resortserverlist,
-       VM_M_setserverlistsort,
-       VM_M_refreshserverlist,
-       VM_M_getserverlistnumber,
-       VM_M_getserverlistindexforkey,
-       VM_M_addwantedserverlistkey, // 623
-       VM_M_getextresponse
+NULL,                                          //   #0 NULL function (not callable)
+VM_checkextension,                     //   #1
+VM_error,                                      //   #2
+VM_objerror,                           //   #3
+VM_print,                                      //   #4
+VM_bprint,                                     //   #5
+VM_sprint,                                     //   #6
+VM_centerprint,                                //   #7
+VM_normalize,                          //   #8
+VM_vlen,                                       //   #9
+VM_vectoyaw,                           //  #10
+VM_vectoangles,                                //  #11
+VM_random,                                     //  #12
+VM_localcmd,                           //  #13
+VM_cvar,                                       //  #14
+VM_cvar_set,                           //  #15
+VM_dprint,                                     //  #16
+VM_ftos,                                       //  #17
+VM_fabs,                                       //  #18
+VM_vtos,                                       //  #19
+VM_etos,                                       //  #20
+VM_stof,                                       //  #21
+VM_spawn,                                      //  #22
+VM_remove,                                     //  #23
+VM_find,                                       //  #24
+VM_findfloat,                          //  #25
+VM_findchain,                          //  #26
+VM_findchainfloat,                     //  #27
+VM_precache_file,                      //  #28
+VM_precache_sound,                     //  #29
+VM_coredump,                           //  #30
+VM_traceon,                                    //  #31
+VM_traceoff,                           //  #32
+VM_eprint,                                     //  #33
+VM_rint,                                       //  #34
+VM_floor,                                      //  #35
+VM_ceil,                                       //  #36
+VM_nextent,                                    //  #37
+VM_sin,                                                //  #38
+VM_cos,                                                //  #39
+VM_sqrt,                                       //  #40
+VM_randomvec,                          //  #41
+VM_registercvar,                       //  #42
+VM_min,                                                //  #43
+VM_max,                                                //  #44
+VM_bound,                                      //  #45
+VM_pow,                                                //  #46
+VM_M_copyentity,                       //  #47
+VM_fopen,                                      //  #48
+VM_fclose,                                     //  #49
+VM_fgets,                                      //  #50
+VM_fputs,                                      //  #51
+VM_strlen,                                     //  #52
+VM_strcat,                                     //  #53
+VM_substring,                          //  #54
+VM_stov,                                       //  #55
+VM_strzone,                                    //  #56
+VM_strunzone,                          //  #57
+VM_tokenize,                           //  #58
+VM_argv,                                       //  #59
+VM_isserver,                           //  #60
+VM_clientcount,                                //  #61
+VM_clientstate,                                //  #62
+VM_clcommand,                          //  #63
+VM_changelevel,                                //  #64
+VM_localsound,                         //  #65
+VM_getmousepos,                                //  #66
+VM_gettime,                                    //  #67
+VM_loadfromdata,                       //  #68
+VM_loadfromfile,                       //  #69
+VM_modulo,                                     //  #70
+VM_cvar_string,                                //  #71
+VM_crash,                                      //  #72
+VM_stackdump,                          //  #73
+VM_search_begin,                       //  #74
+VM_search_end,                         //  #75
+VM_search_getsize,                     //  #76
+VM_search_getfilename,         //  #77
+VM_chr,                                                //  #78
+VM_itof,                                       //  #79
+VM_ftoe,                                       //  #80
+VM_itof,                                       //  #81 isString
+VM_altstr_count,                       //  #82
+VM_altstr_prepare,                     //  #83
+VM_altstr_get,                         //  #84
+VM_altstr_set,                         //  #85
+VM_altstr_ins,                         //  #86
+VM_findflags,                          //  #87
+VM_findchainflags,                     //  #88
+VM_cvar_defstring,                     //  #89
+NULL,                                          //  #90
+NULL,                                          //  #91
+NULL,                                          //  #92
+NULL,                                          //  #93
+NULL,                                          //  #94
+NULL,                                          //  #95
+NULL,                                          //  #96
+NULL,                                          //  #97
+NULL,                                          //  #98
+NULL,                                          //  #99
+NULL,                                          // #100
+NULL,                                          // #101
+NULL,                                          // #102
+NULL,                                          // #103
+NULL,                                          // #104
+NULL,                                          // #105
+NULL,                                          // #106
+NULL,                                          // #107
+NULL,                                          // #108
+NULL,                                          // #109
+NULL,                                          // #110
+NULL,                                          // #111
+NULL,                                          // #112
+NULL,                                          // #113
+NULL,                                          // #114
+NULL,                                          // #115
+NULL,                                          // #116
+NULL,                                          // #117
+NULL,                                          // #118
+NULL,                                          // #119
+NULL,                                          // #120
+NULL,                                          // #121
+NULL,                                          // #122
+NULL,                                          // #123
+NULL,                                          // #124
+NULL,                                          // #125
+NULL,                                          // #126
+NULL,                                          // #127
+NULL,                                          // #128
+NULL,                                          // #129
+NULL,                                          // #130
+NULL,                                          // #131
+NULL,                                          // #132
+NULL,                                          // #133
+NULL,                                          // #134
+NULL,                                          // #135
+NULL,                                          // #136
+NULL,                                          // #137
+NULL,                                          // #138
+NULL,                                          // #139
+NULL,                                          // #140
+NULL,                                          // #141
+NULL,                                          // #142
+NULL,                                          // #143
+NULL,                                          // #144
+NULL,                                          // #145
+NULL,                                          // #146
+NULL,                                          // #147
+NULL,                                          // #148
+NULL,                                          // #149
+NULL,                                          // #150
+NULL,                                          // #151
+NULL,                                          // #152
+NULL,                                          // #153
+NULL,                                          // #154
+NULL,                                          // #155
+NULL,                                          // #156
+NULL,                                          // #157
+NULL,                                          // #158
+NULL,                                          // #159
+NULL,                                          // #160
+NULL,                                          // #161
+NULL,                                          // #162
+NULL,                                          // #163
+NULL,                                          // #164
+NULL,                                          // #165
+NULL,                                          // #166
+NULL,                                          // #167
+NULL,                                          // #168
+NULL,                                          // #169
+NULL,                                          // #170
+NULL,                                          // #171
+NULL,                                          // #172
+NULL,                                          // #173
+NULL,                                          // #174
+NULL,                                          // #175
+NULL,                                          // #176
+NULL,                                          // #177
+NULL,                                          // #178
+NULL,                                          // #179
+NULL,                                          // #180
+NULL,                                          // #181
+NULL,                                          // #182
+NULL,                                          // #183
+NULL,                                          // #184
+NULL,                                          // #185
+NULL,                                          // #186
+NULL,                                          // #187
+NULL,                                          // #188
+NULL,                                          // #189
+NULL,                                          // #190
+NULL,                                          // #191
+NULL,                                          // #192
+NULL,                                          // #193
+NULL,                                          // #194
+NULL,                                          // #195
+NULL,                                          // #196
+NULL,                                          // #197
+NULL,                                          // #198
+NULL,                                          // #199
+NULL,                                          // #200
+NULL,                                          // #201
+NULL,                                          // #202
+NULL,                                          // #203
+NULL,                                          // #204
+NULL,                                          // #205
+NULL,                                          // #206
+NULL,                                          // #207
+NULL,                                          // #208
+NULL,                                          // #209
+NULL,                                          // #210
+NULL,                                          // #211
+NULL,                                          // #212
+NULL,                                          // #213
+NULL,                                          // #214
+NULL,                                          // #215
+NULL,                                          // #216
+NULL,                                          // #217
+NULL,                                          // #218
+NULL,                                          // #219
+NULL,                                          // #220
+NULL,                                          // #221
+NULL,                                          // #222
+NULL,                                          // #223
+NULL,                                          // #224
+NULL,                                          // #225
+NULL,                                          // #226
+NULL,                                          // #227
+NULL,                                          // #228
+NULL,                                          // #229
+NULL,                                          // #230
+NULL,                                          // #231
+NULL,                                          // #232
+NULL,                                          // #233
+NULL,                                          // #234
+NULL,                                          // #235
+NULL,                                          // #236
+NULL,                                          // #237
+NULL,                                          // #238
+NULL,                                          // #239
+NULL,                                          // #240
+NULL,                                          // #241
+NULL,                                          // #242
+NULL,                                          // #243
+NULL,                                          // #244
+NULL,                                          // #245
+NULL,                                          // #246
+NULL,                                          // #247
+NULL,                                          // #248
+NULL,                                          // #249
+NULL,                                          // #250
+NULL,                                          // #251
+NULL,                                          // #252
+NULL,                                          // #253
+NULL,                                          // #254
+NULL,                                          // #255
+NULL,                                          // #256
+NULL,                                          // #257
+NULL,                                          // #258
+NULL,                                          // #259
+NULL,                                          // #260
+NULL,                                          // #261
+NULL,                                          // #262
+NULL,                                          // #263
+NULL,                                          // #264
+NULL,                                          // #265
+NULL,                                          // #266
+NULL,                                          // #267
+NULL,                                          // #268
+NULL,                                          // #269
+NULL,                                          // #270
+NULL,                                          // #271
+NULL,                                          // #272
+NULL,                                          // #273
+NULL,                                          // #274
+NULL,                                          // #275
+NULL,                                          // #276
+NULL,                                          // #277
+NULL,                                          // #278
+NULL,                                          // #279
+NULL,                                          // #280
+NULL,                                          // #281
+NULL,                                          // #282
+NULL,                                          // #283
+NULL,                                          // #284
+NULL,                                          // #285
+NULL,                                          // #286
+NULL,                                          // #287
+NULL,                                          // #288
+NULL,                                          // #289
+NULL,                                          // #290
+NULL,                                          // #291
+NULL,                                          // #292
+NULL,                                          // #293
+NULL,                                          // #294
+NULL,                                          // #295
+NULL,                                          // #296
+NULL,                                          // #297
+NULL,                                          // #298
+NULL,                                          // #299
+NULL,                                          // #300
+NULL,                                          // #301
+NULL,                                          // #302
+NULL,                                          // #303
+NULL,                                          // #304
+NULL,                                          // #305
+NULL,                                          // #306
+NULL,                                          // #307
+NULL,                                          // #308
+NULL,                                          // #309
+NULL,                                          // #310
+NULL,                                          // #311
+NULL,                                          // #312
+NULL,                                          // #313
+NULL,                                          // #314
+NULL,                                          // #315
+NULL,                                          // #316
+NULL,                                          // #317
+NULL,                                          // #318
+NULL,                                          // #319
+NULL,                                          // #320
+NULL,                                          // #321
+NULL,                                          // #322
+NULL,                                          // #323
+NULL,                                          // #324
+NULL,                                          // #325
+NULL,                                          // #326
+NULL,                                          // #327
+NULL,                                          // #328
+NULL,                                          // #329
+NULL,                                          // #330
+NULL,                                          // #331
+NULL,                                          // #332
+NULL,                                          // #333
+NULL,                                          // #334
+NULL,                                          // #335
+NULL,                                          // #336
+NULL,                                          // #337
+NULL,                                          // #338
+NULL,                                          // #339
+NULL,                                          // #340
+NULL,                                          // #341
+NULL,                                          // #342
+NULL,                                          // #343
+NULL,                                          // #344
+NULL,                                          // #345
+NULL,                                          // #346
+NULL,                                          // #347
+NULL,                                          // #348
+NULL,                                          // #349
+NULL,                                          // #350
+NULL,                                          // #351
+NULL,                                          // #352
+NULL,                                          // #353
+NULL,                                          // #354
+NULL,                                          // #355
+NULL,                                          // #356
+NULL,                                          // #357
+NULL,                                          // #358
+NULL,                                          // #359
+NULL,                                          // #360
+NULL,                                          // #361
+NULL,                                          // #362
+NULL,                                          // #363
+NULL,                                          // #364
+NULL,                                          // #365
+NULL,                                          // #366
+NULL,                                          // #367
+NULL,                                          // #368
+NULL,                                          // #369
+NULL,                                          // #370
+NULL,                                          // #371
+NULL,                                          // #372
+NULL,                                          // #373
+NULL,                                          // #374
+NULL,                                          // #375
+NULL,                                          // #376
+NULL,                                          // #377
+NULL,                                          // #378
+NULL,                                          // #379
+NULL,                                          // #380
+NULL,                                          // #381
+NULL,                                          // #382
+NULL,                                          // #383
+NULL,                                          // #384
+NULL,                                          // #385
+NULL,                                          // #386
+NULL,                                          // #387
+NULL,                                          // #388
+NULL,                                          // #389
+NULL,                                          // #390
+NULL,                                          // #391
+NULL,                                          // #392
+NULL,                                          // #393
+NULL,                                          // #394
+NULL,                                          // #395
+NULL,                                          // #396
+NULL,                                          // #397
+NULL,                                          // #398
+NULL,                                          // #399
+NULL,                                          // #400
+VM_M_WriteByte,                                // #401
+VM_M_WriteChar,                                // #402
+VM_M_WriteShort,                       // #403
+VM_M_WriteLong,                                // #404
+VM_M_WriteAngle,                       // #405
+VM_M_WriteCoord,                       // #406
+VM_M_WriteString,                      // #407
+VM_M_WriteEntity,                      // #408
+NULL,                                          // #409
+NULL,                                          // #410
+NULL,                                          // #411
+NULL,                                          // #412
+NULL,                                          // #413
+NULL,                                          // #414
+NULL,                                          // #415
+NULL,                                          // #416
+NULL,                                          // #417
+NULL,                                          // #418
+NULL,                                          // #419
+NULL,                                          // #420
+NULL,                                          // #421
+NULL,                                          // #422
+NULL,                                          // #423
+NULL,                                          // #424
+NULL,                                          // #425
+NULL,                                          // #426
+NULL,                                          // #427
+NULL,                                          // #428
+NULL,                                          // #429
+NULL,                                          // #430
+NULL,                                          // #431
+NULL,                                          // #432
+NULL,                                          // #433
+NULL,                                          // #434
+NULL,                                          // #435
+NULL,                                          // #436
+NULL,                                          // #437
+NULL,                                          // #438
+NULL,                                          // #439
+NULL,                                          // #440
+NULL,                                          // #441
+NULL,                                          // #442
+NULL,                                          // #443
+NULL,                                          // #444
+NULL,                                          // #445
+NULL,                                          // #446
+NULL,                                          // #447
+NULL,                                          // #448
+NULL,                                          // #449
+NULL,                                          // #450
+VM_iscachedpic,                                // #451 draw functions...
+VM_precache_pic,                       // #452
+VM_freepic,                                    // #453
+VM_drawcharacter,                      // #454
+VM_drawstring,                         // #455
+VM_drawpic,                                    // #456
+VM_drawfill,                           // #457
+VM_drawsetcliparea,                    // #458
+VM_drawresetcliparea,          // #459
+VM_getimagesize,                       // #460
+VM_cin_open,                           // #461
+VM_cin_close,                          // #462
+VM_cin_setstate,                       // #463
+VM_cin_getstate,                       // #464
+VM_cin_restart,                        // #465
+VM_drawline,                           // #466
+NULL,                                          // #467
+NULL,                                          // #468
+NULL,                                          // #469
+NULL,                                          // #470
+VM_asin,                                       // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
+VM_acos,                                       // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
+VM_atan,                                       // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
+VM_atan2,                                      // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
+VM_tan,                                                // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
+VM_strlennocol,                                // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
+VM_strdecolorize,                      // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS)
+VM_strftime,                           // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
+NULL,                                          // #479
+NULL,                                          // #480
+NULL,                                          // #481
+NULL,                                          // #482
+NULL,                                          // #483
+NULL,                                          // #484
+NULL,                                          // #485
+NULL,                                          // #486
+NULL,                                          // #487
+NULL,                                          // #488
+NULL,                                          // #489
+NULL,                                          // #490
+NULL,                                          // #491
+NULL,                                          // #492
+NULL,                                          // #493
+NULL,                                          // #494
+NULL,                                          // #495
+NULL,                                          // #496
+NULL,                                          // #497
+NULL,                                          // #498
+NULL,                                          // #499
+NULL,                                          // #500
+NULL,                                          // #501
+NULL,                                          // #502
+NULL,                                          // #503
+NULL,                                          // #504
+NULL,                                          // #505
+NULL,                                          // #506
+NULL,                                          // #507
+NULL,                                          // #508
+NULL,                                          // #509
+NULL,                                          // #510
+NULL,                                          // #511
+NULL,                                          // #512
+NULL,                                          // #513
+NULL,                                          // #514
+NULL,                                          // #515
+NULL,                                          // #516
+NULL,                                          // #517
+NULL,                                          // #518
+NULL,                                          // #519
+NULL,                                          // #520
+NULL,                                          // #521
+NULL,                                          // #522
+NULL,                                          // #523
+NULL,                                          // #524
+NULL,                                          // #525
+NULL,                                          // #526
+NULL,                                          // #527
+NULL,                                          // #528
+NULL,                                          // #529
+NULL,                                          // #530
+NULL,                                          // #531
+NULL,                                          // #532
+NULL,                                          // #533
+NULL,                                          // #534
+NULL,                                          // #535
+NULL,                                          // #536
+NULL,                                          // #537
+NULL,                                          // #538
+NULL,                                          // #539
+NULL,                                          // #540
+NULL,                                          // #541
+NULL,                                          // #542
+NULL,                                          // #543
+NULL,                                          // #544
+NULL,                                          // #545
+NULL,                                          // #546
+NULL,                                          // #547
+NULL,                                          // #548
+NULL,                                          // #549
+NULL,                                          // #550
+NULL,                                          // #551
+NULL,                                          // #552
+NULL,                                          // #553
+NULL,                                          // #554
+NULL,                                          // #555
+NULL,                                          // #556
+NULL,                                          // #557
+NULL,                                          // #558
+NULL,                                          // #559
+NULL,                                          // #560
+NULL,                                          // #561
+NULL,                                          // #562
+NULL,                                          // #563
+NULL,                                          // #564
+NULL,                                          // #565
+NULL,                                          // #566
+NULL,                                          // #567
+NULL,                                          // #568
+NULL,                                          // #569
+NULL,                                          // #570
+NULL,                                          // #571
+NULL,                                          // #572
+NULL,                                          // #573
+NULL,                                          // #574
+NULL,                                          // #575
+NULL,                                          // #576
+NULL,                                          // #577
+NULL,                                          // #578
+NULL,                                          // #579
+NULL,                                          // #580
+NULL,                                          // #581
+NULL,                                          // #582
+NULL,                                          // #583
+NULL,                                          // #584
+NULL,                                          // #585
+NULL,                                          // #586
+NULL,                                          // #587
+NULL,                                          // #588
+NULL,                                          // #589
+NULL,                                          // #590
+NULL,                                          // #591
+NULL,                                          // #592
+NULL,                                          // #593
+NULL,                                          // #594
+NULL,                                          // #595
+NULL,                                          // #596
+NULL,                                          // #597
+NULL,                                          // #598
+NULL,                                          // #599
+NULL,                                          // #600
+VM_M_setkeydest,                       // #601 menu functions...
+VM_M_getkeydest,                       // #602
+VM_M_setmousetarget,           // #603
+VM_M_getmousetarget,           // #604
+VM_M_callfunction,                     // #605
+VM_writetofile,                                // #606
+VM_M_isfunction,                       // #607
+VM_M_getresolution,                    // #608
+VM_keynumtostring,                     // #609
+VM_M_findkeysforcommand,       // #610
+VM_M_getserverliststat,                // #611
+VM_M_getserverliststring,      // #612
+VM_parseentitydata,                    // #613
+VM_stringtokeynum,                     // #614
+VM_M_resetserverlistmasks,     // #615
+VM_M_setserverlistmaskstring,// #616
+VM_M_setserverlistmasknumber,// #617
+VM_M_resortserverlist,         // #618
+VM_M_setserverlistsort,                // #619
+VM_M_refreshserverlist,                // #620
+VM_M_getserverlistnumber,      // #621
+VM_M_getserverlistindexforkey,// #622
+VM_M_addwantedserverlistkey,// #623
+VM_M_getextresponse                    // #624
 };
 
 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
index 47e94fe..887192d 100644 (file)
@@ -206,6 +206,8 @@ void VM_sprint (void)
        int                     clientnum;
        char string[VM_STRINGTEMP_LENGTH];
 
+       VM_SAFEPARMCOUNTRANGE(1, 8, VM_sprint);
+
        //find client for this entity
        clientnum = (int)PRVM_G_FLOAT(OFS_PARM0);
        if (!sv.active  || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
@@ -229,13 +231,14 @@ VM_centerprint
 
 single print to the screen
 
-centerprint(clientent, value)
+centerprint(value)
 =================
 */
 void VM_centerprint (void)
 {
        char string[VM_STRINGTEMP_LENGTH];
 
+       VM_SAFEPARMCOUNTRANGE(1, 8, VM_centerprint);
        VM_VarString(0, string, sizeof(string));
        SCR_CenterPrint(string);
 }
@@ -378,49 +381,6 @@ void VM_random (void)
 }
 
 /*
-=================
-PF_sound
-
-Each entity can have eight independant sound sources, like voice,
-weapon, feet, etc.
-
-Channel 0 is an auto-allocate channel, the others override anything
-already running on that entity/channel pair.
-
-An attenuation of 0 will play full volume everywhere in the level.
-Larger attenuations will drop off.
-
-=================
-*/
-/*
-void PF_sound (void)
-{
-       char            *sample;
-       int                     channel;
-       prvm_edict_t            *entity;
-       int             volume;
-       float attenuation;
-
-       entity = PRVM_G_EDICT(OFS_PARM0);
-       channel = PRVM_G_FLOAT(OFS_PARM1);
-       sample = PRVM_G_STRING(OFS_PARM2);
-       volume = PRVM_G_FLOAT(OFS_PARM3) * 255;
-       attenuation = PRVM_G_FLOAT(OFS_PARM4);
-
-       if (volume < 0 || volume > 255)
-               Host_Error ("SV_StartSound: volume = %i", volume);
-
-       if (attenuation < 0 || attenuation > 4)
-               Host_Error ("SV_StartSound: attenuation = %f", attenuation);
-
-       if (channel < 0 || channel > 7)
-               Host_Error ("SV_StartSound: channel = %i", channel);
-
-       SV_StartSound (entity, channel, sample, volume, attenuation);
-}
-*/
-
-/*
 =========
 VM_localsound
 
@@ -472,6 +432,7 @@ cmd (string, ...)
 void VM_localcmd (void)
 {
        char string[VM_STRINGTEMP_LENGTH];
+       VM_SAFEPARMCOUNTRANGE(1, 8, VM_localcmd);
        VM_VarString(0, string, sizeof(string));
        Cbuf_AddText(string);
 }
@@ -552,6 +513,7 @@ dprint(...[string])
 void VM_dprint (void)
 {
        char string[VM_STRINGTEMP_LENGTH];
+       VM_SAFEPARMCOUNTRANGE(1, 8, VM_dprint);
        if (developer.integer)
        {
                VM_VarString(0, string, sizeof(string));
@@ -651,6 +613,7 @@ float stof(...[string])
 void VM_stof(void)
 {
        char string[VM_STRINGTEMP_LENGTH];
+       VM_SAFEPARMCOUNTRANGE(1, 8, VM_stof);
        VM_VarString(0, string, sizeof(string));
        PRVM_G_FLOAT(OFS_RETURN) = atof(string);
 }
@@ -700,7 +663,8 @@ void VM_strftime(void)
        struct tm *tm;
        char fmt[VM_STRINGTEMP_LENGTH];
        char result[VM_STRINGTEMP_LENGTH];
-       VM_VarString(0, fmt, sizeof(fmt));
+       VM_SAFEPARMCOUNTRANGE(2, 8, VM_strftime);
+       VM_VarString(1, fmt, sizeof(fmt));
        t = time(NULL);
        if (PRVM_G_FLOAT(OFS_PARM0))
                tm = localtime(&t);
@@ -726,6 +690,7 @@ entity spawn()
 void VM_spawn (void)
 {
        prvm_edict_t    *ed;
+       VM_SAFEPARMCOUNT(0, VM_spawn);
        prog->xfunction->builtinsprofile += 20;
        ed = PRVM_ED_Alloc();
        VM_RETURN_EDICT(ed);
@@ -1024,6 +989,46 @@ void VM_findchainflags (void)
 
 /*
 =========
+VM_precache_sound
+
+string precache_sound (string sample)
+=========
+*/
+void VM_precache_sound (void)
+{
+       const char *s;
+
+       VM_SAFEPARMCOUNT(1, VM_precache_sound);
+
+       s = PRVM_G_STRING(OFS_PARM0);
+       PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
+       VM_CheckEmptyString(s);
+
+       if(snd_initialized.integer && !S_PrecacheSound(s, true, false))
+       {
+               VM_Warning("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
+               return;
+       }
+}
+
+/*
+=================
+VM_precache_file
+
+returns the same string as output
+
+does nothing, only used by qcc to build .pak archives
+=================
+*/
+void VM_precache_file (void)
+{
+       VM_SAFEPARMCOUNT(1,VM_precache_file);
+       // precache_file is only used to copy files with qcc, it does nothing
+       PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
+}
+
+/*
+=========
 VM_coredump
 
 coredump()
@@ -1170,6 +1175,8 @@ void VM_nextent (void)
        int             i;
        prvm_edict_t    *ent;
 
+       VM_SAFEPARMCOUNT(1, VM_nextent);
+
        i = PRVM_G_EDICTNUM(OFS_PARM0);
        while (1)
        {
@@ -1358,7 +1365,7 @@ void VM_randomvec (void)
 =========
 VM_registercvar
 
-float  registercvar (string name, string value, float flags)
+float  registercvar (string name, string value[, float flags])
 =========
 */
 void VM_registercvar (void)
@@ -1366,11 +1373,11 @@ void VM_registercvar (void)
        const char *name, *value;
        int     flags;
 
-       VM_SAFEPARMCOUNT(3,VM_registercvar);
+       VM_SAFEPARMCOUNTRANGE(2, 3, VM_registercvar);
 
        name = PRVM_G_STRING(OFS_PARM0);
        value = PRVM_G_STRING(OFS_PARM1);
-       flags = (int)PRVM_G_FLOAT(OFS_PARM2);
+       flags = prog->argc >= 3 ? (int)PRVM_G_FLOAT(OFS_PARM2) : 0;
        PRVM_G_FLOAT(OFS_RETURN) = 0;
 
        if(flags > CVAR_MAXFLAGSVAL)
@@ -1392,6 +1399,7 @@ void VM_registercvar (void)
        PRVM_G_FLOAT(OFS_RETURN) = 1; // success
 }
 
+
 /*
 =================
 VM_min
@@ -1403,20 +1411,19 @@ float min(float a, float b, ...[float])
 */
 void VM_min (void)
 {
+       VM_SAFEPARMCOUNTRANGE(2, 8, VM_min);
        // LordHavoc: 3+ argument enhancement suggested by FrikaC
-       if (prog->argc == 2)
-               PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
-       else if (prog->argc >= 3)
+       if (prog->argc >= 3)
        {
                int i;
                float f = PRVM_G_FLOAT(OFS_PARM0);
                for (i = 1;i < prog->argc;i++)
-                       if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
+                       if (f > PRVM_G_FLOAT((OFS_PARM0+i*3)))
                                f = PRVM_G_FLOAT((OFS_PARM0+i*3));
                PRVM_G_FLOAT(OFS_RETURN) = f;
        }
        else
-               PRVM_ERROR("VM_min: %s must supply at least 2 floats", PRVM_NAME);
+               PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
 }
 
 /*
@@ -1430,20 +1437,19 @@ float   max(float a, float b, ...[float])
 */
 void VM_max (void)
 {
+       VM_SAFEPARMCOUNTRANGE(2, 8, VM_max);
        // LordHavoc: 3+ argument enhancement suggested by FrikaC
-       if (prog->argc == 2)
-               PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
-       else if (prog->argc >= 3)
+       if (prog->argc >= 3)
        {
                int i;
                float f = PRVM_G_FLOAT(OFS_PARM0);
                for (i = 1;i < prog->argc;i++)
-                       if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
+                       if (f < PRVM_G_FLOAT((OFS_PARM0+i*3)))
                                f = PRVM_G_FLOAT((OFS_PARM0+i*3));
                PRVM_G_FLOAT(OFS_RETURN) = f;
        }
        else
-               PRVM_ERROR("VM_max: %s must supply at least 2 floats", PRVM_NAME);
+               PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
 }
 
 /*
@@ -1476,24 +1482,6 @@ void VM_pow (void)
        PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
 }
 
-/*
-=================
-VM_copyentity
-
-copies data from one entity to another
-
-copyentity(entity src, entity dst)
-=================
-*/
-void VM_copyentity (void)
-{
-       prvm_edict_t *in, *out;
-       VM_SAFEPARMCOUNT(2,VM_copyentity);
-       in = PRVM_G_EDICT(OFS_PARM0);
-       out = PRVM_G_EDICT(OFS_PARM1);
-       memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
-}
-
 void VM_Files_Init(void)
 {
        int i;
@@ -1512,7 +1500,7 @@ void VM_Files_CloseAll(void)
        }
 }
 
-qfile_t *VM_GetFileHandle( int index )
+static qfile_t *VM_GetFileHandle( int index )
 {
        if (index < 0 || index >= PRVM_MAX_OPENFILES)
        {
@@ -1709,6 +1697,37 @@ void VM_fputs(void)
 
 /*
 =========
+VM_writetofile
+
+       writetofile(float fhandle, entity ent)
+=========
+*/
+void VM_writetofile(void)
+{
+       prvm_edict_t * ent;
+       qfile_t *file;
+
+       VM_SAFEPARMCOUNT(2, VM_writetofile);
+
+       file = VM_GetFileHandle( (int)PRVM_G_FLOAT(OFS_PARM0) );
+       if( !file )
+       {
+               VM_Warning("VM_writetofile: invalid or closed file handle\n");
+               return;
+       }
+
+       ent = PRVM_G_EDICT(OFS_PARM1);
+       if(ent->priv.required->free)
+       {
+               VM_Warning("VM_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
+               return;
+       }
+
+       PRVM_ED_Write (file, ent);
+}
+
+/*
+=========
 VM_strlen
 
 float  strlen(string s)
@@ -1862,9 +1881,7 @@ string strcat(string,string,...[string])
 void VM_strcat(void)
 {
        char s[VM_STRINGTEMP_LENGTH];
-
-       if(prog->argc < 1)
-               PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !");
+       VM_SAFEPARMCOUNTRANGE(1, 8, VM_strcat);
 
        VM_VarString(0, s, sizeof(s));
        PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(s);
@@ -2053,7 +2070,7 @@ void VM_isserver(void)
 {
        VM_SAFEPARMCOUNT(0,VM_serverstate);
 
-       PRVM_G_FLOAT(OFS_RETURN) = sv.active;
+       PRVM_G_FLOAT(OFS_RETURN) = sv.active && (svs.maxclients > 1 || cls.state == ca_dedicated);
 }
 
 /*
@@ -2833,16 +2850,49 @@ void VM_cin_restart( void )
 
 /*
 ==============
+VM_makevectors
+
+Writes new values for v_forward, v_up, and v_right based on angles
+void makevectors(vector angle)
+==============
+*/
+void VM_makevectors (void)
+{
+       prvm_eval_t *valforward, *valright, *valup;
+       valforward = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_forward);
+       valright = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_right);
+       valup = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_up);
+       if (!valforward || !valright || !valup)
+       {
+               VM_Warning("makevectors: could not find v_forward, v_right, or v_up global variables\n");
+               return;
+       }
+       VM_SAFEPARMCOUNT(1, VM_makevectors);
+       AngleVectors (PRVM_G_VECTOR(OFS_PARM0), valforward->vector, valright->vector, valup->vector);
+}
+
+/*
+==============
 VM_vectorvectors
 
 Writes new values for v_forward, v_up, and v_right based on the given forward vector
-vectorvectors(vector, vector)
+vectorvectors(vector)
 ==============
 */
 void VM_vectorvectors (void)
 {
-       VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward);
-       VectorVectors(prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
+       prvm_eval_t *valforward, *valright, *valup;
+       valforward = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_forward);
+       valright = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_right);
+       valup = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_up);
+       if (!valforward || !valright || !valup)
+       {
+               VM_Warning("vectorvectors: could not find v_forward, v_right, or v_up global variables\n");
+               return;
+       }
+       VM_SAFEPARMCOUNT(1, VM_vectorvectors);
+       VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), valforward->vector);
+       VectorVectors(valforward->vector, valright->vector, valup->vector);
 }
 
 /*
@@ -2868,364 +2918,6 @@ void VM_drawline (void)
        DrawQ_Line(width, c1[0], c1[1], c2[0], c2[1], rgb[0], rgb[1], rgb[2], alpha, flags);
 }
 
-//====================
-//QC POLYGON functions
-//====================
-
-typedef struct
-{
-       rtexture_t              *tex;
-       float                   data[36];       //[515]: enough for polygons
-       unsigned char                   flags;  //[515]: + VM_POLYGON_2D and VM_POLYGON_FL4V flags
-}vm_polygon_t;
-
-//static float                 vm_polygon_linewidth = 1;
-static mempool_t               *vm_polygons_pool = NULL;
-static unsigned char                   vm_current_vertices = 0;
-static qboolean                        vm_polygons_initialized = false;
-static vm_polygon_t            *vm_polygons = NULL;
-static unsigned long   vm_polygons_num = 0, vm_drawpolygons_num = 0;   //[515]: ok long on 64bit ?
-static qboolean                        vm_polygonbegin = false;        //[515]: for "no-crap-on-the-screen" check
-#define VM_DEFPOLYNUM 64       //[515]: enough for default ?
-
-#define VM_POLYGON_FL3V                16      //more than 2 vertices (used only for lines)
-#define VM_POLYGON_FLLINES     32
-#define VM_POLYGON_FL2D                64
-#define VM_POLYGON_FL4V                128     //4 vertices
-
-void VM_InitPolygons (void)
-{
-       vm_polygons_pool = Mem_AllocPool("VMPOLY", 0, NULL);
-       vm_polygons = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
-       memset(vm_polygons, 0, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
-       vm_polygons_num = VM_DEFPOLYNUM;
-       vm_drawpolygons_num = 0;
-       vm_polygonbegin = false;
-       vm_polygons_initialized = true;
-}
-
-void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
-{
-       int surfacelistindex;
-       // LordHavoc: FIXME: this is stupid code
-       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
-       {
-               const vm_polygon_t      *p = &vm_polygons[surfacelist[surfacelistindex]];
-               int                                     flags = p->flags & 0x0f;
-
-               if(flags == DRAWFLAG_ADDITIVE)
-                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-               else if(flags == DRAWFLAG_MODULATE)
-                       GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
-               else if(flags == DRAWFLAG_2XMODULATE)
-                       GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
-               else
-                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-               R_Mesh_TexBind(0, R_GetTexture(p->tex));
-
-               CHECKGLERROR
-               //[515]: is speed is max ?
-               if(p->flags & VM_POLYGON_FLLINES)       //[515]: lines
-               {
-                       qglLineWidth(p->data[13]);CHECKGLERROR
-                       qglBegin(GL_LINE_LOOP);
-                               qglTexCoord1f   (p->data[12]);
-                               qglColor4f              (p->data[20], p->data[21], p->data[22], p->data[23]);
-                               qglVertex3f             (p->data[0] , p->data[1],  p->data[2]);
-
-                               qglTexCoord1f   (p->data[14]);
-                               qglColor4f              (p->data[24], p->data[25], p->data[26], p->data[27]);
-                               qglVertex3f             (p->data[3] , p->data[4],  p->data[5]);
-
-                               if(p->flags & VM_POLYGON_FL3V)
-                               {
-                                       qglTexCoord1f   (p->data[16]);
-                                       qglColor4f              (p->data[28], p->data[29], p->data[30], p->data[31]);
-                                       qglVertex3f             (p->data[6] , p->data[7],  p->data[8]);
-
-                                       if(p->flags & VM_POLYGON_FL4V)
-                                       {
-                                               qglTexCoord1f   (p->data[18]);
-                                               qglColor4f              (p->data[32], p->data[33], p->data[34], p->data[35]);
-                                               qglVertex3f             (p->data[9] , p->data[10],  p->data[11]);
-                                       }
-                               }
-                       qglEnd();
-                       CHECKGLERROR
-               }
-               else
-               {
-                       qglBegin(GL_POLYGON);
-                               qglTexCoord2f   (p->data[12], p->data[13]);
-                               qglColor4f              (p->data[20], p->data[21], p->data[22], p->data[23]);
-                               qglVertex3f             (p->data[0] , p->data[1],  p->data[2]);
-
-                               qglTexCoord2f   (p->data[14], p->data[15]);
-                               qglColor4f              (p->data[24], p->data[25], p->data[26], p->data[27]);
-                               qglVertex3f             (p->data[3] , p->data[4],  p->data[5]);
-
-                               qglTexCoord2f   (p->data[16], p->data[17]);
-                               qglColor4f              (p->data[28], p->data[29], p->data[30], p->data[31]);
-                               qglVertex3f             (p->data[6] , p->data[7],  p->data[8]);
-
-                               if(p->flags & VM_POLYGON_FL4V)
-                               {
-                                       qglTexCoord2f   (p->data[18], p->data[19]);
-                                       qglColor4f              (p->data[32], p->data[33], p->data[34], p->data[35]);
-                                       qglVertex3f             (p->data[9] , p->data[10],  p->data[11]);
-                               }
-                       qglEnd();
-                       CHECKGLERROR
-               }
-       }
-}
-
-void VM_AddPolygonTo2DScene (vm_polygon_t *p)
-{
-       drawqueuemesh_t mesh;
-       static int              picelements[6] = {0, 1, 2, 0, 2, 3};
-
-       mesh.texture = p->tex;
-       mesh.data_element3i = picelements;
-       mesh.data_vertex3f = p->data;
-       mesh.data_texcoord2f = p->data + 12;
-       mesh.data_color4f = p->data + 20;
-       if(p->flags & VM_POLYGON_FL4V)
-       {
-               mesh.num_vertices = 4;
-               mesh.num_triangles = 2;
-       }
-       else
-       {
-               mesh.num_vertices = 3;
-               mesh.num_triangles = 1;
-       }
-       if(p->flags & VM_POLYGON_FLLINES)       //[515]: lines
-               DrawQ_LineLoop (&mesh, (p->flags&0x0f));
-       else
-               DrawQ_Mesh (&mesh, (p->flags&0x0f));
-}
-
-//void(string texturename, float flag, float 2d, float lines) R_BeginPolygon
-void VM_R_PolygonBegin (void)
-{
-       vm_polygon_t    *p;
-       const char              *picname;
-       if(prog->argc < 2)
-               VM_SAFEPARMCOUNT(2, VM_R_PolygonBegin);
-
-       if(!vm_polygons_initialized)
-               VM_InitPolygons();
-       if(vm_polygonbegin)
-       {
-               VM_Warning("VM_R_PolygonBegin: called twice without VM_R_PolygonEnd after first\n");
-               return;
-       }
-       if(vm_drawpolygons_num >= vm_polygons_num)
-       {
-               p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t));
-               memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t));
-               memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t));
-               Mem_Free(vm_polygons);
-               vm_polygons = p;
-               vm_polygons_num *= 2;
-       }
-       p = &vm_polygons[vm_drawpolygons_num];
-       picname = PRVM_G_STRING(OFS_PARM0);
-       if(picname[0])
-               p->tex = Draw_CachePic(picname, true)->tex;
-       else
-               p->tex = r_texture_white;
-       p->flags = (unsigned char)PRVM_G_FLOAT(OFS_PARM1);
-       vm_current_vertices = 0;
-       vm_polygonbegin = true;
-       if(prog->argc >= 3)
-       {
-               if(PRVM_G_FLOAT(OFS_PARM2))
-                       p->flags |= VM_POLYGON_FL2D;
-               if(prog->argc >= 4 && PRVM_G_FLOAT(OFS_PARM3))
-               {
-                       p->data[13] = PRVM_G_FLOAT(OFS_PARM3);  //[515]: linewidth
-                       p->flags |= VM_POLYGON_FLLINES;
-               }
-       }
-}
-
-//void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
-void VM_R_PolygonVertex (void)
-{
-       float                   *coords, *tx, *rgb, alpha;
-       vm_polygon_t    *p;
-       VM_SAFEPARMCOUNT(4, VM_R_PolygonVertex);
-
-       if(!vm_polygonbegin)
-       {
-               VM_Warning("VM_R_PolygonVertex: VM_R_PolygonBegin wasn't called\n");
-               return;
-       }
-       coords  = PRVM_G_VECTOR(OFS_PARM0);
-       tx              = PRVM_G_VECTOR(OFS_PARM1);
-       rgb             = PRVM_G_VECTOR(OFS_PARM2);
-       alpha = PRVM_G_FLOAT(OFS_PARM3);
-
-       p = &vm_polygons[vm_drawpolygons_num];
-       if(vm_current_vertices > 4)
-       {
-               VM_Warning("VM_R_PolygonVertex: may have 4 vertices max\n");
-               return;
-       }
-
-       p->data[vm_current_vertices*3]          = coords[0];
-       p->data[1+vm_current_vertices*3]        = coords[1];
-       p->data[2+vm_current_vertices*3]        = coords[2];
-
-       p->data[12+vm_current_vertices*2]       = tx[0];
-       if(!(p->flags & VM_POLYGON_FLLINES))
-               p->data[13+vm_current_vertices*2]       = tx[1];
-
-       p->data[20+vm_current_vertices*4]       = rgb[0];
-       p->data[21+vm_current_vertices*4]       = rgb[1];
-       p->data[22+vm_current_vertices*4]       = rgb[2];
-       p->data[23+vm_current_vertices*4]       = alpha;
-
-       vm_current_vertices++;
-       if(vm_current_vertices == 4)
-               p->flags |= VM_POLYGON_FL4V;
-       else
-               if(vm_current_vertices == 3)
-                       p->flags |= VM_POLYGON_FL3V;
-}
-
-//void() R_EndPolygon
-void VM_R_PolygonEnd (void)
-{
-       if(!vm_polygonbegin)
-       {
-               VM_Warning("VM_R_PolygonEnd: VM_R_PolygonBegin wasn't called\n");
-               return;
-       }
-       vm_polygonbegin = false;
-       if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES))
-       {
-               if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D)    //[515]: don't use qcpolygons memory if 2D
-                       VM_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]);
-               else
-                       vm_drawpolygons_num++;
-       }
-       else
-               VM_Warning("VM_R_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices);
-}
-
-void VM_AddPolygonsToMeshQueue (void)
-{
-       int i;
-       if(!vm_drawpolygons_num)
-               return;
-       R_Mesh_Matrix(&identitymatrix);
-       GL_CullFace(GL_NONE);
-       for(i = 0;i < (int)vm_drawpolygons_num;i++)
-               VM_DrawPolygonCallback(NULL, NULL, 1, &i);
-       vm_drawpolygons_num = 0;
-}
-
-void Debug_PolygonBegin(const char *picname, int flags, qboolean draw2d, float linewidth)
-{
-       vm_polygon_t    *p;
-
-       if(!vm_polygons_initialized)
-               VM_InitPolygons();
-       if(vm_polygonbegin)
-       {
-               Con_Printf("Debug_PolygonBegin: called twice without Debug_PolygonEnd after first\n");
-               return;
-       }
-       // limit polygons to a vaguely sane amount, beyond this each one just
-       // replaces the last one
-       vm_drawpolygons_num = min(vm_drawpolygons_num, (1<<20)-1);
-       if(vm_drawpolygons_num >= vm_polygons_num)
-       {
-               p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t));
-               memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t));
-               memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t));
-               Mem_Free(vm_polygons);
-               vm_polygons = p;
-               vm_polygons_num *= 2;
-       }
-       p = &vm_polygons[vm_drawpolygons_num];
-       if(picname && picname[0])
-               p->tex = Draw_CachePic(picname, true)->tex;
-       else
-               p->tex = r_texture_white;
-       p->flags = flags;
-       vm_current_vertices = 0;
-       vm_polygonbegin = true;
-       if(draw2d)
-               p->flags |= VM_POLYGON_FL2D;
-       if(linewidth)
-       {
-               p->data[13] = linewidth;        //[515]: linewidth
-               p->flags |= VM_POLYGON_FLLINES;
-       }
-}
-
-void Debug_PolygonVertex(float x, float y, float z, float s, float t, float r, float g, float b, float a)
-{
-       vm_polygon_t    *p;
-
-       if(!vm_polygonbegin)
-       {
-               Con_Printf("Debug_PolygonVertex: Debug_PolygonBegin wasn't called\n");
-               return;
-       }
-
-       p = &vm_polygons[vm_drawpolygons_num];
-       if(vm_current_vertices > 4)
-       {
-               Con_Printf("Debug_PolygonVertex: may have 4 vertices max\n");
-               return;
-       }
-
-       p->data[vm_current_vertices*3]          = x;
-       p->data[1+vm_current_vertices*3]        = y;
-       p->data[2+vm_current_vertices*3]        = z;
-
-       p->data[12+vm_current_vertices*2]       = s;
-       if(!(p->flags & VM_POLYGON_FLLINES))
-               p->data[13+vm_current_vertices*2]       = t;
-
-       p->data[20+vm_current_vertices*4]       = r;
-       p->data[21+vm_current_vertices*4]       = g;
-       p->data[22+vm_current_vertices*4]       = b;
-       p->data[23+vm_current_vertices*4]       = a;
-
-       vm_current_vertices++;
-       if(vm_current_vertices == 4)
-               p->flags |= VM_POLYGON_FL4V;
-       else
-               if(vm_current_vertices == 3)
-                       p->flags |= VM_POLYGON_FL3V;
-}
-
-void Debug_PolygonEnd(void)
-{
-       if(!vm_polygonbegin)
-       {
-               Con_Printf("Debug_PolygonEnd: Debug_PolygonBegin wasn't called\n");
-               return;
-       }
-       vm_polygonbegin = false;
-       if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES))
-       {
-               if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D)    //[515]: don't use qcpolygons memory if 2D
-                       VM_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]);
-               else
-                       vm_drawpolygons_num++;
-       }
-       else
-               Con_Printf("Debug_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices);
-}
-
 
 
 
@@ -3420,6 +3112,8 @@ void VM_altstr_ins(void)
        char *out;
        char outstr[VM_STRINGTEMP_LENGTH];
 
+       VM_SAFEPARMCOUNT(3, VM_altstr_ins);
+
        in = instr = PRVM_G_STRING( OFS_PARM0 );
        num = (int)PRVM_G_FLOAT( OFS_PARM1 );
        set = setstr = PRVM_G_STRING( OFS_PARM2 );
@@ -3456,6 +3150,7 @@ typedef struct
        char    *strings[MAX_QCSTR_STRINGS];
 }qcstrbuffer_t;
 
+// FIXME: move stringbuffers to prog_t to allow multiple progs!
 static qcstrbuffer_t   *qcstringbuffers[MAX_QCSTR_BUFFERS];
 static int                             num_qcstringbuffers;
 static int                             buf_sortpower;
@@ -3527,21 +3222,6 @@ static int BufStr_SortStringsDOWN (const void *in1, const void *in2)
        return strncmp(b, a, buf_sortpower);
 }
 
-#ifdef REMOVETHIS
-static void VM_BufStr_Init (void)
-{
-       memset(qcstringbuffers, 0, sizeof(qcstringbuffers));
-       num_qcstringbuffers = 0;
-}
-
-static void VM_BufStr_ShutDown (void)
-{
-       int i;
-       for(i=0;i<MAX_QCSTR_BUFFERS && num_qcstringbuffers;i++)
-               BufStr_ClearBuffer(i);
-}
-#endif
-
 /*
 ========================
 VM_buf_create
@@ -3916,6 +3596,8 @@ void VM_changeyaw (void)
        prvm_edict_t            *ent;
        float           ideal, current, move, speed;
 
+       VM_SAFEPARMCOUNT(0, VM_changeyaw);
+
        ent = PRVM_PROG_TO_EDICT(PRVM_GLOBALFIELDVALUE(prog->globaloffsets.self)->edict);
        if (ent == prog->edicts)
        {
@@ -3973,6 +3655,8 @@ void VM_changepitch (void)
        prvm_edict_t            *ent;
        float           ideal, current, move, speed;
 
+       VM_SAFEPARMCOUNT(1, VM_changepitch);
+
        ent = PRVM_G_EDICT(OFS_PARM0);
        if (ent == prog->edicts)
        {
@@ -4020,6 +3704,122 @@ void VM_changepitch (void)
        PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.angles)->vector[0] = ANGLEMOD (current + move);
 }
 
+
+static int Is_Text_Color (char c, char t)
+{
+       int a = 0;
+       char c2 = c - (c & 128);
+       char t2 = t - (t & 128);
+
+       if(c != STRING_COLOR_TAG && c2 != STRING_COLOR_TAG)             return 0;
+       if(t >= '0' && t <= '9')                a = 1;
+       if(t2 >= '0' && t2 <= '9')              a = 1;
+/*     if(t >= 'A' && t <= 'Z')                a = 2;
+       if(t2 >= 'A' && t2 <= 'Z')              a = 2;
+
+       if(a == 1 && scr_colortext.integer > 0)
+               return 1;
+       if(a == 2 && scr_multifonts.integer > 0)
+               return 2;
+*/
+       return a;
+}
+
+void VM_uncolorstring (void)
+{
+       const char      *in;
+       char            out[VM_STRINGTEMP_LENGTH];
+       int                     k = 0, i = 0;
+
+       VM_SAFEPARMCOUNT(1, VM_uncolorstring);
+       in = PRVM_G_STRING(OFS_PARM0);
+       VM_CheckEmptyString (in);
+
+       while (in[k])
+       {
+               if(in[k+1])
+               if(Is_Text_Color(in[k], in[k+1]) == 1/* || (in[k] == '&' && in[k+1] == 'r')*/)
+               {
+                       k += 2;
+                       continue;
+               }
+               out[i] = in[k];
+               ++k;
+               ++i;
+       }
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(out);
+}
+
+//#222 string(string s, float index) str2chr (FTE_STRINGS)
+void VM_str2chr (void)
+{
+       const char *s;
+       VM_SAFEPARMCOUNT(2, VM_str2chr);
+       s = PRVM_G_STRING(OFS_PARM0);
+       if((unsigned)PRVM_G_FLOAT(OFS_PARM1) > strlen(s))
+               return;
+       PRVM_G_FLOAT(OFS_RETURN) = (unsigned char)s[(int)PRVM_G_FLOAT(OFS_PARM1)];
+}
+
+//#223 string(float c, ...) chr2str (FTE_STRINGS)
+void VM_chr2str (void)
+{
+       char    t[9];
+       int             i;
+       VM_SAFEPARMCOUNTRANGE(0, 8, VM_chr2str);
+       for(i = 0;i < prog->argc && i < (int)sizeof(t) - 1;i++)
+               t[i] = (unsigned char)PRVM_G_FLOAT(OFS_PARM0+i*3);
+       t[i] = 0;
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
+}
+
+//#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
+void VM_strncmp (void)
+{
+       const char *s1, *s2;
+       VM_SAFEPARMCOUNT(1, VM_strncmp);
+       s1 = PRVM_G_STRING(OFS_PARM0);
+       s2 = PRVM_G_STRING(OFS_PARM1);
+       PRVM_G_FLOAT(OFS_RETURN) = strncmp(s1, s2, (size_t)PRVM_G_FLOAT(OFS_PARM2));
+}
+
+void VM_wasfreed (void)
+{
+       VM_SAFEPARMCOUNT(1, VM_wasfreed);
+       PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_EDICT(OFS_PARM0)->priv.required->free;
+}
+
+void VM_SetTraceGlobals(const trace_t *trace)
+{
+       prvm_eval_t *val;
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_allsolid)))
+               val->_float = trace->allsolid;
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_startsolid)))
+               val->_float = trace->startsolid;
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_fraction)))
+               val->_float = trace->fraction;
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_inwater)))
+               val->_float = trace->inwater;
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_inopen)))
+               val->_float = trace->inopen;
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_endpos)))
+               VectorCopy(trace->endpos, val->vector);
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_plane_normal)))
+               VectorCopy(trace->plane.normal, val->vector);
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_plane_dist)))
+               val->_float = trace->plane.dist;
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_ent)))
+               val->edict = PRVM_EDICT_TO_PROG(trace->ent ? trace->ent : prog->edicts);
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents)))
+               val->_float = trace->startsupercontents;
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents)))
+               val->_float = trace->hitsupercontents;
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags)))
+               val->_float = trace->hitq3surfaceflags;
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename)))
+               val->string = trace->hittexture ? PRVM_SetTempString(trace->hittexture->name) : 0;
+}
+
 //=============
 
 void VM_Cmd_Init(void)
@@ -4028,11 +3828,6 @@ void VM_Cmd_Init(void)
        VM_Files_Init();
        VM_Search_Init();
 //     VM_BufStr_Init();
-       if(vm_polygons_initialized)
-       {
-               Mem_FreePool(&vm_polygons_pool);
-               vm_polygons_initialized = false;
-       }
 }
 
 void VM_Cmd_Reset(void)
@@ -4041,10 +3836,5 @@ void VM_Cmd_Reset(void)
        VM_Search_Reset();
        VM_Files_CloseAll();
 //     VM_BufStr_ShutDown();
-       if(vm_polygons_initialized)
-       {
-               Mem_FreePool(&vm_polygons_pool);
-               vm_polygons_initialized = false;
-       }
 }
 
index 9864589..5856e56 100644 (file)
@@ -189,18 +189,15 @@ float     getserverlistindexforkey(string key)
 // nice helper macros
 
 #ifndef VM_NOPARMCHECK
-#define VM_SAFEPARMCOUNT(p,f)  if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !")
+#define VM_SAFEPARMCOUNTRANGE(p1,p2,f) if(prog->argc < p1 || prog->argc > p2) PRVM_ERROR(#f " wrong parameter count %i (" #p1 " to " #p2 " expected ) !", prog->argc)
+#define VM_SAFEPARMCOUNT(p,f)  if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count %i (" #p " expected ) !", prog->argc)
 #else
+#define VM_SAFEPARMCOUNTRANGE(p1,p2,f)
 #define VM_SAFEPARMCOUNT(p,f)
 #endif
 
 #define        VM_RETURN_EDICT(e)              (((int *)prog->globals.generic)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
 
-#define e10 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
-#define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
-#define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
-
-#define VM_STRINGTEMP_BUFFERS 16
 #define VM_STRINGTEMP_LENGTH MAX_INPUTLINE
 
 // builtins and other general functions
@@ -245,7 +242,6 @@ void VM_findchainfloat (void);
 void VM_findflags (void);
 void VM_findchainflags (void);
 void VM_precache_file (void);
-void VM_precache_error (void);
 void VM_precache_sound (void);
 void VM_coredump (void);
 
@@ -269,7 +265,6 @@ void VM_min (void);
 void VM_max (void);
 void VM_bound (void);
 void VM_pow (void);
-void VM_copyentity (void);
 void VM_asin (void);
 void VM_acos (void);
 void VM_atan (void);
@@ -283,9 +278,7 @@ void VM_fopen(void);
 void VM_fclose(void);
 void VM_fgets(void);
 void VM_fputs(void);
-// used by M_WriteToFile
-// should be only called from a builtin
-qfile_t *VM_GetFileHandle( int index );
+void VM_writetofile(void); // only used by menu
 
 void VM_strlen(void);
 void VM_strcat(void);
@@ -332,6 +325,7 @@ void VM_drawsetcliparea(void);
 void VM_drawresetcliparea(void);
 void VM_getimagesize(void);
 
+void VM_makevectors (void);
 void VM_vectorvectors (void);
 
 void VM_keynumtostring (void);
@@ -344,9 +338,6 @@ void VM_cin_getstate( void );
 void VM_cin_restart( void );
 
 void VM_drawline (void);
-void VM_R_PolygonBegin (void);
-void VM_R_PolygonVertex (void);
-void VM_R_PolygonEnd (void);
 
 void VM_bitshift (void);
 
@@ -370,5 +361,14 @@ void VM_bufstr_free (void);
 void VM_changeyaw (void);
 void VM_changepitch (void);
 
+void VM_uncolorstring (void);
+void VM_str2chr (void);
+void VM_chr2str (void);
+void VM_strncmp (void);
+void VM_registercvar (void);
+void VM_wasfreed (void);
+
+void VM_SetTraceGlobals(const trace_t *trace);
+
 void VM_Cmd_Init(void);
 void VM_Cmd_Reset(void);
index a504dd3..0c34315 100644 (file)
@@ -171,7 +171,7 @@ void R_NewExplosion(const vec3_t org)
                                // clip start origin
                                if (e->clipping)
                                {
-                                       trace = CL_TraceBox(e->origin, vec3_origin, vec3_origin, e->vert[j], true, NULL, SUPERCONTENTS_SOLID, false);
+                                       trace = CL_Move(e->origin, vec3_origin, vec3_origin, e->vert[j], MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false);
                                        VectorCopy(trace.endpos, e->vert[i]);
                                }
                        }
@@ -229,7 +229,7 @@ static void R_MoveExplosion(explosion_t *e)
                        VectorMA(e->vert[i], frametime, e->vertvel[i], end);
                        if (e->clipping)
                        {
-                               trace = CL_TraceBox(e->vert[i], vec3_origin, vec3_origin, end, true, NULL, SUPERCONTENTS_SOLID, false);
+                               trace = CL_Move(e->vert[i], vec3_origin, vec3_origin, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false);
                                if (trace.fraction < 1)
                                {
                                        // clip velocity against the wall
index 4ba71dc..b61ec11 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -83,9 +83,10 @@ void R_DrawCoronas(void)
        R_Mesh_Matrix(&identitymatrix);
        viewdist = DotProduct(r_view.origin, r_view.forward);
        flag = r_refdef.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
+       // FIXME: these traces should scan all render entities instead of cl.world
        for (lnum = 0, light = r_shadow_worldlightchain;light;light = light->next, lnum++)
        {
-               if ((light->flags & flag) && light->corona * r_coronas.value > 0 && (r_shadow_debuglight.integer < 0 || r_shadow_debuglight.integer == lnum) && (dist = (DotProduct(light->rtlight.shadoworigin, r_view.forward) - viewdist)) >= 24.0f && CL_TraceBox(light->rtlight.shadoworigin, vec3_origin, vec3_origin, r_view.origin, true, NULL, SUPERCONTENTS_SOLID, false).fraction == 1)
+               if ((light->flags & flag) && light->corona * r_coronas.value > 0 && (r_shadow_debuglight.integer < 0 || r_shadow_debuglight.integer == lnum) && (dist = (DotProduct(light->rtlight.shadoworigin, r_view.forward) - viewdist)) >= 24.0f && CL_Move(light->rtlight.shadoworigin, vec3_origin, vec3_origin, r_view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1)
                {
                        cscale = light->rtlight.corona * r_coronas.value * 0.25f;
                        scale = light->rtlight.radius * light->rtlight.coronasizescale;
@@ -95,7 +96,7 @@ void R_DrawCoronas(void)
        for (i = 0;i < r_refdef.numlights;i++)
        {
                rtlight = &r_refdef.lights[i];
-               if ((rtlight->flags & flag) && rtlight->corona * r_coronas.value > 0 && (dist = (DotProduct(rtlight->shadoworigin, r_view.forward) - viewdist)) >= 24.0f && CL_TraceBox(rtlight->shadoworigin, vec3_origin, vec3_origin, r_view.origin, true, NULL, SUPERCONTENTS_SOLID, false).fraction == 1)
+               if ((rtlight->flags & flag) && rtlight->corona * r_coronas.value > 0 && (dist = (DotProduct(rtlight->shadoworigin, r_view.forward) - viewdist)) >= 24.0f && CL_Move(rtlight->shadoworigin, vec3_origin, vec3_origin, r_view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1)
                {
                        cscale = rtlight->corona * r_coronas.value * 0.25f;
                        scale = rtlight->radius * rtlight->coronasizescale;
@@ -140,7 +141,7 @@ void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffu
                        light = &r_refdef.lights[i];
                        Matrix4x4_Transform(&light->matrix_worldtolight, p, v);
                        f = 1 - VectorLength2(v);
-                       if (f > 0 && CL_TraceBox(p, vec3_origin, vec3_origin, light->shadoworigin, false, NULL, SUPERCONTENTS_SOLID, false).fraction == 1)
+                       if (f > 0 && CL_Move(p, vec3_origin, vec3_origin, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1)
                                VectorMA(ambientcolor, f, light->currentcolor, ambientcolor);
                }
        }
index 25aa8f8..1ed8fe7 100644 (file)
@@ -2883,7 +2883,7 @@ void R_Shadow_SelectLightInView(void)