]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - clvm_cmds.c
disable joystick by default, and make joy_enable saved;
[xonotic/darkplaces.git] / clvm_cmds.c
index 0393f5d7f73bd37e1d70348d939eb830131f56b5..dabd7e65138a95c84bd43c4bedbe768689f3e5a2 100644 (file)
@@ -1,12 +1,14 @@
+#include "quakedef.h"
+
 #include "prvm_cmds.h"
 #include "csprogs.h"
 #include "cl_collision.h"
+#include "r_shadow.h"
 
 //============================================================================
 // Client
 //[515]: unsolved PROBLEMS
 //- finish player physics code (cs_runplayerphysics)
-//- fix R_AddDynamicLight
 //- EntWasFreed ?
 //- RF_DEPTHHACK is not like it should be
 //- add builtin that sets cl.viewangles instead of reading "input_angles" global
 //4 feature darkplaces csqc: add builtin to clientside qc for reading triangles of model meshes (useful to orient a ui along a triangle of a model mesh)
 //4 feature darkplaces csqc: add builtins to clientside qc for gl calls
 
-#ifndef PF_WARNING
-#define PF_WARNING(s) do{Con_Printf(s);PRVM_PrintState();return;}while(0)
-#endif
-
-//[515]: really need new list ?
-char *vm_cl_extensions =
-"DP_CON_SET "
-"DP_CON_SETA "
-"DP_CON_STARTMAP "
-"DP_EF_ADDITIVE "
-"DP_EF_BLUE "
-"DP_EF_FLAME "
-"DP_EF_FULLBRIGHT "
-"DP_EF_NODEPTHTEST "
-"DP_EF_NODRAW "
-"DP_EF_NOSHADOW "
-"DP_EF_RED "
-"DP_EF_STARDUST "
-"DP_ENT_ALPHA "
-"DP_ENT_CUSTOMCOLORMAP "
-"DP_ENT_GLOW "
-"DP_ENT_SCALE "
-"DP_GFX_EXTERNALTEXTURES "
-"DP_GFX_FOG "
-"DP_GFX_QUAKE3MODELTAGS "
-"DP_GFX_SKINFILES "
-"DP_GFX_SKYBOX "
-"DP_HALFLIFE_MAP "
-"DP_HALFLIFE_MAP_CVAR "
-"DP_HALFLIFE_SPRITE "
-"DP_INPUTBUTTONS "
-"DP_LITSPRITES "
-"DP_LITSUPPORT "
-"DP_MONSTERWALK "
-"DP_MOVETYPEBOUNCEMISSILE "
-"DP_MOVETYPEFOLLOW "
-"DP_QC_CHANGEPITCH "
-"DP_QC_COPYENTITY "
-"DP_QC_CVAR_STRING "
-"DP_QC_ETOS "
-"DP_QC_FINDCHAIN "
-"DP_QC_FINDCHAINFLAGS "
-"DP_QC_FINDCHAINFLOAT "
-"DP_QC_FINDFLAGS "
-"DP_QC_FINDFLOAT "
-"DP_QC_FS_SEARCH " // Black: same as in the menu qc
-"DP_QC_GETLIGHT "
-"DP_QC_GETSURFACE "
-"DP_QC_GETTAGINFO "
-"DP_QC_MINMAXBOUND "
-"DP_QC_MULTIPLETEMPSTRINGS "
-"DP_QC_RANDOMVEC "
-"DP_QC_SINCOSSQRTPOW "
-//"DP_QC_STRINGBUFFERS "       //[515]: not needed ?
-"DP_QC_TRACEBOX "
-//"DP_QC_TRACETOSS "
-"DP_QC_TRACE_MOVETYPE_HITMODEL "
-"DP_QC_TRACE_MOVETYPE_WORLDONLY "
-"DP_QC_VECTORVECTORS "
-"DP_QUAKE2_MODEL "
-"DP_QUAKE2_SPRITE "
-"DP_QUAKE3_MAP "
-"DP_QUAKE3_MODEL "
-"DP_REGISTERCVAR "
-"DP_SND_DIRECTIONLESSATTNNONE "
-"DP_SND_FAKETRACKS "
-"DP_SND_OGGVORBIS "
-"DP_SND_STEREOWAV "
-"DP_SOLIDCORPSE "
-"DP_SPRITE32 "
-"DP_SV_EFFECT "
-"DP_SV_ROTATINGBMODEL "
-"DP_SV_SLOWMO "
-"DP_TE_BLOOD "
-"DP_TE_BLOODSHOWER "
-"DP_TE_CUSTOMFLASH "
-"DP_TE_EXPLOSIONRGB "
-"DP_TE_FLAMEJET "
-"DP_TE_PARTICLECUBE "
-"DP_TE_PARTICLERAIN "
-"DP_TE_PARTICLESNOW "
-"DP_TE_PLASMABURN "
-"DP_TE_QUADEFFECTS1 "
-"DP_TE_SMALLFLASH "
-"DP_TE_SPARK "
-"DP_TE_STANDARDEFFECTBUILTINS "
-"EXT_BITSHIFT "
-"EXT_CSQC "
-"FRIK_FILE "
-"KRIMZON_SV_PARSECLIENTCOMMAND "
-"NEH_CMD_PLAY2 "
-"NXQ_GFX_LETTERBOX "
-"PRYDON_CLIENTCURSOR "
-"TENEBRAE_GFX_DLIGHTS "
-"TW_SV_STEPCONTROL "
-"NEXUIZ_PLAYERMODEL "
-"NEXUIZ_PLAYERSKIN "
-;
-
 sfx_t *S_FindName(const char *name);
-int CL_PointQ1Contents(const vec3_t p);
-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 CL_ExpandCSQCEntities(int num);
 void CSQC_RelinkAllEntities (int drawmask);
 void CSQC_RelinkCSQCEntities (void);
-char *Key_GetBind (int key);
-
-
-
-
+const char *Key_GetBind (int key);
 
 // #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);
@@ -142,14 +38,38 @@ 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)
-               PF_WARNING("setorigin: can not modify world entity\n");
+       {
+               VM_Warning("setorigin: can not modify world entity\n");
+               return;
+       }
        if (e->priv.required->free)
-               PF_WARNING("setorigin: can not modify free entity\n");
+       {
+               VM_Warning("setorigin: can not modify free entity\n");
+               return;
+       }
        org = PRVM_G_VECTOR(OFS_PARM1);
        VectorCopy (org, e->fields.client->origin);
+       CL_LinkEdict(e);
+}
+
+static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max)
+{
+       int             i;
+
+       for (i=0 ; i<3 ; i++)
+               if (min[i] > max[i])
+                       PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
+
+       // set derived values
+       VectorCopy (min, e->fields.client->mins);
+       VectorCopy (max, e->fields.client->maxs);
+       VectorSubtract (max, min, e->fields.client->size);
+
+       CL_LinkEdict (e);
 }
 
 // #3 void(entity e, string m) setmodel
@@ -157,38 +77,54 @@ void VM_CL_setmodel (void)
 {
        prvm_edict_t    *e;
        const char              *m;
-       struct model_s  *mod;
+       model_t *mod;
        int                             i;
 
        VM_SAFEPARMCOUNT(2, VM_CL_setmodel);
 
        e = PRVM_G_EDICT(OFS_PARM0);
+       e->fields.client->modelindex = 0;
+       e->fields.client->model = 0;
+
        m = PRVM_G_STRING(OFS_PARM1);
-       for(i=0;i<MAX_MODELS;i++)
-               if(!cl.csqc_model_precache[i])
-                       break;
-               else
-               if(!strcmp(cl.csqc_model_precache[i]->name, m))
+       mod = NULL;
+       for (i = 0;i < MAX_MODELS && cl.csqc_model_precache[i];i++)
+       {
+               if (!strcmp(cl.csqc_model_precache[i]->name, m))
                {
-                       e->fields.client->model = PRVM_SetEngineString(cl.csqc_model_precache[i]->name);
+                       mod = cl.csqc_model_precache[i];
+                       e->fields.client->model = PRVM_SetEngineString(mod->name);
                        e->fields.client->modelindex = -(i+1);
-                       return;
+                       break;
                }
+       }
 
-       for (i=0, mod = cl.model_precache[0] ; i < MAX_MODELS ; i++, mod = cl.model_precache[i])
-               if(mod)
-               if(!strcmp(mod->name, m))
+       if( !mod ) {
+               for (i = 0;i < MAX_MODELS;i++)
                {
-                       e->fields.client->model = PRVM_SetEngineString(mod->name);
-                       e->fields.client->modelindex = i;
-                       return;
+                       mod = cl.model_precache[i];
+                       if (mod && !strcmp(mod->name, m))
+                       {
+                               e->fields.client->model = PRVM_SetEngineString(mod->name);
+                               e->fields.client->modelindex = i;
+                               break;
+                       }
                }
-       e->fields.client->modelindex = 0;
-       e->fields.client->model = 0;
+       }
+
+       if( mod ) {
+               // TODO: check if this breaks needed consistency and maybe add a cvar for it too?? [1/10/2008 Black]
+               //SetMinMaxSize (e, mod->normalmins, mod->normalmaxs);
+       } 
+       else
+       {
+               SetMinMaxSize (e, vec3_origin, vec3_origin);
+               VM_Warning ("setmodel: model '%s' not precached\n", m);
+       }
 }
 
 // #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;
@@ -196,90 +132,232 @@ void VM_CL_setsize (void)
 
        e = PRVM_G_EDICT(OFS_PARM0);
        if (e == prog->edicts)
-               PF_WARNING("setsize: can not modify world entity\n");
+       {
+               VM_Warning("setsize: can not modify world entity\n");
+               return;
+       }
        if (e->priv.server->free)
-               PF_WARNING("setsize: can not modify free entity\n");
+       {
+               VM_Warning("setsize: can not modify free entity\n");
+               return;
+       }
        min = PRVM_G_VECTOR(OFS_PARM1);
        max = PRVM_G_VECTOR(OFS_PARM2);
 
-       VectorCopy (min, e->fields.client->mins);
-       VectorCopy (max, e->fields.client->maxs);
-       VectorSubtract (max, min, e->fields.client->size);
+       SetMinMaxSize( e, min, max );
+
+       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;
        prvm_edict_t            *entity;
-       int                             volume;
+       float                           volume;
        float                           attenuation;
 
        VM_SAFEPARMCOUNT(5, VM_CL_sound);
 
        entity = PRVM_G_EDICT(OFS_PARM0);
-       channel = PRVM_G_FLOAT(OFS_PARM1);
+       channel = (int)PRVM_G_FLOAT(OFS_PARM1);
        sample = PRVM_G_STRING(OFS_PARM2);
-       volume = PRVM_G_FLOAT(OFS_PARM3)*255;
+       volume = PRVM_G_FLOAT(OFS_PARM3);
        attenuation = PRVM_G_FLOAT(OFS_PARM4);
 
-       if (volume < 0 || volume > 255)
-               PF_WARNING("VM_CL_sound: volume must be in range 0-1\n");
+       if (volume < 0 || volume > 1)
+       {
+               VM_Warning("VM_CL_sound: volume must be in range 0-1\n");
+               return;
+       }
 
        if (attenuation < 0 || attenuation > 4)
-               PF_WARNING("VM_CL_sound: attenuation must be in range 0-4\n");
+       {
+               VM_Warning("VM_CL_sound: attenuation must be in range 0-4\n");
+               return;
+       }
 
        if (channel < 0 || channel > 7)
-               PF_WARNING("VM_CL_sound: channel must be in range 0-7\n");
+       {
+               VM_Warning("VM_CL_sound: channel must be in range 0-7\n");
+               return;
+       }
 
        S_StartSound(32768 + PRVM_NUM_FOR_EDICT(entity), channel, S_FindName(sample), entity->fields.client->origin, volume, attenuation);
 }
 
+// #483 void(vector origin, string sample, float volume, float attenuation) pointsound
+static void VM_CL_pointsound(void)
+{
+       const char                      *sample;
+       float                           volume;
+       float                           attenuation;
+       vec3_t                          org;
+
+       VM_SAFEPARMCOUNT(4, VM_CL_pointsound);
+
+       VectorCopy( PRVM_G_VECTOR(OFS_PARM0), org);
+       sample = PRVM_G_STRING(OFS_PARM1);
+       volume = PRVM_G_FLOAT(OFS_PARM2);
+       attenuation = PRVM_G_FLOAT(OFS_PARM3);
+
+       if (volume < 0 || volume > 1)
+       {
+               VM_Warning("VM_CL_pointsound: volume must be in range 0-1\n");
+               return;
+       }
+
+       if (attenuation < 0 || attenuation > 4)
+       {
+               VM_Warning("VM_CL_pointsound: attenuation must be in range 0-4\n");
+               return;
+       }
+
+       // Send World Entity as Entity to Play Sound (for CSQC, that is 32768)
+       S_StartSound(32768, 0, S_FindName(sample), org, volume, attenuation);
+}
+
 // #14 entity() spawn
-void VM_CL_spawn (void)
+static void VM_CL_spawn (void)
 {
        prvm_edict_t *ed;
        ed = PRVM_ED_Alloc();
-       ed->fields.client->entnum = PRVM_NUM_FOR_EDICT(ed);     //[515]: not needed any more ?
        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, 4, VM_CL_traceline);
+
+       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
 
-       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;
+       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_Move(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+
+       VM_SetTraceGlobals(&trace);
+}
+
+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.movevars_gravity * 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)
 {
-       const char *n;
-       VM_SAFEPARMCOUNT(1, VM_CL_precache_sound);
-       n = PRVM_G_STRING(OFS_PARM0);
-       S_PrecacheSound(n, 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)
 {
@@ -290,37 +368,31 @@ void VM_CL_precache_model (void)
        VM_SAFEPARMCOUNT(1, VM_CL_precache_model);
 
        name = PRVM_G_STRING(OFS_PARM0);
-       for(i=1;i<MAX_MODELS;i++)
-               if(!cl.csqc_model_precache[i])
-               {
-                       i = 0;
-                       break;
-               }
-               else
+       for (i = 0;i < MAX_MODELS && cl.csqc_model_precache[i];i++)
+       {
                if(!strcmp(cl.csqc_model_precache[i]->name, name))
                {
-                       i = -(i+1);
-                       break;
+                       PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
+                       return;
                }
-       if(i)
-       {
-               PRVM_G_FLOAT(OFS_RETURN) = i;
-               return;
        }
        PRVM_G_FLOAT(OFS_RETURN) = 0;
        m = Mod_ForName(name, false, false, false);
        if(m && m->loaded)
        {
-               for(i=1;i<MAX_MODELS;i++)
-                       if(!cl.csqc_model_precache[i])
-                               break;
-               if(i == MAX_MODELS)
-                       PF_WARNING("VM_CL_precache_model: no free models\n");
-               cl.csqc_model_precache[i] = (model_t*)m;
-               PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
+               for (i = 0;i < MAX_MODELS;i++)
+               {
+                       if (!cl.csqc_model_precache[i])
+                       {
+                               cl.csqc_model_precache[i] = (model_t*)m;
+                               PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
+                               return;
+                       }
+               }
+               VM_Warning("VM_CL_precache_model: no free models\n");
                return;
        }
-       Con_Printf("VM_CL_precache_model: model \"%s\" not found\n", name);
+       VM_Warning("VM_CL_precache_model: model \"%s\" not found\n", name);
 }
 
 int CSQC_EntitiesInBox (vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **list)
@@ -333,8 +405,6 @@ int CSQC_EntitiesInBox (vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **li
        {
                if (ent->priv.required->free)
                        continue;
-//             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);
                if(BoxesOverlap(mins, maxs, ent->fields.client->absmin, ent->fields.client->absmax))
                        list[k++] = ent;
        }
@@ -342,7 +412,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;
@@ -350,6 +420,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);
@@ -387,7 +459,7 @@ void VM_CL_findradius (void)
                        eorg[2] -= bound(ent->fields.client->mins[2], eorg[2], ent->fields.client->maxs[2]);
                }
                else
-                       VectorMAMAM(1, eorg, 0.5f, ent->fields.client->mins, 0.5f, ent->fields.client->maxs, eorg);
+                       VectorMAMAM(1, eorg, -0.5f, ent->fields.client->mins, -0.5f, ent->fields.client->maxs, eorg);
                if (DotProduct(eorg, eorg) < radius2)
                {
                        ent->fields.client->chain = PRVM_EDICT_TO_PROG(chain);
@@ -399,32 +471,41 @@ 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;
 
        ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
        if (ent == prog->edicts)
-               PF_WARNING("droptofloor: can not modify world entity\n");
+       {
+               VM_Warning("droptofloor: can not modify world entity\n");
+               return;
+       }
        if (ent->priv.server->free)
-               PF_WARNING("droptofloor: can not modify free entity\n");
+       {
+               VM_Warning("droptofloor: can not modify free entity\n");
+               return;
+       }
 
        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;
@@ -432,30 +513,33 @@ 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;
 
        VM_SAFEPARMCOUNT(2, VM_CL_lightstyle);
 
-       i = PRVM_G_FLOAT(OFS_PARM0);
+       i = (int)PRVM_G_FLOAT(OFS_PARM0);
        c = PRVM_G_STRING(OFS_PARM1);
-       if (i >= MAX_LIGHTSTYLES)
-               PF_WARNING("VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
-       strlcpy (cl_lightstyle[i].map,  MSG_ReadString(), sizeof (cl_lightstyle[i].map));
-       cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
-       cl_lightstyle[i].length = (int)strlen(cl_lightstyle[i].map);
+       if (i >= cl.max_lightstyle)
+       {
+               VM_Warning("VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
+               return;
+       }
+       strlcpy (cl.lightstyle[i].map,  MSG_ReadString(), sizeof (cl.lightstyle[i].map));
+       cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
+       cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map);
 }
 
 // #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);
@@ -474,7 +558,7 @@ void VM_CL_checkbottom (void)
                {
                        start[0] = x ? maxs[0] : mins[0];
                        start[1] = y ? maxs[1] : mins[1];
-                       if (!(CL_PointSuperContents(start) & SUPERCONTENTS_SOLID))
+                       if (!(CL_PointSuperContents(start) & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY)))
                                goto realcheck;
                }
 
@@ -493,7 +577,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;
@@ -507,7 +591,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];
@@ -520,14 +604,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) = CL_PointQ1Contents(PRVM_G_VECTOR(OFS_PARM0));
+       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;
@@ -536,144 +620,13 @@ void VM_CL_particle (void)
 
        org = PRVM_G_VECTOR(OFS_PARM0);
        dir = PRVM_G_VECTOR(OFS_PARM1);
-       color = PRVM_G_FLOAT(OFS_PARM2);
-       count = PRVM_G_FLOAT(OFS_PARM3);
-       if (cl_particles_blood_bloodhack.integer)
-       {
-               if (color == 73)
-               {
-                       // regular blood
-                       CL_BloodPuff(org, dir, count / 2);
-                       return;
-               }
-               if (color == 225)
-               {
-                       // lightning blood
-                       CL_BloodPuff(org, dir, count / 2);
-                       return;
-               }
-       }
-       CL_RunParticleEffect (org, dir, color, count);
-}
-
-// #49 void(entity ent, float ideal_yaw, float speed_yaw) ChangeYaw
-void VM_CL_changeyaw (void)
-{
-       prvm_edict_t    *ent;
-       float                   ideal, current, move, speed;
-       VM_SAFEPARMCOUNT(3, VM_CL_changeyaw);
-
-       ent = PRVM_G_EDICT(OFS_PARM0);
-       if (ent == prog->edicts)
-               PF_WARNING("changeyaw: can not modify world entity\n");
-       if (ent->priv.server->free)
-               PF_WARNING("changeyaw: can not modify free entity\n");
-       current = ANGLEMOD(ent->fields.client->angles[1]);
-       ideal = PRVM_G_FLOAT(OFS_PARM1);
-       speed = PRVM_G_FLOAT(OFS_PARM2);
-
-       if (current == ideal)
-               return;
-       move = ideal - current;
-       if (ideal > current)
-       {
-               if (move >= 180)
-                       move = move - 360;
-       }
-       else
-       {
-               if (move <= -180)
-                       move = move + 360;
-       }
-       if (move > 0)
-       {
-               if (move > speed)
-                       move = speed;
-       }
-       else
-       {
-               if (move < -speed)
-                       move = -speed;
-       }
-
-       ent->fields.client->angles[1] = ANGLEMOD (current + move);
-}
-
-// #63 void(entity ent, float ideal_pitch, float speed_pitch) changepitch (DP_QC_CHANGEPITCH)
-void VM_CL_changepitch (void)
-{
-       prvm_edict_t            *ent;
-       float                           ideal, current, move, speed;
-       VM_SAFEPARMCOUNT(3, VM_CL_changepitch);
-
-       ent = PRVM_G_EDICT(OFS_PARM0);
-       if (ent == prog->edicts)
-               PF_WARNING("changepitch: can not modify world entity\n");
-       if (ent->priv.server->free)
-               PF_WARNING("changepitch: can not modify free entity\n");
-       current = ANGLEMOD( ent->fields.client->angles[0] );
-       ideal = PRVM_G_FLOAT(OFS_PARM1);
-       speed = PRVM_G_FLOAT(OFS_PARM2);
-
-       if (current == ideal)
-               return;
-       move = ideal - current;
-       if (ideal > current)
-       {
-               if (move >= 180)
-                       move = move - 360;
-       }
-       else
-       {
-               if (move <= -180)
-                       move = move + 360;
-       }
-       if (move > 0)
-       {
-               if (move > speed)
-                       move = speed;
-       }
-       else
-       {
-               if (move < -speed)
-                       move = -speed;
-       }
-
-       ent->fields.client->angles[0] = ANGLEMOD (current + move);
-}
-
-// #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)
-               PF_WARNING("tracetoss: can not use world entity\n");
-       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);
-*/
+       color = (int)PRVM_G_FLOAT(OFS_PARM2);
+       count = (int)PRVM_G_FLOAT(OFS_PARM3);
+       CL_ParticleEffect(EFFECT_SVC_PARTICLE, count, org, org, dir, dir, NULL, color);
 }
 
 // #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;
@@ -683,36 +636,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;
@@ -731,239 +656,247 @@ void VM_CL_getlight (void)
 
 //============================================================================
 //[515]: SCENE MANAGER builtins
-void V_CalcRefdef (void);//view.c
-void CSQC_R_ClearScreen (void);//gl_rmain.c
-void CSQC_R_RenderScene (void);//gl_rmain.c
-void CSQC_AddEntity (int n);//csprogs.c
-void CSQC_ClearCSQCEntities (void);
-
-matrix4x4_t csqc_listenermatrix;
-qboolean csqc_usecsqclistener = false, csqc_frame = false;//[515]: per-frame
-qboolean csqc_onground;
-
-static char *particleeffect_names[] =
-{
-       "TE_SPIKE",
-       "TE_SUPERSPIKE",
-       "TE_GUNSHOT",
-       "TE_EXPLOSION",
-       "TE_TAREXPLOSION",
-       "TE_LIGHTNING1",//trail
-       "TE_LIGHTNING2",//trail
-       "TE_WIZSPIKE",
-       "TE_KNIGHTSPIKE",
-       "TE_LIGHTNING3",//trail
-       "TE_LAVASPLASH",
-       "TE_TELEPORT",
-       "TE_EXPLOSION2",
-       "TE_BEAM",//trail
-       "TE_EXPLOSION3",
-       "",//TE_LIGHTNING4NEH
-       "TE_BLOOD",
-       "TE_SPARK",
-       "",//TE_BLOODSHOWER
-       "TE_EXPLOSIONRGB",
-       "",//unused
-       "",
-       "",
-       "TE_GUNSHOTQUAD",
-       "TE_SPIKEQUAD",
-       "TE_SUPERSPIKEQUAD",
-       "TE_EXPLOSIONQUAD",
-       "",
-       "",
-       "",
-       "TE_FLAMEJET",
-       "TE_PLASMABURN",
-       "TE_TEI_G3",
-       "TE_TEI_SMOKE",
-       "TE_TEI_BIGEXPLOSION",
-       "TE_TEI_PLASMAHIT",
-
-
-       //trail effects (as modelflags)
-       "EF_ROCKET",
-       "EF_GRENADE",
-       "EF_GIB",
-       "EF_TRACER",
-       "EF_ZOMGIB",
-       "EF_TRACER2",
-       "EF_TRACER3",
-       "EF_NEH_CIGAR",
-       "EF_NEXUIZ_PLASMA",
-       "EF_GLOWTRAIL",
-};
-
-#define CSQC_TRAILSTART 36
-static const int particleeffects_num = sizeof(particleeffect_names)/sizeof(char*);
+extern qboolean CSQC_AddRenderEdict (prvm_edict_t *ed);//csprogs.c
 
 static void CSQC_R_RecalcView (void)
 {
        extern matrix4x4_t viewmodelmatrix;
-       Matrix4x4_CreateIdentity(&viewmodelmatrix);
-       Matrix4x4_CreateIdentity(&r_refdef.viewentitymatrix);
-       Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], 1);
-       Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], 0.3);
+       Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], 1);
+       Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], cl_viewmodel_scale.value);
 }
 
+void CL_RelinkLightFlashes(void);
 //#300 void() clearscene (EXT_CSQC)
-void VM_R_ClearScene (void)
-{
-       VM_SAFEPARMCOUNT(0, VM_R_ClearScene);
-//     CSQC_R_RecalcView();
-       if(csqc_frame)
-               CSQC_ClearCSQCEntities();
-       CSQC_R_ClearScreen();
+void VM_CL_R_ClearScene (void)
+{
+       VM_SAFEPARMCOUNT(0, VM_CL_R_ClearScene);
+       // clear renderable entity and light lists
+       r_refdef.scene.numentities = 0;
+       r_refdef.scene.numlights = 0;
+       // FIXME: restore these to the values from VM_CL_UpdateView
+       r_refdef.view.x = 0;
+       r_refdef.view.y = 0;
+       r_refdef.view.z = 0;
+       r_refdef.view.width = vid.width;
+       r_refdef.view.height = vid.height;
+       r_refdef.view.depth = 1;
+       // FIXME: restore frustum_x/frustum_y
+       r_refdef.view.useperspective = true;
+       r_refdef.view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom;
+       r_refdef.view.frustum_x = r_refdef.view.frustum_y * (float)r_refdef.view.width / (float)r_refdef.view.height / vid_pixelheight.value;
+       r_refdef.view.frustum_x *= r_refdef.frustumscale_x;
+       r_refdef.view.frustum_y *= r_refdef.frustumscale_y;
+       r_refdef.view.ortho_x = scr_fov.value * (3.0 / 4.0) * (float)r_refdef.view.width / (float)r_refdef.view.height / vid_pixelheight.value;
+       r_refdef.view.ortho_y = scr_fov.value * (3.0 / 4.0);
+       r_refdef.view.clear = true;
+       // FIXME: restore cl.csqc_origin
+       // FIXME: restore cl.csqc_angles
+       cl.csqc_vidvars.drawworld = true;
+       cl.csqc_vidvars.drawenginesbar = false;
+       cl.csqc_vidvars.drawcrosshair = false;
 }
 
 //#301 void(float mask) addentities (EXT_CSQC)
-void VM_R_AddEntities (void)
+extern void CSQC_Predraw (prvm_edict_t *ed);//csprogs.c
+extern void CSQC_Think (prvm_edict_t *ed);//csprogs.c
+void VM_CL_R_AddEntities (void)
 {
-       VM_SAFEPARMCOUNT(1, VM_R_AddEntities);
-       csqc_drawmask = PRVM_G_FLOAT(OFS_PARM0);
+       int                     i, drawmask;
+       prvm_edict_t *ed;
+       VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntities);
+       drawmask = (int)PRVM_G_FLOAT(OFS_PARM0);
+       CSQC_RelinkAllEntities(drawmask);
+       CL_RelinkLightFlashes();
+
+       prog->globals.client->time = cl.time;
+       for(i=1;i<prog->num_edicts;i++)
+       {
+               ed = &prog->edicts[i];
+               if(ed->priv.required->free)
+                       continue;
+               CSQC_Think(ed);
+               if(ed->priv.required->free)
+                       continue;
+               // note that for RF_USEAXIS entities, Predraw sets v_forward/v_right/v_up globals that are read by CSQC_AddRenderEdict
+               CSQC_Predraw(ed);
+               if(ed->priv.required->free)
+                       continue;
+               if(!((int)ed->fields.client->drawmask & drawmask))
+                       continue;
+               CSQC_AddRenderEdict(ed);
+       }
 }
 
 //#302 void(entity ent) addentity (EXT_CSQC)
-void VM_R_AddEntity (void)
+void VM_CL_R_AddEntity (void)
 {
-       VM_SAFEPARMCOUNT(1, VM_R_AddEntity);
-       CSQC_AddEntity(PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)));
+       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)
+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 = PRVM_G_FLOAT(OFS_PARM0);
+       c = (int)PRVM_G_FLOAT(OFS_PARM0);
        f = PRVM_G_VECTOR(OFS_PARM1);
        k = PRVM_G_FLOAT(OFS_PARM1);
 
        switch(c)
        {
-       case VF_MIN:                    r_refdef.x = f[0];
-                                                       r_refdef.y = f[1];
-                                                       break;
-       case VF_MIN_X:                  r_refdef.x = k;
-                                                       break;
-       case VF_MIN_Y:                  r_refdef.y = k;
-                                                       break;
-       case VF_SIZE:                   r_refdef.width = f[0];
-                                                       r_refdef.height = f[1];
-                                                       break;
-       case VF_SIZE_Y:                 r_refdef.width = k;
-                                                       break;
-       case VF_SIZE_X:                 r_refdef.height = k;
-                                                       break;
-       case VF_VIEWPORT:               r_refdef.x = f[0];
-                                                       r_refdef.y = f[1];
-                                                       f = PRVM_G_VECTOR(OFS_PARM2);
-                                                       r_refdef.width = f[0];
-                                                       r_refdef.height = f[1];
-                                                       break;
-       case VF_FOV:                    //r_refdef.fov_x = f[0]; // FIXME!
-                                                       //r_refdef.fov_y = f[1]; // FIXME!
-                                                       break;
-       case VF_FOVX:                   //r_refdef.fov_x = k; // FIXME!
-                                                       break;
-       case VF_FOVY:                   //r_refdef.fov_y = k; // FIXME!
-                                                       break;
-       case VF_ORIGIN:                 VectorCopy(f, csqc_origin);
-                                                       CSQC_R_RecalcView();
-                                                       break;
-       case VF_ORIGIN_X:               csqc_origin[0] = k;
-                                                       CSQC_R_RecalcView();
-                                                       break;
-       case VF_ORIGIN_Y:               csqc_origin[1] = k;
-                                                       CSQC_R_RecalcView();
-                                                       break;
-       case VF_ORIGIN_Z:               csqc_origin[2] = k;
-                                                       CSQC_R_RecalcView();
-                                                       break;
-       case VF_ANGLES:                 VectorCopy(f, csqc_angles);
-                                                       CSQC_R_RecalcView();
-                                                       break;
-       case VF_ANGLES_X:               csqc_angles[0] = k;
-                                                       CSQC_R_RecalcView();
-                                                       break;
-       case VF_ANGLES_Y:               csqc_angles[1] = k;
-                                                       CSQC_R_RecalcView();
-                                                       break;
-       case VF_ANGLES_Z:               csqc_angles[2] = k;
-                                                       CSQC_R_RecalcView();
-                                                       break;
-       case VF_DRAWWORLD:              cl.csqc_vidvars.drawworld = k;
-                                                       break;
-       case VF_DRAWENGINESBAR: cl.csqc_vidvars.drawenginesbar = k;
-                                                       break;
-       case VF_DRAWCROSSHAIR:  cl.csqc_vidvars.drawcrosshair = k;
-                                                       break;
-
-       case VF_CL_VIEWANGLES:  VectorCopy(f, cl.viewangles);
-                                                       break;
-       case VF_CL_VIEWANGLES_X:cl.viewangles[0] = k;
-                                                       break;
-       case VF_CL_VIEWANGLES_Y:cl.viewangles[1] = k;
-                                                       break;
-       case VF_CL_VIEWANGLES_Z:cl.viewangles[2] = k;
-                                                       break;
-
-       default:                                Con_Printf("VM_R_SetView : unknown parm %i\n", c);
-                                                       PRVM_G_FLOAT(OFS_RETURN) = 0;
-                                                       return;
-       }
-       PRVM_G_FLOAT(OFS_RETURN) = 1;
-}
-
-//#304 void() renderscene (EXT_CSQC)
-void VM_R_RenderScene (void) //#134
-{
-       VM_SAFEPARMCOUNT(0, VM_R_RenderScene);
-
-       if(csqc_frame)
-       {
-               CSQC_RelinkCSQCEntities();
-               CSQC_RelinkAllEntities(csqc_drawmask);
-       }
-
-       CSQC_R_RenderScene();
-}
+       case VF_MIN:
+               r_refdef.view.x = (int)(f[0] * vid.width / vid_conwidth.value);
+               r_refdef.view.y = (int)(f[1] * vid.height / vid_conheight.value);
+               break;
+       case VF_MIN_X:
+               r_refdef.view.x = (int)(k * vid.width / vid_conwidth.value);
+               break;
+       case VF_MIN_Y:
+               r_refdef.view.y = (int)(k * vid.height / vid_conheight.value);
+               break;
+       case VF_SIZE:
+               r_refdef.view.width = (int)(f[0] * vid.width / vid_conwidth.value);
+               r_refdef.view.height = (int)(f[1] * vid.height / vid_conheight.value);
+               break;
+       case VF_SIZE_Y:
+               r_refdef.view.width = (int)(k * vid.width / vid_conwidth.value);
+               break;
+       case VF_SIZE_X:
+               r_refdef.view.height = (int)(k * vid.height / vid_conheight.value);
+               break;
+       case VF_VIEWPORT:
+               r_refdef.view.x = (int)(f[0] * vid.width / vid_conwidth.value);
+               r_refdef.view.y = (int)(f[1] * vid.height / vid_conheight.value);
+               f = PRVM_G_VECTOR(OFS_PARM2);
+               r_refdef.view.width = (int)(f[0] * vid.width / vid_conwidth.value);
+               r_refdef.view.height = (int)(f[1] * vid.height / vid_conheight.value);
+               break;
+       case VF_FOV:
+               r_refdef.view.frustum_x = tan(f[0] * M_PI / 360.0);r_refdef.view.ortho_x = f[0];
+               r_refdef.view.frustum_y = tan(f[1] * M_PI / 360.0);r_refdef.view.ortho_y = f[1];
+               break;
+       case VF_FOVX:
+               r_refdef.view.frustum_x = tan(k * M_PI / 360.0);r_refdef.view.ortho_x = k;
+               break;
+       case VF_FOVY:
+               r_refdef.view.frustum_y = tan(k * M_PI / 360.0);r_refdef.view.ortho_y = k;
+               break;
+       case VF_ORIGIN:
+               VectorCopy(f, cl.csqc_origin);
+               CSQC_R_RecalcView();
+               break;
+       case VF_ORIGIN_X:
+               cl.csqc_origin[0] = k;
+               CSQC_R_RecalcView();
+               break;
+       case VF_ORIGIN_Y:
+               cl.csqc_origin[1] = k;
+               CSQC_R_RecalcView();
+               break;
+       case VF_ORIGIN_Z:
+               cl.csqc_origin[2] = k;
+               CSQC_R_RecalcView();
+               break;
+       case VF_ANGLES:
+               VectorCopy(f, cl.csqc_angles);
+               CSQC_R_RecalcView();
+               break;
+       case VF_ANGLES_X:
+               cl.csqc_angles[0] = k;
+               CSQC_R_RecalcView();
+               break;
+       case VF_ANGLES_Y:
+               cl.csqc_angles[1] = k;
+               CSQC_R_RecalcView();
+               break;
+       case VF_ANGLES_Z:
+               cl.csqc_angles[2] = k;
+               CSQC_R_RecalcView();
+               break;
+       case VF_DRAWWORLD:
+               cl.csqc_vidvars.drawworld = k;
+               break;
+       case VF_DRAWENGINESBAR:
+               cl.csqc_vidvars.drawenginesbar = k;
+               break;
+       case VF_DRAWCROSSHAIR:
+               cl.csqc_vidvars.drawcrosshair = k;
+               break;
+       case VF_CL_VIEWANGLES:
+               VectorCopy(f, cl.viewangles);
+               break;
+       case VF_CL_VIEWANGLES_X:
+               cl.viewangles[0] = k;
+               break;
+       case VF_CL_VIEWANGLES_Y:
+               cl.viewangles[1] = k;
+               break;
+       case VF_CL_VIEWANGLES_Z:
+               cl.viewangles[2] = k;
+               break;
+       case VF_PERSPECTIVE:
+               r_refdef.view.useperspective = k != 0;
+               break;
+       case VF_CLEARSCREEN:
+               r_refdef.view.clear = k ? true : false;
+               break;
+       default:
+               PRVM_G_FLOAT(OFS_RETURN) = 0;
+               VM_Warning("VM_CL_R_SetView : unknown parm %i\n", c);
+               return;
+       }
+       PRVM_G_FLOAT(OFS_RETURN) = 1;
+}
+
+//#304 void() renderscene (EXT_CSQC)
+void VM_CL_R_RenderScene (void)
+{
+       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
+       CL_UpdateViewEntities();
+       // now draw stuff!
+       R_RenderView();
+}
 
 //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
-void VM_R_AddDynamicLight (void)
+void VM_CL_R_AddDynamicLight (void)
 {
        float           *pos, *col;
-       matrix4x4_t     tempmatrix;
-       VM_SAFEPARMCOUNT(3, VM_R_AddDynamicLight);
+       matrix4x4_t     matrix;
+       VM_SAFEPARMCOUNTRANGE(3, 3, VM_CL_R_AddDynamicLight);
+
+       // if we've run out of dlights, just return
+       if (r_refdef.scene.numlights >= MAX_DLIGHTS)
+               return;
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        col = PRVM_G_VECTOR(OFS_PARM2);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
-       CL_AllocDlight(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), col[0], col[1], col[2], 500, 0, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       //CL_AllocDlight(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), col[0], col[1], col[2], 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       Matrix4x4_CreateFromQuakeEntity(&matrix, pos[0], pos[1], pos[2], 0, 0, 0, PRVM_G_FLOAT(OFS_PARM1));
+       R_RTLight_Update(&r_refdef.scene.lights[r_refdef.scene.numlights++], false, &matrix, col, -1, NULL, true, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
 }
 
 //============================================================================
 
 //#310 vector (vector v) cs_unproject (EXT_CSQC)
-void VM_CL_unproject (void)
+static void VM_CL_unproject (void)
 {
        float   *f;
        vec3_t  temp;
 
        VM_SAFEPARMCOUNT(1, VM_CL_unproject);
        f = PRVM_G_VECTOR(OFS_PARM0);
-       VectorSet(temp, f[2], f[0] * f[2] * -r_refdef.frustum_x * 2.0 / r_refdef.width, f[1] * f[2] * -r_refdef.frustum_y * 2.0 / r_refdef.height);
-       Matrix4x4_Transform(&r_refdef.viewentitymatrix, temp, PRVM_G_VECTOR(OFS_RETURN));
+       VectorSet(temp, f[2], f[0] * f[2] * -r_refdef.view.frustum_x * 2.0 / r_refdef.view.width, f[1] * f[2] * -r_refdef.view.frustum_y * 2.0 / r_refdef.view.height);
+       Matrix4x4_Transform(&r_refdef.view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN));
 }
 
 //#311 vector (vector v) cs_project (EXT_CSQC)
-void VM_CL_project (void)
+static void VM_CL_project (void)
 {
        float   *f;
        vec3_t  v;
@@ -971,13 +904,13 @@ void VM_CL_project (void)
 
        VM_SAFEPARMCOUNT(1, VM_CL_project);
        f = PRVM_G_VECTOR(OFS_PARM0);
-       Matrix4x4_Invert_Simple(&m, &r_refdef.viewentitymatrix);
+       Matrix4x4_Invert_Simple(&m, &r_refdef.view.matrix);
        Matrix4x4_Transform(&m, f, v);
-       VectorSet(PRVM_G_VECTOR(OFS_RETURN), v[1]/v[0]/-r_refdef.frustum_x*0.5*r_refdef.width, v[2]/v[0]/-r_refdef.frustum_y*r_refdef.height*0.5, v[0]);
+       VectorSet(PRVM_G_VECTOR(OFS_RETURN), v[1]/v[0]/-r_refdef.view.frustum_x*0.5*r_refdef.view.width, v[2]/v[0]/-r_refdef.view.frustum_y*r_refdef.view.height*0.5, v[0]);
 }
 
 //#330 float(float stnum) getstatf (EXT_CSQC)
-void VM_CL_getstatf (void)
+static void VM_CL_getstatf (void)
 {
        int i;
        union
@@ -986,10 +919,10 @@ void VM_CL_getstatf (void)
                int l;
        }dat;
        VM_SAFEPARMCOUNT(1, VM_CL_getstatf);
-       i = PRVM_G_FLOAT(OFS_PARM0);
+       i = (int)PRVM_G_FLOAT(OFS_PARM0);
        if(i < 0 || i >= MAX_CL_STATS)
        {
-               Con_Printf("VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
+               VM_Warning("VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
                return;
        }
        dat.l = cl.stats[i];
@@ -997,327 +930,166 @@ 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);
-       index = PRVM_G_FLOAT(OFS_PARM0);
+       int firstbit, bitcount;
+
+       VM_SAFEPARMCOUNTRANGE(1, 3, VM_CL_getstati);
+
+       index = (int)PRVM_G_FLOAT(OFS_PARM0);
+       if (prog->argc > 1)
+       {
+               firstbit = (int)PRVM_G_FLOAT(OFS_PARM1);
+               if (prog->argc > 2)
+                       bitcount = (int)PRVM_G_FLOAT(OFS_PARM2);
+               else
+                       bitcount = 1;
+       }
+       else
+       {
+               firstbit = 0;
+               bitcount = 32;
+       }
 
        if(index < 0 || index >= MAX_CL_STATS)
        {
-               Con_Printf("VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
+               VM_Warning("VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
                return;
        }
        i = cl.stats[index];
+       if (bitcount != 32)     //32 causes the mask to overflow, so there's nothing to subtract from.
+               i = (((unsigned int)i)&(((1<<bitcount)-1)<<firstbit))>>firstbit;
        PRVM_G_FLOAT(OFS_RETURN) = i;
 }
 
 //#332 string(float firststnum) getstats (EXT_CSQC)
-void VM_CL_getstats (void)
+static void VM_CL_getstats (void)
 {
        int i;
-       char *t;
+       char t[17];
        VM_SAFEPARMCOUNT(1, VM_CL_getstats);
-       i = PRVM_G_FLOAT(OFS_PARM0);
+       i = (int)PRVM_G_FLOAT(OFS_PARM0);
        if(i < 0 || i > MAX_CL_STATS-4)
        {
-               Con_Printf("VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
+               PRVM_G_INT(OFS_RETURN) = OFS_NULL;
+               VM_Warning("VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
                return;
        }
-       t = VM_GetTempString();
-       strlcpy(t, (char*)&cl.stats[i], 16);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
+       strlcpy(t, (char*)&cl.stats[i], sizeof(t));
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
 }
 
 //#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;
-       struct model_s  *m;
+       struct model_s  *model;
 
        VM_SAFEPARMCOUNT(2, VM_CL_setmodelindex);
 
        t = PRVM_G_EDICT(OFS_PARM0);
+
        i = (int)PRVM_G_FLOAT(OFS_PARM1);
 
        t->fields.client->model = 0;
        t->fields.client->modelindex = 0;
 
-       if(!i)
+       if (!i)
                return;
-       if(i<0)
+
+       model = CL_GetModelByIndex(i);
+       if (!model)
        {
-               i = -(i+1);
-               if(i >= MAX_MODELS)
-                       PF_WARNING("VM_CL_setmodelindex >= MAX_MODELS\n");
-               m = cl.csqc_model_precache[i];
+               VM_Warning("VM_CL_setmodelindex: null model\n");
+               return;
        }
-       else
-               if(i >= MAX_MODELS)
-                       PF_WARNING("VM_CL_setmodelindex >= MAX_MODELS\n");
-               else
-                       m = cl.model_precache[i];
-       if(!m)
-               PF_WARNING("VM_CL_setmodelindex: null model\n");
-       t->fields.client->model = PRVM_SetEngineString(m->name);
+       t->fields.client->model = PRVM_SetEngineString(model->name);
        t->fields.client->modelindex = i;
+
+       // TODO: check if this breaks needed consistency and maybe add a cvar for it too?? [1/10/2008 Black]
+       if (model)
+       {
+               SetMinMaxSize (t, model->normalmins, model->normalmaxs);
+       }
+       else
+               SetMinMaxSize (t, vec3_origin, vec3_origin);
 }
 
 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
-void VM_CL_modelnameforindex (void)
+static void VM_CL_modelnameforindex (void)
 {
-       int i;
+       model_t *model;
 
        VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex);
 
-       PRVM_G_INT(OFS_RETURN) = 0;
-       i = PRVM_G_FLOAT(OFS_PARM0);
-       if(i<0)
-       {
-               i = -(i+1);
-               if(i >= MAX_MODELS)
-                       PF_WARNING("VM_CL_modelnameforindex >= MAX_MODELS\n");
-               if(cl.csqc_model_precache[i])
-                       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(cl.csqc_model_precache[i]->name);
-               return;
-       }
-       if(i >= MAX_MODELS)
-               PF_WARNING("VM_CL_modelnameforindex >= MAX_MODELS\n");
-       if(cl.model_precache[i])
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(cl.model_precache[i]->name);
+       PRVM_G_INT(OFS_RETURN) = OFS_NULL;
+       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)
 {
-       const char      *n;
        int                     i;
        VM_SAFEPARMCOUNT(1, VM_CL_particleeffectnum);
-       n = PRVM_G_STRING(OFS_PARM0);
-       for(i=0;i<particleeffects_num;i++)
-               if(!strcasecmp(particleeffect_names[i], n))
-               {
-                       PRVM_G_FLOAT(OFS_RETURN) = i;
-                       return;
-               }
-       PRVM_G_FLOAT(OFS_RETURN) = -1;
-}
-
-void CSQC_ParseBeam (int ent, vec3_t start, vec3_t end, model_t *m, int lightning)
-{
-       int             i;
-       beam_t  *b;
-
-       // override any beam with the same entity
-       for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
-       {
-               if (b->entity == ent && ent)
-               {
-                       //b->entity = ent;
-                       b->lightning = lightning;
-                       b->relativestartvalid = (ent && cl_csqcentities[ent].state_current.active) ? 2 : 0;
-                       b->model = m;
-                       b->endtime = cl.time + 0.2;
-                       VectorCopy (start, b->start);
-                       VectorCopy (end, b->end);
-                       return;
-               }
-       }
-
-       // find a free beam
-       for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
-       {
-               if (!b->model || b->endtime < cl.time)
-               {
-                       b->entity = ent;
-                       b->lightning = lightning;
-                       b->relativestartvalid = (ent && cl_csqcentities[ent].state_current.active) ? 2 : 0;
-                       b->model = m;
-                       b->endtime = cl.time + 0.2;
-                       VectorCopy (start, b->start);
-                       VectorCopy (end, b->end);
-                       return;
-               }
-       }
-       Con_Print("beam list overflow!\n");
+       i = CL_ParticleEffectIndexForName(PRVM_G_STRING(OFS_PARM0));
+       if (i == 0)
+               i = -1;
+       PRVM_G_FLOAT(OFS_RETURN) = i;
 }
 
 // #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, entnum, col;
+       int                             i;
        float                   *start, *end;
-       entity_t                *ent;
-       VM_SAFEPARMCOUNT(4, VM_CL_trailparticles);
+       prvm_edict_t    *t;
+       VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_trailparticles);
 
-       entnum  = PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0));
-       i               = PRVM_G_FLOAT(OFS_PARM1);
+       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);
 
-       if(i >= particleeffects_num)
-               return;
-       if (entnum >= MAX_EDICTS)
-       {
-               Con_Printf("CSQC_ParseBeam: invalid entity number %i\n", entnum);
-               return;
-       }
-       if (entnum >= cl_max_csqcentities)
-               CL_ExpandCSQCEntities(entnum);
-
-       ent = &cl_csqcentities[entnum];
-
-       if(prog->argc > 4)
-               col = PRVM_G_FLOAT(OFS_PARM4);
-       else
-               col = ent->state_current.glowcolor;
-
-       switch(i)
-       {
-       case TE_LIGHTNING1:
-               CSQC_ParseBeam(entnum, start, end, cl.model_bolt, true);
-               break;
-       case TE_LIGHTNING2:
-               CSQC_ParseBeam(entnum, start, end, cl.model_bolt2, true);
-               break;
-       case TE_LIGHTNING3:
-               CSQC_ParseBeam(entnum, start, end, cl.model_bolt3, false);
-               break;
-       case TE_BEAM:
-               CSQC_ParseBeam(entnum, start, end, cl.model_beam, false);
-               break;
-       default:
-               CL_RocketTrail(start, end, i-CSQC_TRAILSTART, col, ent);
-               break;
-       }
+       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;
-       if(prog->argc < 2)
-               VM_SAFEPARMCOUNT(2, VM_CL_pointparticles);
-       i = PRVM_G_FLOAT(OFS_PARM0);
+       VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_pointparticles);
+       i = (int)PRVM_G_FLOAT(OFS_PARM0);
        f = PRVM_G_VECTOR(OFS_PARM1);
-       if(prog->argc >= 4)
-       {
-               v = PRVM_G_VECTOR(OFS_PARM2);
-               n = PRVM_G_FLOAT(OFS_PARM3);
-       }
-       else
-       {
-               v = vec3_origin;
-               n = 15;
-       }
-
-       if(i >= particleeffects_num)
-               return;
-
-       switch(i)
-       {
-       case TE_SPIKE:
-       case TE_SPIKEQUAD:
-       case TE_GUNSHOT:
-       case TE_GUNSHOTQUAD:
-               CL_SparkShower(f, v, 15, 1);
-               CL_Smoke(f, v, 15);
-               if (cl_particles_bulletimpacts.integer)
-                       CL_BulletMark(f);
-               break;
-       case TE_SUPERSPIKE:
-       case TE_SUPERSPIKEQUAD:
-               CL_SparkShower(f, v, 30, 1);
-               CL_Smoke(f, v, 30);
-               if (cl_particles_bulletimpacts.integer)
-                       CL_BulletMark(f);
-               break;
-       case TE_EXPLOSION:
-       case TE_EXPLOSIONQUAD:
-       case TE_TEI_BIGEXPLOSION:
-               CL_ParticleExplosion(f);
-               break;
-       case TE_TAREXPLOSION:
-               CL_BlobExplosion(f);
-               break;
-       case TE_WIZSPIKE:
-               CL_RunParticleEffect(f, v, 20, 30);
-               break;
-       case TE_KNIGHTSPIKE:
-               CL_RunParticleEffect(f, v, 226, 20);
-               break;
-       case TE_LAVASPLASH:
-               CL_LavaSplash(f);
-               break;
-       case TE_TELEPORT:
-               CL_TeleportSplash(f);
-               break;
-       case TE_EXPLOSION2:
-       case TE_EXPLOSION3:
-       case TE_EXPLOSIONRGB:
-               CL_ParticleExplosion2(f, v[0], v[1]);
-               break;
-       case TE_BLOOD:
-               CL_BloodPuff(f, v, n);
-               break;
-       case TE_SPARK:
-               CL_SparkShower(f, v, n, 1);
-               break;
-       case TE_FLAMEJET:
-               CL_Flames(f, v, n);
-               break;
-       case TE_PLASMABURN:
-               CL_PlasmaBurn(f);
-               break;
-       case TE_TEI_G3:
-               CL_BeamParticle(f, v, 8, 1, 1, 1, 1, 1);
-               break;
-       case TE_TEI_SMOKE:
-               CL_Tei_Smoke(f, v, n);
-               break;
-       case TE_TEI_PLASMAHIT:
-               CL_Tei_PlasmaHit(f, v, n);
-               break;
-       default:break;
-       }
-}
-
-//#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);
+       v = PRVM_G_VECTOR(OFS_PARM2);
+       n = (int)PRVM_G_FLOAT(OFS_PARM3);
+       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)
 {
-       int i;
-
        VM_SAFEPARMCOUNT(1, VM_CL_getkeybind);
-       i = PRVM_G_FLOAT(OFS_PARM0);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(Key_GetBind(i));
+       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);
-       cl_ignoremousemove = true;
+       cl_ignoremousemoves = 2;
 }
 
 //#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);
-       frame = PRVM_G_FLOAT(OFS_PARM0);
+       frame = (int)PRVM_G_FLOAT(OFS_PARM0);
        for (i = 0;i < cl.movement_numqueue;i++)
                if (cl.movement_queue[i].sequence == frame)
                {
@@ -1327,40 +1099,39 @@ void VM_CL_getinputstate (void)
                        prog->globals.client->input_timelength = cl.movement_queue[i].frametime;
                        if(cl.movement_queue[i].crouch)
                        {
-                               VectorCopy(cl_playercrouchmins, prog->globals.client->pmove_mins);
-                               VectorCopy(cl_playercrouchmaxs, prog->globals.client->pmove_maxs);
+                               VectorCopy(cl.playercrouchmins, prog->globals.client->pmove_mins);
+                               VectorCopy(cl.playercrouchmaxs, prog->globals.client->pmove_maxs);
                        }
                        else
                        {
-                               VectorCopy(cl_playerstandmins, prog->globals.client->pmove_mins);
-                               VectorCopy(cl_playerstandmaxs, prog->globals.client->pmove_maxs);
+                               VectorCopy(cl.playerstandmins, prog->globals.client->pmove_mins);
+                               VectorCopy(cl.playerstandmaxs, prog->globals.client->pmove_maxs);
                        }
                }
 }
 
 //#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];
        const char      *c;
-       char            *temp;
 
        VM_SAFEPARMCOUNT(2, VM_CL_getplayerkey);
 
-       i = PRVM_G_FLOAT(OFS_PARM0);
+       i = (int)PRVM_G_FLOAT(OFS_PARM0);
        c = PRVM_G_STRING(OFS_PARM1);
        PRVM_G_INT(OFS_RETURN) = OFS_NULL;
        Sbar_SortFrags();
@@ -1372,16 +1143,19 @@ void VM_CL_getplayerkey (void)
        t[0] = 0;
 
        if(!strcasecmp(c, "name"))
-               strcpy(t, cl.scores[i].name);
+               strlcpy(t, cl.scores[i].name, sizeof(t));
        else
                if(!strcasecmp(c, "frags"))
                        sprintf(t, "%i", cl.scores[i].frags);
-//     else
-//             if(!strcasecmp(c, "ping"))
-//                     sprintf(t, "%i", cl.scores[i].ping);
-//     else
-//             if(!strcasecmp(c, "entertime"))
-//                     sprintf(t, "%f", cl.scores[i].entertime);
+       else
+               if(!strcasecmp(c, "ping"))
+                       sprintf(t, "%i", cl.scores[i].qw_ping);
+       else
+               if(!strcasecmp(c, "pl"))
+                       sprintf(t, "%i", cl.scores[i].qw_packetloss);
+       else
+               if(!strcasecmp(c, "entertime"))
+                       sprintf(t, "%f", cl.scores[i].qw_entertime);
        else
                if(!strcasecmp(c, "colors"))
                        sprintf(t, "%i", cl.scores[i].colors);
@@ -1396,34 +1170,36 @@ void VM_CL_getplayerkey (void)
                        sprintf(t, "%i", i+1);
        if(!t[0])
                return;
-       temp = VM_GetTempString();
-       strcpy(temp, t);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(temp);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
 }
 
 //#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));
-       csqc_usecsqclistener = true;    //use csqc listener at this frame
+       Matrix4x4_FromVectors(&cl.csqc_listenermatrix, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_VECTOR(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0));
+       cl.csqc_usecsqclistener = true; //use csqc listener at this frame
 }
 
 //#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);
        if(!Cmd_Exists(PRVM_G_STRING(OFS_PARM0)))
        {
-               t = Z_Malloc(strlen(PRVM_G_STRING(OFS_PARM0))+1);
-               strcpy(t, PRVM_G_STRING(OFS_PARM0));
+               size_t alloclen;
+
+               alloclen = strlen(PRVM_G_STRING(OFS_PARM0)) + 1;
+               t = (char *)Z_Malloc(alloclen);
+               memcpy(t, PRVM_G_STRING(OFS_PARM0), alloclen);
                Cmd_AddCommand(t, NULL, "console command created by QuakeC");
        }
        else
@@ -1431,92 +1207,183 @@ 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) = csqc_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)
 {
-       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadCoord(cl.protocol);
+       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)
 {
-       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadAngle(cl.protocol);
+       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)
 {
-       char *t, *s;
-       t = VM_GetTempString();
-       s = MSG_ReadString();
-       PRVM_G_INT(OFS_RETURN) = 0;
-       if(s)
-       {
-               strcpy(t, s);
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
-       }
+       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
+               memset(staticent, 0, sizeof(*staticent));
+               staticent->render.model = CL_GetModelByIndex((int)ent->fields.client->modelindex);
+               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.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);
+
+               // 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 | EF_ADDITIVE | EF_NODEPTHTEST)) && (staticent->render.alpha >= 1))
+                       staticent->render.flags |= RENDER_SHADOW;
+
+               CL_UpdateRenderEntity(&staticent->render);
+       }
+       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), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
+       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;
@@ -1525,20 +1392,29 @@ void VM_CL_te_blood (void)
                return;
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       CL_BloodPuff(pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
+       CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
 }
 
 // #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;
        VM_SAFEPARMCOUNT(4, VM_CL_te_bloodshower);
        if (PRVM_G_FLOAT(OFS_PARM3) < 1)
                return;
-       CL_BloodShower(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3));
+       speed = PRVM_G_FLOAT(OFS_PARM2);
+       vel1[0] = -speed;
+       vel1[1] = -speed;
+       vel1[2] = -speed;
+       vel2[0] = speed;
+       vel2[1] = speed;
+       vel2[2] = speed;
+       CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), vel1, vel2, NULL, 0);
 }
 
 // #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;
@@ -1548,86 +1424,78 @@ void VM_CL_te_explosionrgb (void)
        CL_FindNonSolidLocation(pos, pos2, 10);
        CL_ParticleExplosion(pos2);
        Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 350, PRVM_G_VECTOR(OFS_PARM1)[0], PRVM_G_VECTOR(OFS_PARM1)[1], PRVM_G_VECTOR(OFS_PARM1)[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_AllocLightFlash(NULL, &tempmatrix, 350, PRVM_G_VECTOR(OFS_PARM1)[0], PRVM_G_VECTOR(OFS_PARM1)[1], PRVM_G_VECTOR(OFS_PARM1)[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
 }
 
 // #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);
-       if (PRVM_G_FLOAT(OFS_PARM3) < 1)
-               return;
-       CL_ParticleCube(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4), PRVM_G_FLOAT(OFS_PARM5), PRVM_G_FLOAT(OFS_PARM6));
+       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);
-       if (PRVM_G_FLOAT(OFS_PARM3) < 1)
-               return;
-       CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4), 0);
+       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);
-       if (PRVM_G_FLOAT(OFS_PARM3) < 1)
-               return;
-       CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4), 1);
+       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;
        VM_SAFEPARMCOUNT(3, VM_CL_te_spark);
 
-       if (PRVM_G_FLOAT(OFS_PARM2) < 1)
-               return;
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       CL_SparkShower(pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2), 1);
+       CL_ParticleEffect(EFFECT_TE_SPARK, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
 }
 
+extern cvar_t cl_sound_ric_gunshot;
 // #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;
-       matrix4x4_t     tempmatrix;
+       int                     rnd;
        VM_SAFEPARMCOUNT(1, VM_CL_te_gunshotquad);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       CL_SparkShower(pos2, vec3_origin, 15, 1);
-       CL_Smoke(pos2, vec3_origin, 15);
-       CL_BulletMark(pos2);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_ParticleEffect(EFFECT_TE_GUNSHOTQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
+       if(cl_sound_ric_gunshot.integer >= 2)
+       {
+               if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
+               else
+               {
+                       rnd = rand() & 3;
+                       if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
+                       else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
+                       else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
+               }
+       }
 }
 
 // #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;
-       matrix4x4_t     tempmatrix;
        int                     rnd;
        VM_SAFEPARMCOUNT(1, VM_CL_te_spikequad);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       if (cl_particles_bulletimpacts.integer)
-       {
-               CL_SparkShower(pos2, vec3_origin, 15, 1);
-               CL_Smoke(pos2, vec3_origin, 15);
-               CL_BulletMark(pos2);
-       }
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_ParticleEffect(EFFECT_TE_SPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
        else
        {
@@ -1639,24 +1507,16 @@ 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;
-       matrix4x4_t     tempmatrix;
        int                     rnd;
        VM_SAFEPARMCOUNT(1, VM_CL_te_superspikequad);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       if (cl_particles_bulletimpacts.integer)
-       {
-               CL_SparkShower(pos2, vec3_origin, 30, 1);
-               CL_Smoke(pos2, vec3_origin, 30);
-               CL_BulletMark(pos2);
-       }
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_ParticleEffect(EFFECT_TE_SUPERSPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos, 1, 1);
        else
        {
@@ -1668,38 +1528,32 @@ 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;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_explosionquad);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 10);
-       CL_ParticleExplosion(pos2);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 350, 2.5f, 2.0f, 4.0f, 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       if (gamemode != GAME_NEXUIZ)
-               S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
+       CL_ParticleEffect(EFFECT_TE_EXPLOSIONQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
+       S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
 }
 
 // #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;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_smallflash);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 10);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 200, 2, 2, 2, 1000, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_ParticleEffect(EFFECT_TE_SMALLFLASH, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
 }
 
 // #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;
@@ -1709,25 +1563,35 @@ void VM_CL_te_customflash (void)
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
        Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM3)[0], PRVM_G_VECTOR(OFS_PARM3)[1], PRVM_G_VECTOR(OFS_PARM3)[2], PRVM_G_FLOAT(OFS_PARM1) / PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM2), 0, -1, true, 1, 0.25, 1, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_AllocLightFlash(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM3)[0], PRVM_G_VECTOR(OFS_PARM3)[1], PRVM_G_VECTOR(OFS_PARM3)[2], PRVM_G_FLOAT(OFS_PARM1) / PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM2), 0, -1, true, 1, 0.25, 1, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
 }
 
 // #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;
+       int                     rnd;
        VM_SAFEPARMCOUNT(1, VM_CL_te_gunshot);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       CL_SparkShower(pos2, vec3_origin, 15, 1);
-       CL_Smoke(pos2, vec3_origin, 15);
-       CL_BulletMark(pos2);
+       CL_ParticleEffect(EFFECT_TE_GUNSHOT, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
+       if(cl_sound_ric_gunshot.integer == 1 || cl_sound_ric_gunshot.integer == 3)
+       {
+               if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
+               else
+               {
+                       rnd = rand() & 3;
+                       if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
+                       else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
+                       else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
+               }
+       }
 }
 
 // #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;
@@ -1736,12 +1600,7 @@ void VM_CL_te_spike (void)
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       if (cl_particles_bulletimpacts.integer)
-       {
-               CL_SparkShower(pos2, vec3_origin, 15, 1);
-               CL_Smoke(pos2, vec3_origin, 15);
-               CL_BulletMark(pos2);
-       }
+       CL_ParticleEffect(EFFECT_TE_SPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
        else
        {
@@ -1753,7 +1612,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;
@@ -1762,12 +1621,7 @@ void VM_CL_te_superspike (void)
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       if (cl_particles_bulletimpacts.integer)
-       {
-               CL_SparkShower(pos2, vec3_origin, 30, 1);
-               CL_Smoke(pos2, vec3_origin, 30);
-               CL_BulletMark(pos2);
-       }
+       CL_ParticleEffect(EFFECT_TE_SUPERSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
        else
        {
@@ -1779,93 +1633,73 @@ 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;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_explosion);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 10);
-       CL_ParticleExplosion(pos2);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 350, 4.0f, 2.0f, 0.50f, 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       if (gamemode != GAME_NEXUIZ)
-               S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
+       CL_ParticleEffect(EFFECT_TE_EXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
+       S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
 }
 
 // #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;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_tarexplosion);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 10);
-       CL_BlobExplosion(pos2);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 600, 1.6f, 0.8f, 2.0f, 1200, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       if (gamemode != GAME_NEXUIZ)
-               S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
+       CL_ParticleEffect(EFFECT_TE_TAREXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
+       S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
 }
 
 // #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;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_wizspike);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 100, 0.12f, 0.50f, 0.12f, 500, 0.2, 0, -1, false, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       CL_RunParticleEffect(pos2, vec3_origin, 20, 30);
+       CL_ParticleEffect(EFFECT_TE_WIZSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        S_StartSound(-1, 0, cl.sfx_wizhit, pos2, 1, 1);
 }
 
 // #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;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_knightspike);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 100, 0.50f, 0.30f, 0.10f, 500, 0.2, 0, -1, false, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       CL_RunParticleEffect(pos2, vec3_origin, 226, 20);
+       CL_ParticleEffect(EFFECT_TE_KNIGHTSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        S_StartSound(-1, 0, cl.sfx_knighthit, pos2, 1, 1);
 }
 
 // #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_LavaSplash(PRVM_G_VECTOR(OFS_PARM0));
+       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)
 {
-       float           *pos;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_teleport);
-
-       pos = PRVM_G_VECTOR(OFS_PARM0);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 200, 1.0f, 1.0f, 1.0f, 600, 99.0f, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       CL_TeleportSplash(pos);
+       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;
@@ -1875,146 +1709,94 @@ void VM_CL_te_explosion2 (void)
        VM_SAFEPARMCOUNT(3, VM_CL_te_explosion2);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
-       colorStart = PRVM_G_FLOAT(OFS_PARM1);
-       colorLength = PRVM_G_FLOAT(OFS_PARM2);
+       colorStart = (int)PRVM_G_FLOAT(OFS_PARM1);
+       colorLength = (int)PRVM_G_FLOAT(OFS_PARM2);
        CL_FindNonSolidLocation(pos, pos2, 10);
        CL_ParticleExplosion2(pos2, colorStart, colorLength);
-       tempcolor = (unsigned char *)&palette_complete[(rand()%colorLength) + colorStart];
+       tempcolor = palette_rgb[(rand()%colorLength) + colorStart];
        color[0] = tempcolor[0] * (2.0f / 255.0f);
        color[1] = tempcolor[1] * (2.0f / 255.0f);
        color[2] = tempcolor[2] * (2.0f / 255.0f);
        Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       if (gamemode != GAME_NEXUIZ)
-               S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
+       CL_AllocLightFlash(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
 }
 
 
-static void VM_CL_NewBeam (int ent, float *start, float *end, model_t *m, qboolean lightning)
+// #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
+static void VM_CL_te_lightning1 (void)
 {
-       beam_t  *b;
-       int             i;
-       extern entity_t *cl_csqcentities;
-       extern int cl_max_csqcentities;
+       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);
+}
 
-       if (ent >= cl_max_csqcentities)
-               CL_ExpandCSQCEntities(ent);
-
-       // override any beam with the same entity
-       for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
-       {
-               if (b->entity == ent && ent)
-               {
-                       //b->entity = ent;
-                       b->lightning = lightning;
-                       b->relativestartvalid = (ent && cl_csqcentities[ent].state_current.active) ? 2 : 0;
-                       b->model = m;
-                       b->endtime = cl.time + 0.2;
-                       VectorCopy (start, b->start);
-                       VectorCopy (end, b->end);
-                       return;
-               }
-       }
-
-       // find a free beam
-       for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
-       {
-               if (!b->model || b->endtime < cl.time)
-               {
-                       b->entity = ent;
-                       b->lightning = lightning;
-                       b->relativestartvalid = (ent && cl_csqcentities[ent].state_current.active) ? 2 : 0;
-                       b->model = m;
-                       b->endtime = cl.time + 0.2;
-                       VectorCopy (start, b->start);
-                       VectorCopy (end, b->end);
-                       return;
-               }
-       }
-       Con_Print("beam list overflow!\n");
-}
-
-// #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
-void VM_CL_te_lightning1 (void)
-{
-       VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1);
-       VM_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)
-{
-       VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2);
-       VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
-}
+// #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
+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);
-       VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
+       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);
-       VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
+       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;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_plasmaburn);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 200, 1, 1, 1, 1000, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       CL_PlasmaBurn(pos2);
+       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
 
-void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out);
-static msurface_t *cl_getsurface(prvm_edict_t *ed, int surfacenum)
+extern void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out);
+
+static msurface_t *cl_getsurface(model_t *model, int surfacenum)
 {
-       int modelindex;
-       model_t *model = NULL;
-       if (!ed || ed->priv.server->free)
-               return NULL;
-       modelindex = ed->fields.client->modelindex;
-       if(!modelindex)
-               return NULL;
-       if(modelindex<0)
-       {
-               modelindex = -(modelindex+1);
-               if(modelindex < MAX_MODELS)
-                       model = cl.csqc_model_precache[modelindex];
-       }
-       else
-       {
-               if(modelindex < MAX_MODELS)
-                       model = cl.model_precache[modelindex];
-       }
-       if(!model)
-               return NULL;
        if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
                return NULL;
        return model->data_surfaces + surfacenum + model->firstmodelsurface;
 }
 
 // #434 float(entity e, float s) getsurfacenumpoints
-void VM_CL_getsurfacenumpoints(void)
+static void VM_CL_getsurfacenumpoints(void)
 {
+       model_t *model;
        msurface_t *surface;
+       VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenumpoints);
        // return 0 if no such surface
-       if (!(surface = cl_getsurface(PRVM_G_EDICT(OFS_PARM0), 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;
@@ -2025,86 +1807,148 @@ 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 (!ed || ed->priv.server->free)
+       if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
                return;
-       if (!(surface = cl_getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
+       // note: this (incorrectly) assumes it is a simple polygon
+       pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
+       if (pointnum < 0 || pointnum >= surface->num_vertices)
+               return;
+       // FIXME: implement rotation/scaling
+       VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
+}
+//PF_getsurfacepointattribute,     // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
+// float SPA_POSITION = 0;
+// float SPA_S_AXIS = 1;
+// float SPA_T_AXIS = 2;
+// float SPA_R_AXIS = 3; // same as SPA_NORMAL
+// float SPA_TEXCOORDS0 = 4;
+// float SPA_LIGHTMAP0_TEXCOORDS = 5;
+// float SPA_LIGHTMAP0_COLOR = 6;
+// TODO: add some wrapper code and merge VM_CL/SV_getsurface* [12/16/2007 Black]
+static void VM_CL_getsurfacepointattribute(void)
+{
+       prvm_edict_t *ed;
+       model_t *model;
+       msurface_t *surface;
+       int pointnum;
+       int attributetype;
+
+       VM_SAFEPARMCOUNT(4, VM_CL_getsurfacenumpoints);
+       VectorClear(PRVM_G_VECTOR(OFS_RETURN));
+       ed = PRVM_G_EDICT(OFS_PARM0);
+       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 = PRVM_G_FLOAT(OFS_PARM2);
+       pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
        if (pointnum < 0 || pointnum >= surface->num_vertices)
                return;
+
        // FIXME: implement rotation/scaling
-       VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
-}
+       attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
 
+       switch( attributetype ) {
+               // float SPA_POSITION = 0;
+               case 0:
+                       VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
+                       break;
+               // float SPA_S_AXIS = 1;
+               case 1:
+                       VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
+                       break;
+               // float SPA_T_AXIS = 2;
+               case 2:
+                       VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
+                       break;
+               // float SPA_R_AXIS = 3; // same as SPA_NORMAL
+               case 3:
+                       VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
+                       break;
+               // float SPA_TEXCOORDS0 = 4;
+               case 4: {
+                       float *ret = PRVM_G_VECTOR(OFS_RETURN);
+                       float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
+                       ret[0] = texcoord[0];
+                       ret[1] = texcoord[1];
+                       ret[2] = 0.0f;
+                       break;
+               }
+               // float SPA_LIGHTMAP0_TEXCOORDS = 5;
+               case 5: {
+                       float *ret = PRVM_G_VECTOR(OFS_RETURN);
+                       float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
+                       ret[0] = texcoord[0];
+                       ret[1] = texcoord[1];
+                       ret[2] = 0.0f;
+                       break;
+               }
+               // float SPA_LIGHTMAP0_COLOR = 6;
+               case 6:
+                       // ignore alpha for now..
+                       VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
+                       break;
+               default:
+                       VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
+                       break;
+       }
+}
 // #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 (!(surface = cl_getsurface(PRVM_G_EDICT(OFS_PARM0), 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
        // note: this only returns the first triangle, so it doesn't work very
        // well for curved surfaces or arbitrary meshes
-       TriangleNormal((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + 3, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + 6, normal);
+       TriangleNormal((model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex), (model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + 3, (model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + 6, normal);
        VectorNormalize(normal);
        VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
 }
 
 // #437 string(entity e, float s) getsurfacetexture
-void VM_CL_getsurfacetexture(void)
+static void VM_CL_getsurfacetexture(void)
 {
+       model_t *model;
        msurface_t *surface;
-       PRVM_G_INT(OFS_RETURN) = 0;
-       if (!(surface = cl_getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
+       VM_SAFEPARMCOUNT(2, VM_CL_getsurfacetexture);
+       PRVM_G_INT(OFS_RETURN) = OFS_NULL;
+       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_SetEngineString(surface->texture->name);
+       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, modelindex;
+       int surfacenum, best;
        vec3_t clipped, p;
        vec_t dist, bestdist;
        prvm_edict_t *ed;
        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);
-       point = PRVM_G_VECTOR(OFS_PARM1);
-
-       if (!ed || ed->priv.server->free)
-               return;
-       modelindex = ed->fields.client->modelindex;
-       if(!modelindex)
-               return;
-       if(modelindex<0)
-       {
-               modelindex = -(modelindex+1);
-               if(modelindex < MAX_MODELS)
-                       model = cl.csqc_model_precache[modelindex];
-       }
-       else
-               if(modelindex < MAX_MODELS)
-                       model = cl.model_precache[modelindex];
-       if(!model)
-               return;
-       if (!model->num_surfaces)
+       if(!(model = CL_GetModelFromEdict(ed)) || !model->num_surfaces)
                return;
 
        // FIXME: implement rotation/scaling
+       point = PRVM_G_VECTOR(OFS_PARM1);
        VectorSubtract(point, ed->fields.client->origin, p);
        best = -1;
        bestdist = 1000000000;
@@ -2119,7 +1963,7 @@ void VM_CL_getsurfacenearpoint(void)
                if (dist < bestdist)
                {
                        // it is, check the nearest point on the actual geometry
-                       clippointtosurface(surface, p, clipped);
+                       clippointtosurface(model, surface, p, clipped);
                        VectorSubtract(clipped, p, clipped);
                        dist += VectorLength2(clipped);
                        if (dist < bestdist)
@@ -2134,20 +1978,20 @@ 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 (!ed || ed->priv.server->free)
-               return;
-       if (!(surface = cl_getsurface(ed, 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);
-       clippointtosurface(surface, p, out);
+       clippointtosurface(model, surface, p, out);
        // FIXME: implement rotation/scaling
        VectorAdd(out, ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
 }
@@ -2155,49 +1999,46 @@ void VM_CL_getsurfaceclippedpoint(void)
 // #443 void(entity e, entity tagentity, string tagname) setattachment
 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)
-               PF_WARNING("setattachment: can not modify world entity\n");
+       {
+               VM_Warning("setattachment: can not modify world entity\n");
+               return;
+       }
        if (e->priv.server->free)
-               PF_WARNING("setattachment: can not modify free entity\n");
+       {
+               VM_Warning("setattachment: can not modify free entity\n");
+               return;
+       }
 
        if (tagentity == NULL)
                tagentity = prog->edicts;
 
-       v = PRVM_GETEDICTFIELDVALUE(e, csqc_fieldoff_tag_entity);
+       v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
        if (v)
                v->edict = PRVM_EDICT_TO_PROG(tagentity);
 
-       v = PRVM_GETEDICTFIELDVALUE(e, csqc_fieldoff_tag_index);
+       v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
        if (v)
                v->_float = 0;
        if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
        {
                modelindex = (int)tagentity->fields.client->modelindex;
-               model = NULL;
-
-               if(modelindex)
-               {
-                       if(modelindex<0)
-                       {
-                               modelindex = -(modelindex+1);
-                               if(modelindex < MAX_MODELS)
-                                       model = cl.csqc_model_precache[modelindex];
-                       }
-                       else
-                               if(modelindex < MAX_MODELS)
-                                       model = cl.model_precache[modelindex];
-               }
-
+               model = CL_GetModelByIndex(modelindex);
                if (model)
                {
-                       v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.client->skin, tagname);
+                       v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.client->skin, tagname);
                        if (v->_float == 0)
                                Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", PRVM_NUM_FOR_EDICT(e), PRVM_NUM_FOR_EDICT(tagentity), tagname, tagname, PRVM_NUM_FOR_EDICT(tagentity), model->name);
                }
@@ -2211,27 +2052,11 @@ void VM_CL_setattachment (void)
 
 int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
 {
-       int i;
-       model_t *m;
-
-       i = e->fields.client->modelindex;
-
-       if(!i)
-               return -1;
-       if(i<0)
-       {
-               i = -(i+1);
-               if(i >= MAX_MODELS)
-                       return -1;
-               m = cl.csqc_model_precache[i];
-       }
+       model_t *model = CL_GetModelFromEdict(e);
+       if (model)
+               return Mod_Alias_GetTagIndexForName(model, (int)e->fields.client->skin, tagname);
        else
-               if(i >= MAX_MODELS)
-                       return -1;
-               else
-                       m = cl.model_precache[i];
-
-       return Mod_Alias_GetTagIndexForName(m, e->fields.client->skin, tagname);
+               return -1;
 };
 
 // Warnings/errors code:
@@ -2247,34 +2072,23 @@ extern cvar_t cl_bobup;
 int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
 {
        prvm_eval_t *val;
-       int modelindex, reqframe, attachloop, i;
+       int reqframe, attachloop;
        matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
        prvm_edict_t *attachent;
        model_t *model;
+       float scale;
 
-       Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
+       *out = identitymatrix; // warnings and errors return identical matrix
 
        if (ent == prog->edicts)
                return 1;
        if (ent->priv.server->free)
                return 2;
 
-       modelindex = (int)ent->fields.client->modelindex;
+       model = CL_GetModelFromEdict(ent);
 
-       if(!modelindex)
+       if(!model)
                return 3;
-       if(modelindex<0)
-       {
-               modelindex = -(modelindex+1);
-               if(modelindex >= MAX_MODELS)
-                       return 3;
-               model = cl.csqc_model_precache[modelindex];
-       }
-       else
-               if(modelindex >= MAX_MODELS)
-                       return 3;
-               else
-                       model = cl.model_precache[modelindex];
 
        if (ent->fields.client->frame >= 0 && ent->fields.client->frame < model->numframes && model->animscenes)
                reqframe = model->animscenes[(int)ent->fields.client->frame].firstframe;
@@ -2289,49 +2103,34 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                        return ret;
        }
        else
-               Matrix4x4_CreateIdentity(&tagmatrix);
+               tagmatrix = identitymatrix;
 
-       if ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_entity)) && val->edict)
+       if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
        { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
                attachloop = 0;
                do
                {
                        attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
-                       val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_index);
+                       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index);
 
-                       model = NULL;
-                       i = attachent->fields.client->modelindex;
-                       if(i<0)
-                       {
-                               i = -(i+1);
-                               if(i < MAX_MODELS)
-                                       model = cl.csqc_model_precache[i];
-                       }
-                       else
-                               if(i < MAX_MODELS)
-                                       model = cl.model_precache[i];
+                       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, val->_float - 1, &attachmatrix);
+                               Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.client->frame].firstframe, (int)val->_float - 1, &attachmatrix);
                        else
-                               Matrix4x4_CreateIdentity(&attachmatrix);
+                               attachmatrix = identitymatrix;
 
                        // apply transformation by child entity matrix
-                       val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
-                       if (val->_float == 0)
-                               val->_float = 1;
-                       Matrix4x4_CreateFromQuakeEntity(&entitymatrix, 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], val->_float);
+                       scale = 1;
+                       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
+                       if (val && val->_float != 0)
+                               scale = val->_float;
+                       Matrix4x4_CreateFromQuakeEntity(&entitymatrix, 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], scale);
                        Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
-                       out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
-                       out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
-                       out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
                        Matrix4x4_Copy(&tagmatrix, out);
 
                        // finally transformate by matrix of tag on parent entity
                        Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
-                       out->m[0][3] = attachmatrix.m[0][3] + attachmatrix.m[0][0]*tagmatrix.m[0][3] + attachmatrix.m[0][1]*tagmatrix.m[1][3] + attachmatrix.m[0][2]*tagmatrix.m[2][3];
-                       out->m[1][3] = attachmatrix.m[1][3] + attachmatrix.m[1][0]*tagmatrix.m[0][3] + attachmatrix.m[1][1]*tagmatrix.m[1][3] + attachmatrix.m[1][2]*tagmatrix.m[2][3];
-                       out->m[2][3] = attachmatrix.m[2][3] + attachmatrix.m[2][0]*tagmatrix.m[0][3] + attachmatrix.m[2][1]*tagmatrix.m[1][3] + attachmatrix.m[2][2]*tagmatrix.m[2][3];
                        Matrix4x4_Copy(&tagmatrix, out);
 
                        ent = attachent;
@@ -2339,33 +2138,29 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                        if (attachloop > 255) // prevent runaway looping
                                return 5;
                }
-               while ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_entity)) && val->edict);
+               while ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict);
        }
 
        // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
-       val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
-       if (val->_float == 0)
-               val->_float = 1;
+       scale = 1;
+       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
+       if (val && val->_float != 0)
+               scale = val->_float;
        // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
-       Matrix4x4_CreateFromQuakeEntity(&entitymatrix, 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], val->_float);
+       Matrix4x4_CreateFromQuakeEntity(&entitymatrix, 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], scale);
        Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
-       out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
-       out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
-       out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
 
-       if ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_renderflags)) && (RF_VIEWMODEL & (int)val->_float))
+       if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && (RF_VIEWMODEL & (int)val->_float))
        {// RENDER_VIEWMODEL magic
                Matrix4x4_Copy(&tagmatrix, out);
 
-               val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
-               if (val->_float == 0)
-                       val->_float = 1;
+               scale = 1;
+               val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
+               if (val && val->_float != 0)
+                       scale = val->_float;
 
-               Matrix4x4_CreateFromQuakeEntity(&entitymatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], val->_float);
+               Matrix4x4_CreateFromQuakeEntity(&entitymatrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], scale);
                Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
-               out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
-               out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
-               out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
 
                /*
                // Cl_bob, ported from rendering code
@@ -2376,7 +2171,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                        // should be done in QC on the server, but oh well, quake is quake)
                        // LordHavoc: figured out bobup: the time at which the sin is at 180
                        // degrees (which allows lengthening or squishing the peak or valley)
-                       cycle = sv.time/cl_bobcycle.value;
+                       cycle = cl.time/cl_bobcycle.value;
                        cycle -= (int)cycle;
                        if (cycle < cl_bobup.value)
                                cycle = sin(M_PI * cycle / cl_bobup.value);
@@ -2386,7 +2181,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                        // (don't count Z, or jumping messes it up)
                        bob = sqrt(ent->fields.client->velocity[0]*ent->fields.client->velocity[0] + ent->fields.client->velocity[1]*ent->fields.client->velocity[1])*cl_bob.value;
                        bob = bob*0.3 + bob*0.7*cycle;
-                       out->m[2][3] += bound(-7, bob, 4);
+                       Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
                }
                */
        }
@@ -2396,20 +2191,28 @@ 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)
 {
-       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)
-               PF_WARNING("gettagindex: can't affect world entity\n");
+       {
+               VM_Warning("gettagindex: can't affect world entity\n");
+               return;
+       }
        if (ent->priv.server->free)
-               PF_WARNING("gettagindex: can't affect free entity\n");
+       {
+               VM_Warning("gettagindex: can't affect free entity\n");
+               return;
+       }
 
        modelindex = (int)ent->fields.client->modelindex;
-       if(modelindex < 0)
-               modelindex = -(modelindex+1);
        tag_index = 0;
-       if (modelindex <= 0 || modelindex >= MAX_MODELS)
+       if (modelindex >= MAX_MODELS || (modelindex <= -MAX_MODELS /* client models */))
                Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
        else
        {
@@ -2423,21 +2226,25 @@ void VM_CL_gettagindex (void)
 // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
 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));
 
        switch(returncode)
        {
                case 1:
-                       PF_WARNING("gettagindex: can't affect world entity\n");
+                       VM_Warning("gettagindex: can't affect world entity\n");
                        break;
                case 2:
-                       PF_WARNING("gettagindex: can't affect free entity\n");
+                       VM_Warning("gettagindex: can't affect free entity\n");
                        break;
                case 3:
                        Con_DPrintf("CL_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
@@ -2451,466 +2258,1002 @@ void VM_CL_gettaginfo (void)
        }
 }
 
-//=================================================
-//[515]: here goes test/unfinished/etc.
+//============================================================================
 
-//[515]: check if it is what it should be
-void VM_WasFreed (void)
-{
-       prvm_edict_t    *e;
-       VM_SAFEPARMCOUNT(1, VM_WasFreed);
+//====================
+//QC POLYGON functions
+//====================
+
+#define VMPOLYGONS_MAXPOINTS 64
+
+typedef struct vmpolygons_triangle_s
+{
+       rtexture_t              *texture;
+       int                             drawflag;
+       int                             element3i[3];
+}vmpolygons_triangle_t;
+
+typedef struct vmpolygons_s
+{
+       mempool_t               *pool;
+       qboolean                initialized;
+
+       int                             max_vertices;
+       int                             num_vertices;
+       float                   *data_vertex3f;
+       float                   *data_color4f;
+       float                   *data_texcoord2f;
+
+       int                             max_triangles;
+       int                             num_triangles;
+       vmpolygons_triangle_t *data_triangles;
+       int                             *data_sortedelement3i;
+
+       qboolean                begin_active;
+       rtexture_t              *begin_texture;
+       int                             begin_drawflag;
+       int                             begin_vertices;
+       float                   begin_vertex[VMPOLYGONS_MAXPOINTS][3];
+       float                   begin_color[VMPOLYGONS_MAXPOINTS][4];
+       float                   begin_texcoord[VMPOLYGONS_MAXPOINTS][2];
+} vmpolygons_t;
+
+// FIXME: make VM_CL_R_Polygon functions use Debug_Polygon functions?
+vmpolygons_t vmpolygons[PRVM_MAXPROGS];
+
+static void VM_ResizePolygons(vmpolygons_t *polys)
+{
+       float *oldvertex3f = polys->data_vertex3f;
+       float *oldcolor4f = polys->data_color4f;
+       float *oldtexcoord2f = polys->data_texcoord2f;
+       vmpolygons_triangle_t *oldtriangles = polys->data_triangles;
+       int *oldsortedelement3i = polys->data_sortedelement3i;
+       polys->max_vertices = polys->max_triangles*3;
+       polys->data_vertex3f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[3]));
+       polys->data_color4f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[4]));
+       polys->data_texcoord2f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[2]));
+       polys->data_triangles = (vmpolygons_triangle_t *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(vmpolygons_triangle_t));
+       polys->data_sortedelement3i = (int *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(int[3]));
+       if (polys->num_vertices)
+       {
+               memcpy(polys->data_vertex3f, oldvertex3f, polys->num_vertices*sizeof(float[3]));
+               memcpy(polys->data_color4f, oldcolor4f, polys->num_vertices*sizeof(float[4]));
+               memcpy(polys->data_texcoord2f, oldtexcoord2f, polys->num_vertices*sizeof(float[2]));
+       }
+       if (polys->num_triangles)
+       {
+               memcpy(polys->data_triangles, oldtriangles, polys->num_triangles*sizeof(vmpolygons_triangle_t));
+               memcpy(polys->data_sortedelement3i, oldsortedelement3i, polys->num_triangles*sizeof(int[3]));
+       }
+       if (oldvertex3f)
+               Mem_Free(oldvertex3f);
+       if (oldcolor4f)
+               Mem_Free(oldcolor4f);
+       if (oldtexcoord2f)
+               Mem_Free(oldtexcoord2f);
+       if (oldtriangles)
+               Mem_Free(oldtriangles);
+       if (oldsortedelement3i)
+               Mem_Free(oldsortedelement3i);
+}
+
+static void VM_InitPolygons (vmpolygons_t* polys)
+{
+       memset(polys, 0, sizeof(*polys));
+       polys->pool = Mem_AllocPool("VMPOLY", 0, NULL);
+       polys->max_triangles = 1024;
+       VM_ResizePolygons(polys);
+       polys->initialized = true;
+}
+
+static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
+{
+       int surfacelistindex;
+       vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+       R_Mesh_Matrix(&identitymatrix);
+       GL_CullFace(GL_NONE);
+       R_Mesh_VertexPointer(polys->data_vertex3f, 0, 0);
+       R_Mesh_ColorPointer(polys->data_color4f, 0, 0);
+       R_Mesh_TexCoordPointer(0, 2, polys->data_texcoord2f, 0, 0);
+       R_SetupGenericShader(true);
+       for (surfacelistindex = 0;surfacelistindex < numsurfaces;)
+       {
+               int numtriangles = 0;
+               rtexture_t *tex = polys->data_triangles[surfacelist[surfacelistindex]].texture;
+               int drawflag = polys->data_triangles[surfacelist[surfacelistindex]].drawflag;
+               if(drawflag == DRAWFLAG_ADDITIVE)
+                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+               else if(drawflag == DRAWFLAG_MODULATE)
+                       GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
+               else if(drawflag == 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(tex));
+               numtriangles = 0;
+               for (;surfacelistindex < numsurfaces;surfacelistindex++)
+               {
+                       if (polys->data_triangles[surfacelist[surfacelistindex]].texture != tex || polys->data_triangles[surfacelist[surfacelistindex]].drawflag != drawflag)
+                               break;
+                       VectorCopy(polys->data_triangles[surfacelist[surfacelistindex]].element3i, polys->data_sortedelement3i + 3*numtriangles);
+                       numtriangles++;
+               }
+               R_Mesh_Draw(0, polys->num_vertices, numtriangles, polys->data_sortedelement3i, 0, 0);
+       }
+}
 
-       e = PRVM_G_EDICT(OFS_PARM0);
-       if (!e->priv.required->free || (e->priv.required->free && (e->priv.required->freetime < 2 || (*prog->time - e->priv.required->freetime) > 0.5 )))
-               PRVM_G_FLOAT(OFS_RETURN) = false;
+void VMPolygons_Store(vmpolygons_t *polys)
+{
+       if (r_refdef.draw2dstage)
+       {
+               // draw the polygon as 2D immediately
+               drawqueuemesh_t mesh;
+               mesh.texture = polys->begin_texture;
+               mesh.num_vertices = polys->begin_vertices;
+               mesh.num_triangles = polys->begin_vertices-2;
+               mesh.data_element3i = polygonelements;
+               mesh.data_vertex3f = polys->begin_vertex[0];
+               mesh.data_color4f = polys->begin_color[0];
+               mesh.data_texcoord2f = polys->begin_texcoord[0];
+               DrawQ_Mesh(&mesh, polys->begin_drawflag);
+       }
        else
-               PRVM_G_FLOAT(OFS_RETURN) = true;
+       {
+               // queue the polygon as 3D for sorted transparent rendering later
+               int i;
+               if (polys->max_triangles < polys->num_triangles + polys->begin_vertices-2)
+               {
+                       polys->max_triangles *= 2;
+                       VM_ResizePolygons(polys);
+               }
+               memcpy(polys->data_vertex3f + polys->num_vertices * 3, polys->begin_vertex[0], polys->num_vertices * sizeof(float[3]));
+               memcpy(polys->data_color4f + polys->num_vertices * 4, polys->begin_color[0], polys->num_vertices * sizeof(float[4]));
+               memcpy(polys->data_texcoord2f + polys->num_vertices * 2, polys->begin_texcoord[0], polys->num_vertices * sizeof(float[2]));
+               for (i = 0;i < polys->begin_vertices-2;i++)
+               {
+                       polys->data_triangles[polys->num_triangles].texture = polys->begin_texture;
+                       polys->data_triangles[polys->num_triangles].drawflag = polys->begin_drawflag;
+                       polys->data_triangles[polys->num_triangles].element3i[0] = polys->num_vertices;
+                       polys->data_triangles[polys->num_triangles].element3i[1] = polys->num_vertices + i+1;
+                       polys->data_triangles[polys->num_triangles].element3i[2] = polys->num_vertices + i+2;
+                       polys->num_triangles++;
+               }
+               polys->num_vertices += polys->begin_vertices;
+       }
+       polys->begin_active = false;
 }
 
-void VM_CL_select_cube (void)
+// TODO: move this into the client code and clean-up everything else, too! [1/6/2008 Black]
+// LordHavoc: agreed, this is a mess
+void VM_CL_AddPolygonsToMeshQueue (void)
 {
-       int             i;
-       int             chain_of;
-       float   *mins2, *maxs2;
-       prvm_edict_t    *ent, *chain;
-       vec3_t  mins1, maxs1;
+       int i;
+       vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+       vec3_t center;
 
-       VM_SAFEPARMCOUNT(2, VM_CL_select_cube);
+       // only add polygons of the currently active prog to the queue - if there is none, we're done
+       if( !prog )
+               return;
 
-       // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
-       if(!prog->flag & PRVM_FE_CHAIN)
-               PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
+       if (!polys->num_triangles)
+               return;
 
-       chain_of = PRVM_ED_FindField("chain")->ofs;
-       chain = prog->edicts;
+       for (i = 0;i < polys->num_triangles;i++)
+       {
+               VectorMAMAM(1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].element3i[0], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].element3i[1], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].element3i[2], center);
+               R_MeshQueue_AddTransparent(center, VM_DrawPolygonCallback, NULL, i, NULL);
+       }
 
-       mins2 = PRVM_G_VECTOR(OFS_PARM0);
-       maxs2 = PRVM_G_VECTOR(OFS_PARM1);
+       polys->num_triangles = 0;
+       polys->num_vertices = 0;
+}
 
-       ent = PRVM_NEXT_EDICT(prog->edicts);
-       for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
+//void(string texturename, float flag) R_BeginPolygon
+void VM_CL_R_PolygonBegin (void)
+{
+       const char              *picname;
+       vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
+       VM_SAFEPARMCOUNT(2, VM_CL_R_PolygonBegin);
+
+       if (!polys->initialized)
+               VM_InitPolygons(polys);
+       if (polys->begin_active)
        {
-               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_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
-               chain = ent;
+               VM_Warning("VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonBegin after first\n");
+               return;
        }
+       picname = PRVM_G_STRING(OFS_PARM0);
+       polys->begin_texture = picname[0] ? Draw_CachePic (picname)->tex : r_texture_white;
+       polys->begin_drawflag = (int)PRVM_G_FLOAT(OFS_PARM1);
+       polys->begin_vertices = 0;
+       polys->begin_active = true;
+}
 
-       VM_RETURN_EDICT(chain);
+//void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
+void VM_CL_R_PolygonVertex (void)
+{
+       vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
+       VM_SAFEPARMCOUNT(4, VM_CL_R_PolygonVertex);
+
+       if (!polys->begin_active)
+       {
+               VM_Warning("VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n");
+               return;
+       }
+
+       if (polys->begin_vertices >= VMPOLYGONS_MAXPOINTS)
+       {
+               VM_Warning("VM_CL_R_PolygonVertex: may have %i vertices max\n", VMPOLYGONS_MAXPOINTS);
+               return;
+       }
+
+       polys->begin_vertex[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM0)[0];
+       polys->begin_vertex[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM0)[1];
+       polys->begin_vertex[polys->begin_vertices][2] = PRVM_G_VECTOR(OFS_PARM0)[2];
+       polys->begin_texcoord[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM1)[0];
+       polys->begin_texcoord[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM1)[1];
+       polys->begin_color[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM2)[0];
+       polys->begin_color[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM2)[1];
+       polys->begin_color[polys->begin_vertices][2] = PRVM_G_VECTOR(OFS_PARM2)[2];
+       polys->begin_color[polys->begin_vertices][3] = PRVM_G_FLOAT(OFS_PARM3);
+       polys->begin_vertices++;
 }
 
-void VM_CL_select_super (void)
+//void() R_EndPolygon
+void VM_CL_R_PolygonEnd (void)
 {
-/*     int             i;
-       int             chain_of;
-       float   *v[8];
-       prvm_edict_t    *ent, *chain;
-       vec3_t  mins1, maxs1;
+       vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
 
-       VM_SAFEPARMCOUNT(8, VM_findchain);
-       for(i=0;i<8;i++)
-               v[i] = PRVM_G_VECTOR(OFS_PARM0+i*3);
+       VM_SAFEPARMCOUNT(0, VM_CL_R_PolygonEnd);
+       if (!polys->begin_active)
+       {
+               VM_Warning("VM_CL_R_PolygonEnd: VM_CL_R_PolygonBegin wasn't called\n");
+               return;
+       }
+       polys->begin_active = false;
+       if (polys->begin_vertices >= 3)
+               VMPolygons_Store(polys);
+       else
+               VM_Warning("VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", polys->begin_vertices);
+}
 
-       // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
-       if(!prog->flag & PRVM_FE_CHAIN)
-               PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
+static vmpolygons_t debugPolys;
 
-       chain_of = PRVM_ED_FindField("chain")->ofs;
-       chain = prog->edicts;
+void Debug_PolygonBegin(const char *picname, int drawflag)
+{
+       if(!debugPolys.initialized)
+               VM_InitPolygons(&debugPolys);
+       if(debugPolys.begin_active)
+       {
+               Con_Printf("Debug_PolygonBegin: called twice without Debug_PolygonEnd after first\n");
+               return;
+       }
+       debugPolys.begin_texture = picname[0] ? Draw_CachePic (picname)->tex : r_texture_white;
+       debugPolys.begin_drawflag = drawflag;
+       debugPolys.begin_vertices = 0;
+       debugPolys.begin_active = true;
+}
 
-       mins2 = PRVM_G_VECTOR(OFS_PARM0);
-       maxs2 = PRVM_G_VECTOR(OFS_PARM1);
+void Debug_PolygonVertex(float x, float y, float z, float s, float t, float r, float g, float b, float a)
+{
+       if(!debugPolys.begin_active)
+       {
+               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))
+       if(debugPolys.begin_vertices > VMPOLYGONS_MAXPOINTS)
        {
-               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_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
-               chain = ent;
+               Con_Printf("Debug_PolygonVertex: may have %i vertices max\n", VMPOLYGONS_MAXPOINTS);
+               return;
        }
 
-       VM_RETURN_EDICT(chain);*/
+       debugPolys.begin_vertex[debugPolys.begin_vertices][0] = x;
+       debugPolys.begin_vertex[debugPolys.begin_vertices][1] = y;
+       debugPolys.begin_vertex[debugPolys.begin_vertices][2] = z;
+       debugPolys.begin_texcoord[debugPolys.begin_vertices][0] = s;
+       debugPolys.begin_texcoord[debugPolys.begin_vertices][1] = t;
+       debugPolys.begin_color[debugPolys.begin_vertices][0] = r;
+       debugPolys.begin_color[debugPolys.begin_vertices][1] = g;
+       debugPolys.begin_color[debugPolys.begin_vertices][2] = b;
+       debugPolys.begin_color[debugPolys.begin_vertices][3] = a;
+       debugPolys.begin_vertices++;
 }
 
-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 (!debugPolys.begin_active)
+       {
+               Con_Printf("Debug_PolygonEnd: Debug_PolygonBegin wasn't called\n");
+               return;
+       }
+       debugPolys.begin_active = false;
+       if (debugPolys.begin_vertices >= 3)
+               VMPolygons_Store(&debugPolys);
+       else
+               Con_Printf("Debug_PolygonEnd: %i vertices isn't a good choice\n", debugPolys.begin_vertices);
+}
 
-       if(c != '^' && c2 != '^')               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;
-       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);
-       if(!in)
-               PRVM_ERROR ("VM_uncolorstring: %s: NULL\n", PRVM_NAME);
-       VM_CheckEmptyString (in);
-       out = VM_GetTempString();
+// 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;
                }
-               out[i] = in[k];
-               ++k;
-               ++i;
+
+               return false;
        }
-}
 
-void VM_CL_selecttraceline (void)
-{
-       float   *v1, *v2;
-       int             ent, ignore, csqcents;
+// push down from a step height above the wished position
+       neworg[2] += sv_stepheight.value;
+       VectorCopy (neworg, end);
+       end[2] -= sv_stepheight.value*2;
 
-       v1 = PRVM_G_VECTOR(OFS_PARM0);
-       v2 = PRVM_G_VECTOR(OFS_PARM1);
-       ignore = PRVM_G_FLOAT(OFS_PARM2);
-       csqcents = PRVM_G_FLOAT(OFS_PARM3);
-       ent = 0;
+       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((csqcents && ignore > cl_num_csqcentities) || (!csqcents && ignore > cl_num_entities))
+       if (trace.startsolid)
        {
-               Con_Printf("VM_CL_selecttraceline: out of entities\n");
-               return;
+               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;
        }
-       else
-               if(csqcents)
-                       prog->globals.client->trace_fraction = CL_SelectTraceLine(v1, v2, prog->globals.client->trace_endpos, prog->globals.client->trace_plane_normal, &prog->globals.client->trace_ent, &cl_csqcentities[ignore].render, csqcents);
-               else
-                       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, csqcents);
-       PRVM_G_FLOAT(OFS_RETURN) = ent;
+       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;
+               }
+               VectorCopy (oldorg, ent->fields.client->origin);
+               return false;
+       }
+
+       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_charindex (void)
+/*
+===============
+VM_CL_walkmove
+
+float(float yaw, float dist[, settrace]) walkmove
+===============
+*/
+static void VM_CL_walkmove (void)
 {
-       const char *s;
-       s = PRVM_G_STRING(OFS_PARM0);
-       if(!s)
+       prvm_edict_t    *ent;
+       float   yaw, dist;
+       vec3_t  move;
+       mfunction_t     *oldf;
+       int     oldself;
+       qboolean        settrace;
+
+       VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_walkmove);
+
+       // 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("walkmove: can not modify world entity\n");
                return;
-       if((unsigned)PRVM_G_FLOAT(OFS_PARM1) > strlen(s))
+       }
+       if (ent->priv.server->free)
+       {
+               VM_Warning("walkmove: can not modify free entity\n");
                return;
-       PRVM_G_FLOAT(OFS_RETURN) = (unsigned char)s[(int)PRVM_G_FLOAT(OFS_PARM1)];
-}
+       }
+       yaw = PRVM_G_FLOAT(OFS_PARM0);
+       dist = PRVM_G_FLOAT(OFS_PARM1);
+       settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
 
-//#223 string(float c, ...) chr2str (FTE_STRINGS)
-void VM_chr2str (void)
-{
-       char    *t;
-       int             i;
-       t = VM_GetTempString();
-       for(i=0;i<prog->argc;i++)
-               t[i] = (unsigned char)PRVM_G_FLOAT(OFS_PARM0+i*3);
-       t[i] = 0;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
+       if ( !( (int)ent->fields.client->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
+               return;
+
+       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);
 }
 
 //============================================================================
-//============================================================================
+
+// To create a almost working builtin file from this replace:
+// "^NULL.*" with ""
+// "^{.*//.*}:Wh\(.*\)" with "\1"
+// "\:" with "//"
+// "^.*//:Wh{\#:d*}:Wh{.*}" with "\2 = \1;"
+// "\n\n+" with "\n\n"
 
 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_CL_changeyaw,                       // #49 void(entity ent, float ideal_yaw, float speed_yaw) 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_CL_changepitch,                     // #63 void(entity ent, float ideal_pitch, float speed_pitch) 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, entity ignoreentity) 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[, float settrace]) 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
+VM_strstrofs,                                  // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
+VM_str2chr,                                            // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
+VM_chr2str,                                            // #223 string(float c, ...) chr2str (FTE_STRINGS)
+VM_strconv,                                            // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
+VM_strpad,                                             // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
+VM_infoadd,                                            // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
+VM_infoget,                                            // #227 string(string info, string key) infoget (FTE_STRINGS)
+VM_strncmp,                                            // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
+VM_strncasecmp,                                        // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
+VM_strncasecmp,                                        // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
+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 /* R_LoadWorldModel in menu VM, should stay unassigned in client*/, // #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
+VM_drawcolorcodedstring,               // #326 float drawcolorcodedstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) (EXT_CSQC)
+NULL,                                                  // #327 // FIXME add stringwidth() here?
+NULL,                                                  // #328 // FIXME add drawsubpic() here?
+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) setsensitivityscale (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)
@@ -2949,46 +3292,92 @@ 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)
-e10, e10, e10                  // #470-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_QC_FS_SEARCH)
+VM_search_end,                                 // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
+VM_search_getsize,                             // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
+VM_search_getfilename,                 // #447 string(float handle, float num) search_getfilename (DP_QC_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 (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)
+VM_tokenizebyseparator,                        // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
+VM_strtolower,                                 // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
+VM_strtoupper,                                 // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
+VM_cvar_defstring,                             // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
+VM_CL_pointsound,                              // #483 void(vector origin, string sample, float volume, float attenuation) pointsound (DP_SV_POINTSOUND)
+VM_strreplace,                                 // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
+VM_strireplace,                                        // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
+VM_CL_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute
+VM_gecko_create,                                       // #487 float gecko_create( string name )
+VM_gecko_destroy,                                      // #488 void gecko_destroy( string name )
+VM_gecko_navigate,                             // #489 void gecko_navigate( string name, string URI )
+VM_gecko_keyevent,                             // #490 float gecko_keyevent( string name, float key, float eventtype )
+VM_gecko_movemouse,                            // #491 void gecko_mousemove( string name, float x, float y )
+VM_gecko_resize,                                       // #492 void gecko_resize( string name, float w, float h )
+VM_gecko_get_texture_extent,   // #493 vector gecko_get_texture_extent( string name )
+VM_crc16,                                              // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
+VM_cvar_type,                                  // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
+NULL,                                                  // #496
+NULL,                                                  // #497
+NULL,                                                  // #498
+NULL,                                                  // #499
 };
 
 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
 
+void VM_Polygons_Reset(void)
+{
+       vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
+       // TODO: replace vm_polygons stuff with a more general debugging polygon system, and make vm_polygons functions use that system
+       if(polys->initialized)
+       {
+               Mem_FreePool(&polys->pool);
+               polys->initialized = false;
+       }
+}
+
 void VM_CL_Cmd_Init(void)
 {
+       VM_Cmd_Init();
+       VM_Polygons_Reset();
 }
 
 void VM_CL_Cmd_Reset(void)
 {
+       VM_Cmd_Reset();
+       VM_Polygons_Reset();
 }
 
+