]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - clvm_cmds.c
Fix setinfo.
[xonotic/darkplaces.git] / clvm_cmds.c
index d9b8c77d23ceed63a817370961183273df5f4da6..51f64b5073ff01a1d77a8f30805aad2fdb859c08 100644 (file)
 extern cvar_t v_flipped;
 extern cvar_t r_equalize_entities_fullbright;
 
-sfx_t *S_FindName(const char *name);
-int Sbar_GetSortedPlayerIndex (int index);
-void Sbar_SortFrags (void);
-void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius);
-void CSQC_RelinkAllEntities (int drawmask);
-void CSQC_RelinkCSQCEntities (void);
+r_refdef_view_t csqc_original_r_refdef_view;
+r_refdef_view_t csqc_main_r_refdef_view;
 
 // #1 void(vector ang) makevectors
-static void VM_CL_makevectors (void)
+static void VM_CL_makevectors (prvm_prog_t *prog)
 {
+       vec3_t angles, forward, right, up;
        VM_SAFEPARMCOUNT(1, VM_CL_makevectors);
-       AngleVectors (PRVM_G_VECTOR(OFS_PARM0), PRVM_clientglobalvector(v_forward), PRVM_clientglobalvector(v_right), PRVM_clientglobalvector(v_up));
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), angles);
+       AngleVectors(angles, forward, right, up);
+       VectorCopy(forward, PRVM_clientglobalvector(v_forward));
+       VectorCopy(right, PRVM_clientglobalvector(v_right));
+       VectorCopy(up, PRVM_clientglobalvector(v_up));
 }
 
 // #2 void(entity e, vector o) setorigin
-void VM_CL_setorigin (void)
+static void VM_CL_setorigin (prvm_prog_t *prog)
 {
        prvm_edict_t    *e;
-       float   *org;
+       prvm_vec_t      *org;
        VM_SAFEPARMCOUNT(2, VM_CL_setorigin);
 
        e = PRVM_G_EDICT(OFS_PARM0);
        if (e == prog->edicts)
        {
-               VM_Warning("setorigin: can not modify world entity\n");
+               VM_Warning(prog, "setorigin: can not modify world entity\n");
                return;
        }
        if (e->priv.required->free)
        {
-               VM_Warning("setorigin: can not modify free entity\n");
+               VM_Warning(prog, "setorigin: can not modify free entity\n");
                return;
        }
        org = PRVM_G_VECTOR(OFS_PARM1);
        VectorCopy (org, PRVM_clientedictvector(e, origin));
+       if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
+               e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
        CL_LinkEdict(e);
 }
 
-static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max)
+static void SetMinMaxSizePRVM (prvm_prog_t *prog, prvm_edict_t *e, prvm_vec_t *min, prvm_vec_t *max)
 {
        int             i;
 
        for (i=0 ; i<3 ; i++)
                if (min[i] > max[i])
-                       PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
+                       prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
 
        // set derived values
        VectorCopy (min, PRVM_clientedictvector(e, mins));
@@ -76,8 +79,16 @@ static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max)
        CL_LinkEdict (e);
 }
 
+static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, const vec_t *min, const vec_t *max)
+{
+       prvm_vec3_t mins, maxs;
+       VectorCopy(min, mins);
+       VectorCopy(max, maxs);
+       SetMinMaxSizePRVM(prog, e, mins, maxs);
+}
+
 // #3 void(entity e, string m) setmodel
-void VM_CL_setmodel (void)
+static void VM_CL_setmodel (prvm_prog_t *prog)
 {
        prvm_edict_t    *e;
        const char              *m;
@@ -97,7 +108,7 @@ void VM_CL_setmodel (void)
                if (!strcmp(cl.csqc_model_precache[i]->name, m))
                {
                        mod = cl.csqc_model_precache[i];
-                       PRVM_clientedictstring(e, model) = PRVM_SetEngineString(mod->name);
+                       PRVM_clientedictstring(e, model) = PRVM_SetEngineString(prog, mod->name);
                        PRVM_clientedictfloat(e, modelindex) = -(i+1);
                        break;
                }
@@ -109,7 +120,7 @@ void VM_CL_setmodel (void)
                        mod = cl.model_precache[i];
                        if (mod && !strcmp(mod->name, m))
                        {
-                               PRVM_clientedictstring(e, model) = PRVM_SetEngineString(mod->name);
+                               PRVM_clientedictstring(e, model) = PRVM_SetEngineString(prog, mod->name);
                                PRVM_clientedictfloat(e, modelindex) = i;
                                break;
                        }
@@ -118,50 +129,52 @@ void VM_CL_setmodel (void)
 
        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);
+               // LordHavoc: erm you broke it by commenting this out - setmodel must do setsize or else the qc can't find out the model size, and ssqc does this by necessity, consistency.
+               SetMinMaxSize (prog, e, mod->normalmins, mod->normalmaxs);
        }
        else
        {
-               SetMinMaxSize (e, vec3_origin, vec3_origin);
-               VM_Warning ("setmodel: model '%s' not precached\n", m);
+               SetMinMaxSize (prog, e, vec3_origin, vec3_origin);
+               VM_Warning(prog, "setmodel: model '%s' not precached\n", m);
        }
 }
 
 // #4 void(entity e, vector min, vector max) setsize
-static void VM_CL_setsize (void)
+static void VM_CL_setsize (prvm_prog_t *prog)
 {
        prvm_edict_t    *e;
-       float                   *min, *max;
+       vec3_t          mins, maxs;
        VM_SAFEPARMCOUNT(3, VM_CL_setsize);
 
        e = PRVM_G_EDICT(OFS_PARM0);
        if (e == prog->edicts)
        {
-               VM_Warning("setsize: can not modify world entity\n");
+               VM_Warning(prog, "setsize: can not modify world entity\n");
                return;
        }
        if (e->priv.server->free)
        {
-               VM_Warning("setsize: can not modify free entity\n");
+               VM_Warning(prog, "setsize: can not modify free entity\n");
                return;
        }
-       min = PRVM_G_VECTOR(OFS_PARM1);
-       max = PRVM_G_VECTOR(OFS_PARM2);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
 
-       SetMinMaxSize( e, min, max );
+       SetMinMaxSize( prog, e, mins, maxs );
 
        CL_LinkEdict(e);
 }
 
-// #8 void(entity e, float chan, string samp, float volume, float atten) sound
-static void VM_CL_sound (void)
+// #8 void(entity e, float chan, string samp, float volume, float atten[, float pitchchange[, float flags]]) sound
+static void VM_CL_sound (prvm_prog_t *prog)
 {
        const char                      *sample;
        int                                     channel;
        prvm_edict_t            *entity;
-       float                           volume;
+       float                           fvolume;
        float                           attenuation;
        float pitchchange;
+       float                           startposition;
        int flags;
        vec3_t                          org;
 
@@ -170,18 +183,18 @@ static void VM_CL_sound (void)
        entity = PRVM_G_EDICT(OFS_PARM0);
        channel = (int)PRVM_G_FLOAT(OFS_PARM1);
        sample = PRVM_G_STRING(OFS_PARM2);
-       volume = PRVM_G_FLOAT(OFS_PARM3);
+       fvolume = PRVM_G_FLOAT(OFS_PARM3);
        attenuation = PRVM_G_FLOAT(OFS_PARM4);
 
-       if (volume < 0 || volume > 1)
+       if (fvolume < 0 || fvolume > 1)
        {
-               VM_Warning("VM_CL_sound: volume must be in range 0-1\n");
+               VM_Warning(prog, "VM_CL_sound: volume must be in range 0-1\n");
                return;
        }
 
        if (attenuation < 0 || attenuation > 4)
        {
-               VM_Warning("VM_CL_sound: attenuation must be in range 0-4\n");
+               VM_Warning(prog, "VM_CL_sound: attenuation must be in range 0-4\n");
                return;
        }
 
@@ -189,30 +202,41 @@ static void VM_CL_sound (void)
                pitchchange = 0;
        else
                pitchchange = PRVM_G_FLOAT(OFS_PARM5);
-       // ignoring prog->argc < 7 for now (no flags supported yet)
 
        if (prog->argc < 7)
                flags = 0;
        else
-               flags = PRVM_G_FLOAT(OFS_PARM6);
+       {
+               // LordHavoc: we only let the qc set certain flags, others are off-limits
+               flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED | CHANNELFLAG_FULLVOLUME);
+       }
+
+       // sound_starttime exists instead of sound_startposition because in a
+       // networking sense you might not know when something is being received,
+       // so making sounds match up in sync would be impossible if relative
+       // position was sent
+       if (PRVM_clientglobalfloat(sound_starttime))
+               startposition = cl.time - PRVM_clientglobalfloat(sound_starttime);
+       else
+               startposition = 0;
 
        channel = CHAN_USER2ENGINE(channel);
 
        if (!IS_CHAN(channel))
        {
-               VM_Warning("VM_CL_sound: channel must be in range 0-127\n");
+               VM_Warning(prog, "VM_CL_sound: channel must be in range 0-127\n");
                return;
        }
 
        CL_VM_GetEntitySoundOrigin(MAX_EDICTS + PRVM_NUM_FOR_EDICT(entity), org);
-       S_StartSound(MAX_EDICTS + PRVM_NUM_FOR_EDICT(entity), channel, S_FindName(sample), org, volume, attenuation);
+       S_StartSound_StartPosition_Flags(MAX_EDICTS + PRVM_NUM_FOR_EDICT(entity), channel, S_FindName(sample), org, fvolume, attenuation, startposition, flags, pitchchange > 0.0f ? pitchchange * 0.01f : 1.0f);
 }
 
 // #483 void(vector origin, string sample, float volume, float attenuation) pointsound
-static void VM_CL_pointsound(void)
+static void VM_CL_pointsound(prvm_prog_t *prog)
 {
        const char                      *sample;
-       float                           volume;
+       float                           fvolume;
        float                           attenuation;
        vec3_t                          org;
 
@@ -220,36 +244,36 @@ static void VM_CL_pointsound(void)
 
        VectorCopy( PRVM_G_VECTOR(OFS_PARM0), org);
        sample = PRVM_G_STRING(OFS_PARM1);
-       volume = PRVM_G_FLOAT(OFS_PARM2);
+       fvolume = PRVM_G_FLOAT(OFS_PARM2);
        attenuation = PRVM_G_FLOAT(OFS_PARM3);
 
-       if (volume < 0 || volume > 1)
+       if (fvolume < 0 || fvolume > 1)
        {
-               VM_Warning("VM_CL_pointsound: volume must be in range 0-1\n");
+               VM_Warning(prog, "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");
+               VM_Warning(prog, "VM_CL_pointsound: attenuation must be in range 0-4\n");
                return;
        }
 
        // Send World Entity as Entity to Play Sound (for CSQC, that is MAX_EDICTS)
-       S_StartSound(MAX_EDICTS, 0, S_FindName(sample), org, volume, attenuation);
+       S_StartSound(MAX_EDICTS, 0, S_FindName(sample), org, fvolume, attenuation);
 }
 
 // #14 entity() spawn
-static void VM_CL_spawn (void)
+static void VM_CL_spawn (prvm_prog_t *prog)
 {
        prvm_edict_t *ed;
-       ed = PRVM_ED_Alloc();
+       ed = PRVM_ED_Alloc(prog);
        VM_RETURN_EDICT(ed);
 }
 
-void CL_VM_SetTraceGlobals(const trace_t *trace, int svent)
+static void CL_VM_SetTraceGlobals(prvm_prog_t *prog, const trace_t *trace, int svent)
 {
-       VM_SetTraceGlobals(trace);
+       VM_SetTraceGlobals(prog, trace);
        PRVM_clientglobalfloat(trace_networkentity) = svent;
 }
 
@@ -257,9 +281,9 @@ void CL_VM_SetTraceGlobals(const trace_t *trace, int svent)
 #define CL_HitNetworkPlayers(move)     !((move) == MOVE_WORLDONLY || (move) == MOVE_NOMONSTERS)
 
 // #16 void(vector v1, vector v2, float movetype, entity ignore) traceline
-static void VM_CL_traceline (void)
+static void VM_CL_traceline (prvm_prog_t *prog)
 {
-       float   *v1, *v2;
+       vec3_t  v1, v2;
        trace_t trace;
        int             move, svent;
        prvm_edict_t    *ent;
@@ -270,17 +294,17 @@ static void VM_CL_traceline (void)
 
        prog->xfunction->builtinsprofile += 30;
 
-       v1 = PRVM_G_VECTOR(OFS_PARM0);
-       v2 = PRVM_G_VECTOR(OFS_PARM1);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
        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(v2[1]) || 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));
+       if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
+               prog->error_cmd("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
 
-       trace = CL_TraceLine(v1, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true, false);
+       trace = CL_TraceLine(v1, v2, move, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtracelinelength.value, CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true, false);
 
-       CL_VM_SetTraceGlobals(&trace, svent);
+       CL_VM_SetTraceGlobals(prog, &trace, svent);
 //     R_TimeReport("traceline");
 }
 
@@ -296,9 +320,9 @@ 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)
+static void VM_CL_tracebox (prvm_prog_t *prog)
 {
-       float   *v1, *v2, *m1, *m2;
+       vec3_t  v1, v2, m1, m2;
        trace_t trace;
        int             move, svent;
        prvm_edict_t    *ent;
@@ -308,27 +332,27 @@ static void VM_CL_tracebox (void)
 
        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);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
        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(v2[1]) || 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));
+       if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
+               prog->error_cmd("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
 
-       trace = CL_TraceBox(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true);
+       trace = CL_TraceBox(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtraceboxlength.value, CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true);
 
-       CL_VM_SetTraceGlobals(&trace, svent);
+       CL_VM_SetTraceGlobals(prog, &trace, svent);
 //     R_TimeReport("tracebox");
 }
 
-trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore, int *svent)
+static trace_t CL_Trace_Toss (prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore, int *svent)
 {
        int i;
        float gravity;
-       vec3_t move, end;
+       vec3_t start, end, mins, maxs, move;
        vec3_t original_origin;
        vec3_t original_velocity;
        vec3_t original_angles;
@@ -351,7 +375,10 @@ trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore, int *svent)
                VectorMA (PRVM_clientedictvector(tossent, angles), 0.05, PRVM_clientedictvector(tossent, avelocity), PRVM_clientedictvector(tossent, angles));
                VectorScale (PRVM_clientedictvector(tossent, velocity), 0.05, move);
                VectorAdd (PRVM_clientedictvector(tossent, origin), move, end);
-               trace = CL_TraceBox(PRVM_clientedictvector(tossent, origin), PRVM_clientedictvector(tossent, mins), PRVM_clientedictvector(tossent, maxs), end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), true, true, NULL, true);
+               VectorCopy(PRVM_clientedictvector(tossent, origin), start);
+               VectorCopy(PRVM_clientedictvector(tossent, mins), mins);
+               VectorCopy(PRVM_clientedictvector(tossent, maxs), maxs);
+               trace = CL_TraceBox(start, mins, maxs, end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), 0, 0, collision_extendmovelength.value, true, true, NULL, true);
                VectorCopy (trace.endpos, PRVM_clientedictvector(tossent, origin));
 
                if (trace.fraction < 1)
@@ -366,7 +393,7 @@ trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore, int *svent)
        return trace;
 }
 
-static void VM_CL_tracetoss (void)
+static void VM_CL_tracetoss (prvm_prog_t *prog)
 {
        trace_t trace;
        prvm_edict_t    *ent;
@@ -380,19 +407,19 @@ static void VM_CL_tracetoss (void)
        ent = PRVM_G_EDICT(OFS_PARM0);
        if (ent == prog->edicts)
        {
-               VM_Warning("tracetoss: can not use world entity\n");
+               VM_Warning(prog, "tracetoss: can not use world entity\n");
                return;
        }
        ignore = PRVM_G_EDICT(OFS_PARM1);
 
-       trace = CL_Trace_Toss (ent, ignore, &svent);
+       trace = CL_Trace_Toss (prog, ent, ignore, &svent);
 
-       CL_VM_SetTraceGlobals(&trace, svent);
+       CL_VM_SetTraceGlobals(prog, &trace, svent);
 }
 
 
 // #20 void(string s) precache_model
-void VM_CL_precache_model (void)
+static void VM_CL_precache_model (prvm_prog_t *prog)
 {
        const char      *name;
        int                     i;
@@ -422,30 +449,14 @@ void VM_CL_precache_model (void)
                                return;
                        }
                }
-               VM_Warning("VM_CL_precache_model: no free models\n");
+               VM_Warning(prog, "VM_CL_precache_model: no free models\n");
                return;
        }
-       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)
-{
-       prvm_edict_t    *ent;
-       int                             i, k;
-
-       ent = PRVM_NEXT_EDICT(prog->edicts);
-       for(k=0,i=1; i<prog->num_edicts ;i++, ent = PRVM_NEXT_EDICT(ent))
-       {
-               if (ent->priv.required->free)
-                       continue;
-               if(BoxesOverlap(mins, maxs, PRVM_clientedictvector(ent, absmin), PRVM_clientedictvector(ent, absmax)))
-                       list[k++] = ent;
-       }
-       return k;
+       VM_Warning(prog, "VM_CL_precache_model: model \"%s\" not found\n", name);
 }
 
 // #22 entity(vector org, float rad) findradius
-static void VM_CL_findradius (void)
+static void VM_CL_findradius (prvm_prog_t *prog)
 {
        prvm_edict_t    *ent, *chain;
        vec_t                   radius, radius2;
@@ -461,7 +472,7 @@ static void VM_CL_findradius (void)
        else
                chainfield = prog->fieldoffsets.chain;
        if(chainfield < 0)
-               PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
+               prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
 
        chain = (prvm_edict_t *)prog->edicts;
 
@@ -475,7 +486,7 @@ static void VM_CL_findradius (void)
        maxs[0] = org[0] + (radius + 1);
        maxs[1] = org[1] + (radius + 1);
        maxs[2] = org[2] + (radius + 1);
-       numtouchedicts = CSQC_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
+       numtouchedicts = World_EntitiesInBox(&cl.world, mins, maxs, MAX_EDICTS, touchedicts);
        if (numtouchedicts > MAX_EDICTS)
        {
                // this never happens   //[515]: for what then ?
@@ -512,10 +523,10 @@ static void VM_CL_findradius (void)
 }
 
 // #34 float() droptofloor
-static void VM_CL_droptofloor (void)
+static void VM_CL_droptofloor (prvm_prog_t *prog)
 {
        prvm_edict_t            *ent;
-       vec3_t                          end;
+       vec3_t                          start, end, mins, maxs;
        trace_t                         trace;
 
        VM_SAFEPARMCOUNTRANGE(0, 2, VM_CL_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
@@ -526,19 +537,22 @@ static void VM_CL_droptofloor (void)
        ent = PRVM_PROG_TO_EDICT(PRVM_clientglobaledict(self));
        if (ent == prog->edicts)
        {
-               VM_Warning("droptofloor: can not modify world entity\n");
+               VM_Warning(prog, "droptofloor: can not modify world entity\n");
                return;
        }
        if (ent->priv.server->free)
        {
-               VM_Warning("droptofloor: can not modify free entity\n");
+               VM_Warning(prog, "droptofloor: can not modify free entity\n");
                return;
        }
 
-       VectorCopy (PRVM_clientedictvector(ent, origin), end);
+       VectorCopy(PRVM_clientedictvector(ent, origin), start);
+       VectorCopy(PRVM_clientedictvector(ent, mins), mins);
+       VectorCopy(PRVM_clientedictvector(ent, maxs), maxs);
+       VectorCopy(PRVM_clientedictvector(ent, origin), end);
        end[2] -= 256;
 
-       trace = CL_TraceBox(PRVM_clientedictvector(ent, origin), PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+       trace = CL_TraceBox(start, mins, maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, true, NULL, true);
 
        if (trace.fraction != 1)
        {
@@ -552,7 +566,7 @@ static void VM_CL_droptofloor (void)
 }
 
 // #35 void(float style, string value) lightstyle
-static void VM_CL_lightstyle (void)
+static void VM_CL_lightstyle (prvm_prog_t *prog)
 {
        int                     i;
        const char      *c;
@@ -563,7 +577,7 @@ static void VM_CL_lightstyle (void)
        c = PRVM_G_STRING(OFS_PARM1);
        if (i >= cl.max_lightstyle)
        {
-               VM_Warning("VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
+               VM_Warning(prog, "VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
                return;
        }
        strlcpy (cl.lightstyle[i].map, c, sizeof (cl.lightstyle[i].map));
@@ -572,7 +586,7 @@ static void VM_CL_lightstyle (void)
 }
 
 // #40 float(entity e) checkbottom
-static void VM_CL_checkbottom (void)
+static void VM_CL_checkbottom (prvm_prog_t *prog)
 {
        static int              cs_yes, cs_no;
        prvm_edict_t    *ent;
@@ -616,7 +630,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_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true, false);
+       trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, true, NULL, true, false);
 
        if (trace.fraction == 1.0)
                return;
@@ -630,7 +644,7 @@ realcheck:
                        start[0] = stop[0] = x ? maxs[0] : mins[0];
                        start[1] = stop[1] = y ? maxs[1] : mins[1];
 
-                       trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true, false);
+                       trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, true, NULL, true, false);
 
                        if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
                                bottom = trace.endpos[2];
@@ -643,96 +657,87 @@ realcheck:
 }
 
 // #41 float(vector v) pointcontents
-static void VM_CL_pointcontents (void)
+static void VM_CL_pointcontents (prvm_prog_t *prog)
 {
+       vec3_t point;
        VM_SAFEPARMCOUNT(1, VM_CL_pointcontents);
-       PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, CL_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
+       PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(CL_PointSuperContents(point));
 }
 
 // #48 void(vector o, vector d, float color, float count) particle
-static void VM_CL_particle (void)
+static void VM_CL_particle (prvm_prog_t *prog)
 {
-       float   *org, *dir;
+       vec3_t org, dir;
        int             count;
        unsigned char   color;
        VM_SAFEPARMCOUNT(4, VM_CL_particle);
 
-       org = PRVM_G_VECTOR(OFS_PARM0);
-       dir = PRVM_G_VECTOR(OFS_PARM1);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
        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
-static void VM_CL_ambientsound (void)
+static void VM_CL_ambientsound (prvm_prog_t *prog)
 {
-       float   *f;
+       vec3_t f;
        sfx_t   *s;
        VM_SAFEPARMCOUNT(4, VM_CL_ambientsound);
        s = S_FindName(PRVM_G_STRING(OFS_PARM0));
-       f = PRVM_G_VECTOR(OFS_PARM1);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), f);
        S_StaticSound (s, f, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3)*64);
 }
 
 // #92 vector(vector org[, float lpflag]) getlight (DP_QC_GETLIGHT)
-static void VM_CL_getlight (void)
+static void VM_CL_getlight (prvm_prog_t *prog)
 {
        vec3_t ambientcolor, diffusecolor, diffusenormal;
-       vec_t *p;
-
-       VM_SAFEPARMCOUNTRANGE(1, 2, VM_CL_getlight);
-
-       p = PRVM_G_VECTOR(OFS_PARM0);
-       VectorClear(ambientcolor);
-       VectorClear(diffusecolor);
-       VectorClear(diffusenormal);
-       if (prog->argc >= 2)
-               R_CompleteLightPoint(ambientcolor, diffusecolor, diffusenormal, p, PRVM_G_FLOAT(OFS_PARM1));
-       else if (cl.worldmodel && cl.worldmodel->brush.LightPoint)
-               cl.worldmodel->brush.LightPoint(cl.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
+       vec3_t p;
+       int flags = prog->argc >= 2 ? PRVM_G_FLOAT(OFS_PARM1) : LP_LIGHTMAP;
+
+       VM_SAFEPARMCOUNTRANGE(1, 3, VM_CL_getlight);
+
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
+       R_CompleteLightPoint(ambientcolor, diffusecolor, diffusenormal, p, flags, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
        VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
+       if (PRVM_clientglobalvector(getlight_ambient))
+               VectorCopy(ambientcolor, PRVM_clientglobalvector(getlight_ambient));
+       if (PRVM_clientglobalvector(getlight_diffuse))
+               VectorCopy(diffusecolor, PRVM_clientglobalvector(getlight_diffuse));
+       if (PRVM_clientglobalvector(getlight_dir))
+               VectorCopy(diffusenormal, PRVM_clientglobalvector(getlight_dir));
 }
 
 //============================================================================
 //[515]: SCENE MANAGER builtins
-extern qboolean CSQC_AddRenderEdict (prvm_edict_t *ed, int edictnum);//csprogs.c
 
+extern cvar_t v_yshearing;
 void CSQC_R_RecalcView (void)
 {
        extern matrix4x4_t viewmodelmatrix_nobob;
        extern matrix4x4_t viewmodelmatrix_withbob;
        Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, cl.csqc_vieworigin[0], cl.csqc_vieworigin[1], cl.csqc_vieworigin[2], cl.csqc_viewangles[0], cl.csqc_viewangles[1], cl.csqc_viewangles[2], 1);
+       if (v_yshearing.value > 0)
+               Matrix4x4_QuakeToDuke3D(&r_refdef.view.matrix, &r_refdef.view.matrix, v_yshearing.value);
        Matrix4x4_Copy(&viewmodelmatrix_nobob, &r_refdef.view.matrix);
        Matrix4x4_ConcatScale(&viewmodelmatrix_nobob, cl_viewmodel_scale.value);
        Matrix4x4_Concat(&viewmodelmatrix_withbob, &r_refdef.view.matrix, &cl.csqc_viewmodelmatrixfromengine);
 }
 
-void CL_RelinkLightFlashes(void);
 //#300 void() clearscene (EXT_CSQC)
-void VM_CL_R_ClearScene (void)
+static void VM_CL_R_ClearScene (prvm_prog_t *prog)
 {
        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;
-       r_refdef.view.isoverlay = false;
+       // restore the view settings to the values that VM_CL_UpdateView received from the client code
+       r_refdef.view = csqc_original_r_refdef_view;
+       // polygonbegin without draw2d arg has to guess
+       prog->polygonbegin_guess2d = false;
        VectorCopy(cl.csqc_vieworiginfromengine, cl.csqc_vieworigin);
        VectorCopy(cl.csqc_viewanglesfromengine, cl.csqc_viewangles);
        cl.csqc_vidvars.drawworld = r_drawworld.integer != 0;
@@ -742,17 +747,14 @@ void VM_CL_R_ClearScene (void)
 }
 
 //#301 void(float mask) addentities (EXT_CSQC)
-extern void CSQC_Predraw (prvm_edict_t *ed);//csprogs.c
-extern void CSQC_Think (prvm_edict_t *ed);//csprogs.c
-void VM_CL_R_AddEntities (void)
+static void VM_CL_R_AddEntities (prvm_prog_t *prog)
 {
-       double t = Sys_DoubleTime();
+       double t = Sys_DirtyTime();
        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();
 
        PRVM_clientglobalfloat(time) = cl.time;
        for(i=1;i<prog->num_edicts;i++)
@@ -775,16 +777,18 @@ void VM_CL_R_AddEntities (void)
        }
 
        // callprofile fixing hack: do not include this time in what is counted for CSQC_UpdateView
-       prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= Sys_DoubleTime() - t;
+       t = Sys_DirtyTime() - t;if (t < 0 || t >= 1800) t = 0;
+       prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= t;
 }
 
 //#302 void(entity ent) addentity (EXT_CSQC)
-void VM_CL_R_AddEntity (void)
+static void VM_CL_R_AddEntity (prvm_prog_t *prog)
 {
-       double t = Sys_DoubleTime();
+       double t = Sys_DirtyTime();
        VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntity);
        CSQC_AddRenderEdict(PRVM_G_EDICT(OFS_PARM0), 0);
-       prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= Sys_DoubleTime() - t;
+       t = Sys_DirtyTime() - t;if (t < 0 || t >= 1800) t = 0;
+       prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= t;
 }
 
 //#303 float(float property, ...) setproperty (EXT_CSQC)
@@ -793,10 +797,10 @@ void VM_CL_R_AddEntity (void)
 //#309 float(float property) getproperty
 //#309 vector(float property) getpropertyvec
 // VorteX: make this function be able to return previously set property if new value is not given
-void VM_CL_R_SetView (void)
+static void VM_CL_R_SetView (prvm_prog_t *prog)
 {
        int             c;
-       float   *f;
+       prvm_vec_t      *f;
        float   k;
 
        VM_SAFEPARMCOUNTRANGE(1, 3, VM_CL_R_SetView);
@@ -827,7 +831,7 @@ void VM_CL_R_SetView (void)
                        PRVM_G_FLOAT(OFS_RETURN) = r_refdef.view.height;
                        break;
                case VF_VIEWPORT:
-                       VM_Warning("VM_CL_R_GetView : VF_VIEWPORT can't be retrieved, use VF_MIN/VF_SIZE instead\n");
+                       VM_Warning(prog, "VM_CL_R_GetView : VF_VIEWPORT can't be retrieved, use VF_MIN/VF_SIZE instead\n");
                        break;
                case VF_FOV:
                        VectorSet(PRVM_G_VECTOR(OFS_RETURN), r_refdef.view.ortho_x, r_refdef.view.ortho_y, 0);
@@ -889,9 +893,47 @@ void VM_CL_R_SetView (void)
                case VF_CLEARSCREEN:
                        PRVM_G_FLOAT(OFS_RETURN) = r_refdef.view.isoverlay;
                        break;
+               case VF_MAINVIEW:
+                       PRVM_G_FLOAT(OFS_RETURN) = r_refdef.view.ismain;
+                       break;
+               case VF_FOG_DENSITY:
+                       PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_density;
+                       break;
+               case VF_FOG_COLOR:
+                       PRVM_G_VECTOR(OFS_RETURN)[0] = r_refdef.fog_red;
+                       PRVM_G_VECTOR(OFS_RETURN)[1] = r_refdef.fog_green;
+                       PRVM_G_VECTOR(OFS_RETURN)[2] = r_refdef.fog_blue;
+                       break;
+               case VF_FOG_COLOR_R:
+                       PRVM_G_VECTOR(OFS_RETURN)[0] = r_refdef.fog_red;
+                       break;
+               case VF_FOG_COLOR_G:
+                       PRVM_G_VECTOR(OFS_RETURN)[1] = r_refdef.fog_green;
+                       break;
+               case VF_FOG_COLOR_B:
+                       PRVM_G_VECTOR(OFS_RETURN)[2] = r_refdef.fog_blue;
+                       break;
+               case VF_FOG_ALPHA:
+                       PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_alpha;
+                       break;
+               case VF_FOG_START:
+                       PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_start;
+                       break;
+               case VF_FOG_END:
+                       PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_end;
+                       break;
+               case VF_FOG_HEIGHT:
+                       PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_height;
+                       break;
+               case VF_FOG_FADEDEPTH:
+                       PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_fadedepth;
+                       break;
+               case VF_MINFPS_QUALITY:
+                       PRVM_G_FLOAT(OFS_RETURN) = r_refdef.view.quality;
+                       break;
                default:
                        PRVM_G_FLOAT(OFS_RETURN) = 0;
-                       VM_Warning("VM_CL_R_GetView : unknown parm %i\n", c);
+                       VM_Warning(prog, "VM_CL_R_GetView : unknown parm %i\n", c);
                        return;
                }
                return;
@@ -1004,21 +1046,59 @@ void VM_CL_R_SetView (void)
        case VF_CLEARSCREEN:
                r_refdef.view.isoverlay = !k;
                break;
+       case VF_MAINVIEW:
+               PRVM_G_FLOAT(OFS_RETURN) = r_refdef.view.ismain;
+               break;
+       case VF_FOG_DENSITY:
+               r_refdef.fog_density = k;
+               break;
+       case VF_FOG_COLOR:
+               r_refdef.fog_red = f[0];
+               r_refdef.fog_green = f[1];
+               r_refdef.fog_blue = f[2];
+               break;
+       case VF_FOG_COLOR_R:
+               r_refdef.fog_red = k;
+               break;
+       case VF_FOG_COLOR_G:
+               r_refdef.fog_green = k;
+               break;
+       case VF_FOG_COLOR_B:
+               r_refdef.fog_blue = k;
+               break;
+       case VF_FOG_ALPHA:
+               r_refdef.fog_alpha = k;
+               break;
+       case VF_FOG_START:
+               r_refdef.fog_start = k;
+               break;
+       case VF_FOG_END:
+               r_refdef.fog_end = k;
+               break;
+       case VF_FOG_HEIGHT:
+               r_refdef.fog_height = k;
+               break;
+       case VF_FOG_FADEDEPTH:
+               r_refdef.fog_fadedepth = k;
+               break;
+       case VF_MINFPS_QUALITY:
+               r_refdef.view.quality = k;
+               break;
        default:
                PRVM_G_FLOAT(OFS_RETURN) = 0;
-               VM_Warning("VM_CL_R_SetView : unknown parm %i\n", c);
+               VM_Warning(prog, "VM_CL_R_SetView : unknown parm %i\n", c);
                return;
        }
        PRVM_G_FLOAT(OFS_RETURN) = 1;
 }
 
 //#305 void(vector org, float radius, vector lightcolours[, float style, string cubemapname, float pflags]) adddynamiclight (EXT_CSQC)
-void VM_CL_R_AddDynamicLight (void)
+static void VM_CL_R_AddDynamicLight (prvm_prog_t *prog)
 {
-       double t = Sys_DoubleTime();
-       vec_t *org;
+       double t = Sys_DirtyTime();
+       vec3_t org;
        float radius = 300;
-       vec_t *col;
+       vec3_t col;
        int style = -1;
        const char *cubemapname = NULL;
        int pflags = PFLAGS_CORONA | PFLAGS_FULLDYNAMIC;
@@ -1036,9 +1116,9 @@ void VM_CL_R_AddDynamicLight (void)
        if (r_refdef.scene.numlights >= MAX_DLIGHTS)
                return;
 
-       org = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
        radius = PRVM_G_FLOAT(OFS_PARM1);
-       col = PRVM_G_VECTOR(OFS_PARM2);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM2), col);
        if (prog->argc >= 4)
        {
                style = (int)PRVM_G_FLOAT(OFS_PARM3);
@@ -1062,38 +1142,41 @@ void VM_CL_R_AddDynamicLight (void)
 
        R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &matrix, col, style, cubemapname, castshadow, coronaintensity, coronasizescale, ambientscale, diffusescale, specularscale, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
        r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights];r_refdef.scene.numlights++;
-       prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= Sys_DoubleTime() - t;
+       t = Sys_DirtyTime() - t;if (t < 0 || t >= 1800) t = 0;
+       prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= t;
 }
 
 //============================================================================
 
 //#310 vector (vector v) cs_unproject (EXT_CSQC)
-static void VM_CL_unproject (void)
+static void VM_CL_unproject (prvm_prog_t *prog)
 {
-       float   *f;
-       vec3_t  temp;
+       vec3_t f;
+       vec3_t temp;
+       vec3_t result;
 
        VM_SAFEPARMCOUNT(1, VM_CL_unproject);
-       f = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), f);
        VectorSet(temp,
                f[2],
                (-1.0 + 2.0 * (f[0] / vid_conwidth.integer)) * f[2] * -r_refdef.view.frustum_x,
                (-1.0 + 2.0 * (f[1] / vid_conheight.integer)) * f[2] * -r_refdef.view.frustum_y);
        if(v_flipped.integer)
                temp[1] = -temp[1];
-       Matrix4x4_Transform(&r_refdef.view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN));
+       Matrix4x4_Transform(&r_refdef.view.matrix, temp, result);
+       VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN));
 }
 
 //#311 vector (vector v) cs_project (EXT_CSQC)
-static void VM_CL_project (void)
+static void VM_CL_project (prvm_prog_t *prog)
 {
-       float   *f;
-       vec3_t  v;
+       vec3_t f;
+       vec3_t v;
        matrix4x4_t m;
 
        VM_SAFEPARMCOUNT(1, VM_CL_project);
-       f = PRVM_G_VECTOR(OFS_PARM0);
-       Matrix4x4_Invert_Simple(&m, &r_refdef.view.matrix);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), f);
+       Matrix4x4_Invert_Full(&m, &r_refdef.view.matrix);
        Matrix4x4_Transform(&m, f, v);
        if(v_flipped.integer)
                v[1] = -v[1];
@@ -1107,7 +1190,7 @@ static void VM_CL_project (void)
 }
 
 //#330 float(float stnum) getstatf (EXT_CSQC)
-static void VM_CL_getstatf (void)
+static void VM_CL_getstatf (prvm_prog_t *prog)
 {
        int i;
        union
@@ -1119,7 +1202,7 @@ static void VM_CL_getstatf (void)
        i = (int)PRVM_G_FLOAT(OFS_PARM0);
        if(i < 0 || i >= MAX_CL_STATS)
        {
-               VM_Warning("VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
+               VM_Warning(prog, "VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
                return;
        }
        dat.l = cl.stats[i];
@@ -1127,7 +1210,7 @@ static void VM_CL_getstatf (void)
 }
 
 //#331 float(float stnum) getstati (EXT_CSQC)
-static void VM_CL_getstati (void)
+static void VM_CL_getstati (prvm_prog_t *prog)
 {
        int i, index;
        int firstbit, bitcount;
@@ -1151,7 +1234,7 @@ static void VM_CL_getstati (void)
 
        if(index < 0 || index >= MAX_CL_STATS)
        {
-               VM_Warning("VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
+               VM_Warning(prog, "VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
                return;
        }
        i = cl.stats[index];
@@ -1161,7 +1244,7 @@ static void VM_CL_getstati (void)
 }
 
 //#332 string(float firststnum) getstats (EXT_CSQC)
-static void VM_CL_getstats (void)
+static void VM_CL_getstats (prvm_prog_t *prog)
 {
        int i;
        char t[17];
@@ -1170,15 +1253,15 @@ static void VM_CL_getstats (void)
        if(i < 0 || i > MAX_CL_STATS-4)
        {
                PRVM_G_INT(OFS_RETURN) = OFS_NULL;
-               VM_Warning("VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
+               VM_Warning(prog, "VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
                return;
        }
        strlcpy(t, (char*)&cl.stats[i], sizeof(t));
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, t);
 }
 
 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
-static void VM_CL_setmodelindex (void)
+static void VM_CL_setmodelindex (prvm_prog_t *prog)
 {
        int                             i;
        prvm_edict_t    *t;
@@ -1199,23 +1282,23 @@ static void VM_CL_setmodelindex (void)
        model = CL_GetModelByIndex(i);
        if (!model)
        {
-               VM_Warning("VM_CL_setmodelindex: null model\n");
+               VM_Warning(prog, "VM_CL_setmodelindex: null model\n");
                return;
        }
-       PRVM_clientedictstring(t, model) = PRVM_SetEngineString(model->name);
+       PRVM_clientedictstring(t, model) = PRVM_SetEngineString(prog, model->name);
        PRVM_clientedictfloat(t, 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);
+               SetMinMaxSize (prog, t, model->normalmins, model->normalmaxs);
        }
        else
-               SetMinMaxSize (t, vec3_origin, vec3_origin);
+               SetMinMaxSize (prog, t, vec3_origin, vec3_origin);
 }
 
 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
-static void VM_CL_modelnameforindex (void)
+static void VM_CL_modelnameforindex (prvm_prog_t *prog)
 {
        dp_model_t *model;
 
@@ -1223,11 +1306,11 @@ static void VM_CL_modelnameforindex (void)
 
        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;
+       PRVM_G_INT(OFS_RETURN) = model ? PRVM_SetEngineString(prog, model->name) : 0;
 }
 
 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
-static void VM_CL_particleeffectnum (void)
+static void VM_CL_particleeffectnum (prvm_prog_t *prog)
 {
        int                     i;
        VM_SAFEPARMCOUNT(1, VM_CL_particleeffectnum);
@@ -1238,33 +1321,34 @@ static void VM_CL_particleeffectnum (void)
 }
 
 // #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC)
-static void VM_CL_trailparticles (void)
+static void VM_CL_trailparticles (prvm_prog_t *prog)
 {
        int                             i;
-       float                   *start, *end;
+       vec3_t                  start, end, velocity;
        prvm_edict_t    *t;
        VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_trailparticles);
 
        t = PRVM_G_EDICT(OFS_PARM0);
        i               = (int)PRVM_G_FLOAT(OFS_PARM1);
-       start   = PRVM_G_VECTOR(OFS_PARM2);
-       end             = PRVM_G_VECTOR(OFS_PARM3);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
+       VectorCopy(PRVM_clientedictvector(t, velocity), velocity);
 
        if (i < 0)
                return;
-       CL_ParticleEffect(i, 1, start, end, PRVM_clientedictvector(t, velocity), PRVM_clientedictvector(t, velocity), NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0);
+       CL_ParticleTrail(i, 1, start, end, velocity, velocity, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0, true, true, NULL, NULL, 1);
 }
 
 //#337 void(float effectnum, vector origin, vector dir, float count[, float color]) pointparticles (EXT_CSQC)
-static void VM_CL_pointparticles (void)
+static void VM_CL_pointparticles (prvm_prog_t *prog)
 {
        int                     i;
        float n;
-       float           *f, *v;
+       vec3_t f, v;
        VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_pointparticles);
        i = (int)PRVM_G_FLOAT(OFS_PARM0);
-       f = PRVM_G_VECTOR(OFS_PARM1);
-       v = PRVM_G_VECTOR(OFS_PARM2);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), f);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM2), v);
        n = PRVM_G_FLOAT(OFS_PARM3);
        if (i < 0)
                return;
@@ -1272,29 +1356,36 @@ static void VM_CL_pointparticles (void)
 }
 
 //#502 void(float effectnum, entity own, vector origin_from, vector origin_to, vector dir_from, vector dir_to, float count, float extflags) boxparticles (DP_CSQC_BOXPARTICLES)
-static void VM_CL_boxparticles (void)
+static void VM_CL_boxparticles (prvm_prog_t *prog)
 {
        int effectnum;
        // prvm_edict_t *own;
-       float *origin_from, *origin_to, *dir_from, *dir_to;
+       vec3_t origin_from, origin_to, dir_from, dir_to;
        float count;
        int flags;
-       float tintmins[4], tintmaxs[4];
+       qboolean istrail;
+       float tintmins[4], tintmaxs[4], fade;
        VM_SAFEPARMCOUNTRANGE(7, 8, VM_CL_boxparticles);
 
        effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
+       if (effectnum < 0)
+               return;
        // own = PRVM_G_EDICT(OFS_PARM1); // TODO find use for this
-       origin_from = PRVM_G_VECTOR(OFS_PARM2);
-       origin_to = PRVM_G_VECTOR(OFS_PARM3);
-       dir_from = PRVM_G_VECTOR(OFS_PARM4);
-       dir_to = PRVM_G_VECTOR(OFS_PARM5);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin_from);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin_to  );
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM4), dir_from   );
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM5), dir_to     );
        count = PRVM_G_FLOAT(OFS_PARM6);
        if(prog->argc >= 8)
                flags = PRVM_G_FLOAT(OFS_PARM7);
        else
                flags = 0;
+
        Vector4Set(tintmins, 1, 1, 1, 1);
        Vector4Set(tintmaxs, 1, 1, 1, 1);
+       fade = 1;
+       istrail = false;
+
        if(flags & 1) // read alpha
        {
                tintmins[3] = PRVM_clientglobalfloat(particles_alphamin);
@@ -1305,13 +1396,23 @@ static void VM_CL_boxparticles (void)
                VectorCopy(PRVM_clientglobalvector(particles_colormin), tintmins);
                VectorCopy(PRVM_clientglobalvector(particles_colormax), tintmaxs);
        }
-       if (effectnum < 0)
-               return;
-       CL_ParticleTrail(effectnum, count, origin_from, origin_to, dir_from, dir_to, NULL, 0, true, true, tintmins, tintmaxs);
+       if(flags & 4) // read fade
+       {
+               fade = PRVM_clientglobalfloat(particles_fade);
+       }
+       if(flags & 128) // draw as trail
+       {
+               istrail = true;
+       }
+
+       if (istrail)
+               CL_ParticleTrail(effectnum, count, origin_from, origin_to, dir_from, dir_to, NULL, 0, true, true, tintmins, tintmaxs, fade);
+       else
+               CL_ParticleBox(effectnum, count, origin_from, origin_to, dir_from, dir_to, NULL, 0, true, true, tintmins, tintmaxs, fade);
 }
 
 //#531 void(float pause) setpause
-static void VM_CL_setpause(void) 
+static void VM_CL_setpause(prvm_prog_t *prog)
 {
        VM_SAFEPARMCOUNT(1, VM_CL_setpause);
        if ((int)PRVM_G_FLOAT(OFS_PARM0) != 0)
@@ -1321,7 +1422,7 @@ static void VM_CL_setpause(void)
 }
 
 //#343 void(float usecursor) setcursormode (DP_CSQC)
-static void VM_CL_setcursormode (void)
+static void VM_CL_setcursormode (prvm_prog_t *prog)
 {
        VM_SAFEPARMCOUNT(1, VM_CL_setcursormode);
        cl.csqc_wantsmousemove = PRVM_G_FLOAT(OFS_PARM0) != 0;
@@ -1329,7 +1430,7 @@ static void VM_CL_setcursormode (void)
 }
 
 //#344 vector() getmousepos (DP_CSQC)
-static void VM_CL_getmousepos(void)
+static void VM_CL_getmousepos(prvm_prog_t *prog)
 {
        VM_SAFEPARMCOUNT(0,VM_CL_getmousepos);
 
@@ -1342,11 +1443,11 @@ static void VM_CL_getmousepos(void)
 }
 
 //#345 float(float framenum) getinputstate (EXT_CSQC)
-static void VM_CL_getinputstate (void)
+static void VM_CL_getinputstate (prvm_prog_t *prog)
 {
-       int i, frame;
+       unsigned int i, frame;
        VM_SAFEPARMCOUNT(1, VM_CL_getinputstate);
-       frame = (int)PRVM_G_FLOAT(OFS_PARM0);
+       frame = (unsigned int)PRVM_G_FLOAT(OFS_PARM0);
        PRVM_G_FLOAT(OFS_RETURN) = false;
        for (i = 0;i < CL_MAX_USERCMDS;i++)
        {
@@ -1358,6 +1459,7 @@ static void VM_CL_getinputstate (void)
                        PRVM_clientglobalvector(input_movevalues)[1] = cl.movecmd[i].sidemove;
                        PRVM_clientglobalvector(input_movevalues)[2] = cl.movecmd[i].upmove;
                        PRVM_clientglobalfloat(input_timelength) = cl.movecmd[i].frametime;
+                       // this probably shouldn't be here
                        if(cl.movecmd[i].crouch)
                        {
                                VectorCopy(cl.playercrouchmins, PRVM_clientglobalvector(pmove_mins));
@@ -1374,19 +1476,85 @@ static void VM_CL_getinputstate (void)
 }
 
 //#346 void(float sens) setsensitivityscaler (EXT_CSQC)
-static void VM_CL_setsensitivityscale (void)
+static void VM_CL_setsensitivityscale (prvm_prog_t *prog)
 {
        VM_SAFEPARMCOUNT(1, VM_CL_setsensitivityscale);
        cl.sensitivityscale = PRVM_G_FLOAT(OFS_PARM0);
 }
 
 //#347 void() runstandardplayerphysics (EXT_CSQC)
-static void VM_CL_runplayerphysics (void)
+#define PMF_JUMP_HELD 1 // matches FTEQW
+#define PMF_LADDER 2 // not used by DP, FTEQW sets this in runplayerphysics but does not read it
+#define PMF_DUCKED 4 // FIXME FTEQW doesn't have this for Q1 like movement because Q1 cannot crouch
+#define PMF_ONGROUND 8 // FIXME FTEQW doesn't have this for Q1 like movement and expects CSQC code to do its own trace, this is stupid CPU waste
+static void VM_CL_runplayerphysics (prvm_prog_t *prog)
 {
+       cl_clientmovement_state_t s;
+       prvm_edict_t *ent;
+
+       memset(&s, 0, sizeof(s));
+
+       VM_SAFEPARMCOUNTRANGE(0, 1, VM_CL_runplayerphysics);
+
+       ent = (prog->argc == 1 ? PRVM_G_EDICT(OFS_PARM0) : prog->edicts);
+       if(ent == prog->edicts)
+       {
+               // deprecated use
+               s.self = NULL;
+               VectorCopy(PRVM_clientglobalvector(pmove_org), s.origin);
+               VectorCopy(PRVM_clientglobalvector(pmove_vel), s.velocity);
+               VectorCopy(PRVM_clientglobalvector(pmove_mins), s.mins);
+               VectorCopy(PRVM_clientglobalvector(pmove_maxs), s.maxs);
+               s.crouched = 0;
+               s.waterjumptime = PRVM_clientglobalfloat(pmove_waterjumptime);
+               s.cmd.canjump = (int)PRVM_clientglobalfloat(pmove_jump_held) == 0;
+       }
+       else
+       {
+               // new use
+               s.self = ent;
+               VectorCopy(PRVM_clientedictvector(ent, origin), s.origin);
+               VectorCopy(PRVM_clientedictvector(ent, velocity), s.velocity);
+               VectorCopy(PRVM_clientedictvector(ent, mins), s.mins);
+               VectorCopy(PRVM_clientedictvector(ent, maxs), s.maxs);
+               s.crouched = ((int)PRVM_clientedictfloat(ent, pmove_flags) & PMF_DUCKED) != 0;
+               s.waterjumptime = 0; // FIXME where do we get this from? FTEQW lacks support for this too
+               s.cmd.canjump = ((int)PRVM_clientedictfloat(ent, pmove_flags) & PMF_JUMP_HELD) == 0;
+       }
+
+       VectorCopy(PRVM_clientglobalvector(input_angles), s.cmd.viewangles);
+       s.cmd.forwardmove = PRVM_clientglobalvector(input_movevalues)[0];
+       s.cmd.sidemove = PRVM_clientglobalvector(input_movevalues)[1];
+       s.cmd.upmove = PRVM_clientglobalvector(input_movevalues)[2];
+       s.cmd.buttons = PRVM_clientglobalfloat(input_buttons);
+       s.cmd.frametime = PRVM_clientglobalfloat(input_timelength);
+       s.cmd.jump = (s.cmd.buttons & 2) != 0;
+       s.cmd.crouch = (s.cmd.buttons & 16) != 0;
+
+       CL_ClientMovement_PlayerMove_Frame(&s);
+
+       if(ent == prog->edicts)
+       {
+               // deprecated use
+               VectorCopy(s.origin, PRVM_clientglobalvector(pmove_org));
+               VectorCopy(s.velocity, PRVM_clientglobalvector(pmove_vel));
+               PRVM_clientglobalfloat(pmove_jump_held) = !s.cmd.canjump;
+               PRVM_clientglobalfloat(pmove_waterjumptime) = s.waterjumptime;
+       }
+       else
+       {
+               // new use
+               VectorCopy(s.origin, PRVM_clientedictvector(ent, origin));
+               VectorCopy(s.velocity, PRVM_clientedictvector(ent, velocity));
+               PRVM_clientedictfloat(ent, pmove_flags) =
+                       (s.crouched ? PMF_DUCKED : 0) |
+                       (s.cmd.canjump ? 0 : PMF_JUMP_HELD) |
+                       (s.onground ? PMF_ONGROUND : 0);
+       }
 }
 
 //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
-static void VM_CL_getplayerkey (void)
+static void VM_CL_getplayerkey (prvm_prog_t *prog)
 {
        int                     i;
        char            t[128];
@@ -1435,35 +1603,26 @@ static void VM_CL_getplayerkey (void)
        else
                if(!strcasecmp(c, "viewentity"))
                        dpsnprintf(t, sizeof(t), "%i", i+1);
-       else
-               if(gamemode == GAME_XONOTIC && !strcasecmp(c, "TEMPHACK_origin"))
-               {
-                       // PLEASE REMOVE THIS once deltalisten() of EXT_CSQC_1
-                       // is implemented, or Xonotic uses CSQC-networked
-                       // players, whichever comes first
-                       entity_t *e = cl.entities + (i+1);
-                       if(e->state_current.active)
-                       {
-                               vec3_t origin;
-                               Matrix4x4_OriginFromMatrix(&e->render.matrix, origin);
-                               dpsnprintf(t, sizeof(t), "%.9g %.9g %.9g", origin[0], origin[1], origin[2]);
-                       }
-               }
        if(!t[0])
                return;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, t);
 }
 
 //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
-static void VM_CL_setlistener (void)
+static void VM_CL_setlistener (prvm_prog_t *prog)
 {
+       vec3_t origin, forward, left, up;
        VM_SAFEPARMCOUNT(4, VM_CL_setlistener);
-       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));
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), origin);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), forward);
+       VectorNegate(PRVM_G_VECTOR(OFS_PARM2), left);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM3), up);
+       Matrix4x4_FromVectors(&cl.csqc_listenermatrix, forward, left, up, origin);
        cl.csqc_usecsqclistener = true; //use csqc listener at this frame
 }
 
 //#352 void(string cmdname) registercommand (EXT_CSQC)
-static void VM_CL_registercmd (void)
+static void VM_CL_registercmd (prvm_prog_t *prog)
 {
        char *t;
        VM_SAFEPARMCOUNT(1, VM_CL_registercmd);
@@ -1482,113 +1641,111 @@ static void VM_CL_registercmd (void)
 }
 
 //#360 float() readbyte (EXT_CSQC)
-static void VM_CL_ReadByte (void)
+static void VM_CL_ReadByte (prvm_prog_t *prog)
 {
        VM_SAFEPARMCOUNT(0, VM_CL_ReadByte);
-       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadByte();
+       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadByte(&cl_message);
 }
 
 //#361 float() readchar (EXT_CSQC)
-static void VM_CL_ReadChar (void)
+static void VM_CL_ReadChar (prvm_prog_t *prog)
 {
        VM_SAFEPARMCOUNT(0, VM_CL_ReadChar);
-       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadChar();
+       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadChar(&cl_message);
 }
 
 //#362 float() readshort (EXT_CSQC)
-static void VM_CL_ReadShort (void)
+static void VM_CL_ReadShort (prvm_prog_t *prog)
 {
        VM_SAFEPARMCOUNT(0, VM_CL_ReadShort);
-       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadShort();
+       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadShort(&cl_message);
 }
 
 //#363 float() readlong (EXT_CSQC)
-static void VM_CL_ReadLong (void)
+static void VM_CL_ReadLong (prvm_prog_t *prog)
 {
        VM_SAFEPARMCOUNT(0, VM_CL_ReadLong);
-       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadLong();
+       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadLong(&cl_message);
 }
 
 //#364 float() readcoord (EXT_CSQC)
-static void VM_CL_ReadCoord (void)
+static void VM_CL_ReadCoord (prvm_prog_t *prog)
 {
        VM_SAFEPARMCOUNT(0, VM_CL_ReadCoord);
-       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadCoord(cls.protocol);
+       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadCoord(&cl_message, cls.protocol);
 }
 
 //#365 float() readangle (EXT_CSQC)
-static void VM_CL_ReadAngle (void)
+static void VM_CL_ReadAngle (prvm_prog_t *prog)
 {
        VM_SAFEPARMCOUNT(0, VM_CL_ReadAngle);
-       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadAngle(cls.protocol);
+       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadAngle(&cl_message, cls.protocol);
 }
 
 //#366 string() readstring (EXT_CSQC)
-static void VM_CL_ReadString (void)
+static void VM_CL_ReadString (prvm_prog_t *prog)
 {
        VM_SAFEPARMCOUNT(0, VM_CL_ReadString);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(MSG_ReadString());
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));
 }
 
 //#367 float() readfloat (EXT_CSQC)
-static void VM_CL_ReadFloat (void)
+static void VM_CL_ReadFloat (prvm_prog_t *prog)
 {
        VM_SAFEPARMCOUNT(0, VM_CL_ReadFloat);
-       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadFloat();
+       PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadFloat(&cl_message);
 }
 
 //#501 string() readpicture (DP_CSQC_READWRITEPICTURE)
 extern cvar_t cl_readpicture_force;
-static void VM_CL_ReadPicture (void)
+static void VM_CL_ReadPicture (prvm_prog_t *prog)
 {
        const char *name;
        unsigned char *data;
        unsigned char *buf;
-       int size;
+       unsigned short size;
        int i;
        cachepic_t *pic;
 
        VM_SAFEPARMCOUNT(0, VM_CL_ReadPicture);
 
-       name = MSG_ReadString();
-       size = MSG_ReadShort();
+       name = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
+       size = (unsigned short) MSG_ReadShort(&cl_message);
 
        // check if a texture of that name exists
        // if yes, it is used and the data is discarded
        // if not, the (low quality) data is used to build a new texture, whose name will get returned
 
-       pic = Draw_CachePic_Flags (name, CACHEPICFLAG_NOTPERSISTENT);
+       pic = Draw_CachePic_Flags(name, CACHEPICFLAG_NOTPERSISTENT | CACHEPICFLAG_FAILONMISSING);
 
        if(size)
        {
-               if(pic->tex == r_texture_notexture)
-                       pic->tex = NULL; // don't overwrite the notexture by Draw_NewPic
-               if(pic->tex && !cl_readpicture_force.integer)
+               if (Draw_IsPicLoaded(pic) && !cl_readpicture_force.integer)
                {
                        // texture found and loaded
                        // skip over the jpeg as we don't need it
                        for(i = 0; i < size; ++i)
-                               (void) MSG_ReadByte();
+                               (void) MSG_ReadByte(&cl_message);
                }
                else
                {
                        // texture not found
                        // use the attached jpeg as texture
                        buf = (unsigned char *) Mem_Alloc(tempmempool, size);
-                       MSG_ReadBytes(size, buf);
+                       MSG_ReadBytes(&cl_message, size, buf);
                        data = JPEG_LoadImage_BGRA(buf, size, NULL);
                        Mem_Free(buf);
-                       Draw_NewPic(name, image_width, image_height, false, data);
+                       Draw_NewPic(name, image_width, image_height, data, TEXTYPE_BGRA, TEXF_CLAMP);
                        Mem_Free(data);
                }
        }
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(name);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, name);
 }
 
 //////////////////////////////////////////////////////////
 
-static void VM_CL_makestatic (void)
+static void VM_CL_makestatic (prvm_prog_t *prog)
 {
        prvm_edict_t *ent;
 
@@ -1597,12 +1754,12 @@ static void VM_CL_makestatic (void)
        ent = PRVM_G_EDICT(OFS_PARM0);
        if (ent == prog->edicts)
        {
-               VM_Warning("makestatic: can not modify world entity\n");
+               VM_Warning(prog, "makestatic: can not modify world entity\n");
                return;
        }
        if (ent->priv.server->free)
        {
-               VM_Warning("makestatic: can not modify free entity\n");
+               VM_Warning(prog, "makestatic: can not modify free entity\n");
                return;
        }
 
@@ -1638,9 +1795,12 @@ static void VM_CL_makestatic (void)
                renderflags = (int)PRVM_clientedictfloat(ent, renderflags);
                if (renderflags & RF_USEAXIS)
                {
-                       vec3_t left;
+                       vec3_t forward, left, up, origin;
+                       VectorCopy(PRVM_clientglobalvector(v_forward), forward);
                        VectorNegate(PRVM_clientglobalvector(v_right), left);
-                       Matrix4x4_FromVectors(&staticent->render.matrix, PRVM_clientglobalvector(v_forward), left, PRVM_clientglobalvector(v_up), PRVM_clientedictvector(ent, origin));
+                       VectorCopy(PRVM_clientglobalvector(v_up), up);
+                       VectorCopy(PRVM_clientedictvector(ent, origin), origin);
+                       Matrix4x4_FromVectors(&staticent->render.matrix, forward, left, up, origin);
                        Matrix4x4_Scale(&staticent->render.matrix, staticent->render.scale, 1);
                }
                else
@@ -1671,7 +1831,7 @@ static void VM_CL_makestatic (void)
                Con_Printf("Too many static entities");
 
 // throw the entity away now
-       PRVM_ED_Free (ent);
+       PRVM_ED_Free(prog, ent);
 }
 
 //=================================================================//
@@ -1685,63 +1845,69 @@ copies data from one entity to another
 copyentity(src, dst)
 =================
 */
-static void VM_CL_copyentity (void)
+static void VM_CL_copyentity (prvm_prog_t *prog)
 {
        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");
+               VM_Warning(prog, "copyentity: can not read world entity\n");
                return;
        }
        if (in->priv.server->free)
        {
-               VM_Warning("copyentity: can not read free entity\n");
+               VM_Warning(prog, "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");
+               VM_Warning(prog, "copyentity: can not modify world entity\n");
                return;
        }
        if (out->priv.server->free)
        {
-               VM_Warning("copyentity: can not modify free entity\n");
+               VM_Warning(prog, "copyentity: can not modify free entity\n");
                return;
        }
-       memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
+       memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
        CL_LinkEdict(out);
 }
 
 //=================================================================//
 
 // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
-static void VM_CL_effect (void)
+static void VM_CL_effect (prvm_prog_t *prog)
 {
+#if 1
+       Con_Printf("WARNING: VM_CL_effect not implemented\n"); // FIXME: this needs to take modelname not modelindex, the csqc defs has it as string and so it shall be
+#else
+       vec3_t org;
        VM_SAFEPARMCOUNT(5, VM_CL_effect);
-       CL_Effect(PRVM_G_VECTOR(OFS_PARM0), (int)PRVM_G_FLOAT(OFS_PARM1), (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
+       CL_Effect(org, (int)PRVM_G_FLOAT(OFS_PARM1), (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
+#endif
 }
 
 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
-static void VM_CL_te_blood (void)
+static void VM_CL_te_blood (prvm_prog_t *prog)
 {
-       float   *pos;
-       vec3_t  pos2;
+       vec3_t pos, vel, pos2;
        VM_SAFEPARMCOUNT(3, VM_CL_te_blood);
        if (PRVM_G_FLOAT(OFS_PARM2) < 1)
                return;
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), vel);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
+       CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, vel, vel, NULL, 0);
 }
 
 // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
-static void VM_CL_te_bloodshower (void)
+static void VM_CL_te_bloodshower (prvm_prog_t *prog)
 {
        vec_t speed;
-       vec3_t vel1, vel2;
+       vec3_t mincorner, maxcorner, vel1, vel2;
        VM_SAFEPARMCOUNT(4, VM_CL_te_bloodshower);
        if (PRVM_G_FLOAT(OFS_PARM3) < 1)
                return;
@@ -1752,17 +1918,19 @@ static void VM_CL_te_bloodshower (void)
        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);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), mincorner);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), maxcorner);
+       CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM3), mincorner, maxcorner, vel1, vel2, NULL, 0);
 }
 
 // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
-static void VM_CL_te_explosionrgb (void)
+static void VM_CL_te_explosionrgb (prvm_prog_t *prog)
 {
-       float           *pos;
+       vec3_t          pos;
        vec3_t          pos2;
        matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(2, VM_CL_te_explosionrgb);
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 10);
        CL_ParticleExplosion(pos2);
        Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
@@ -1770,48 +1938,59 @@ static void VM_CL_te_explosionrgb (void)
 }
 
 // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
-static void VM_CL_te_particlecube (void)
+static void VM_CL_te_particlecube (prvm_prog_t *prog)
 {
+       vec3_t mincorner, maxcorner, vel;
        VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube);
-       CL_ParticleCube(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), PRVM_G_FLOAT(OFS_PARM5), PRVM_G_FLOAT(OFS_PARM6));
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), mincorner);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), maxcorner);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
+       CL_ParticleCube(mincorner, maxcorner, vel, (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)
-static void VM_CL_te_particlerain (void)
+static void VM_CL_te_particlerain (prvm_prog_t *prog)
 {
+       vec3_t mincorner, maxcorner, vel;
        VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain);
-       CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), mincorner);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), maxcorner);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
+       CL_ParticleRain(mincorner, maxcorner, vel, (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)
-static void VM_CL_te_particlesnow (void)
+static void VM_CL_te_particlesnow (prvm_prog_t *prog)
 {
+       vec3_t mincorner, maxcorner, vel;
        VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow);
-       CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 1);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), mincorner);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), maxcorner);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
+       CL_ParticleRain(mincorner, maxcorner, vel, (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 1);
 }
 
 // #411 void(vector org, vector vel, float howmany) te_spark
-static void VM_CL_te_spark (void)
+static void VM_CL_te_spark (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t pos, pos2, vel;
        VM_SAFEPARMCOUNT(3, VM_CL_te_spark);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), vel);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       CL_ParticleEffect(EFFECT_TE_SPARK, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
+       CL_ParticleEffect(EFFECT_TE_SPARK, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, vel, vel, NULL, 0);
 }
 
 extern cvar_t cl_sound_ric_gunshot;
 // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
-static void VM_CL_te_gunshotquad (void)
+static void VM_CL_te_gunshotquad (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t          pos, pos2;
        int                     rnd;
        VM_SAFEPARMCOUNT(1, VM_CL_te_gunshotquad);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 4);
        CL_ParticleEffect(EFFECT_TE_GUNSHOTQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        if(cl_sound_ric_gunshot.integer >= 2)
@@ -1828,14 +2007,13 @@ static void VM_CL_te_gunshotquad (void)
 }
 
 // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
-static void VM_CL_te_spikequad (void)
+static void VM_CL_te_spikequad (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t          pos, pos2;
        int                     rnd;
        VM_SAFEPARMCOUNT(1, VM_CL_te_spikequad);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 4);
        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);
@@ -1849,14 +2027,13 @@ static void VM_CL_te_spikequad (void)
 }
 
 // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
-static void VM_CL_te_superspikequad (void)
+static void VM_CL_te_superspikequad (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t          pos, pos2;
        int                     rnd;
        VM_SAFEPARMCOUNT(1, VM_CL_te_superspikequad);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 4);
        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);
@@ -1870,53 +2047,49 @@ static void VM_CL_te_superspikequad (void)
 }
 
 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
-static void VM_CL_te_explosionquad (void)
+static void VM_CL_te_explosionquad (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t          pos, pos2;
        VM_SAFEPARMCOUNT(1, VM_CL_te_explosionquad);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 10);
        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)
-static void VM_CL_te_smallflash (void)
+static void VM_CL_te_smallflash (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t          pos, pos2;
        VM_SAFEPARMCOUNT(1, VM_CL_te_smallflash);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 10);
        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)
-static void VM_CL_te_customflash (void)
+static void VM_CL_te_customflash (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t          pos, pos2;
        matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(4, VM_CL_te_customflash);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 4);
        Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
        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)
-static void VM_CL_te_gunshot (void)
+static void VM_CL_te_gunshot (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t          pos, pos2;
        int                     rnd;
        VM_SAFEPARMCOUNT(1, VM_CL_te_gunshot);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 4);
        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)
@@ -1933,14 +2106,13 @@ static void VM_CL_te_gunshot (void)
 }
 
 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_spike (void)
+static void VM_CL_te_spike (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t          pos, pos2;
        int                     rnd;
        VM_SAFEPARMCOUNT(1, VM_CL_te_spike);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 4);
        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);
@@ -1954,14 +2126,13 @@ static void VM_CL_te_spike (void)
 }
 
 // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_superspike (void)
+static void VM_CL_te_superspike (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t          pos, pos2;
        int                     rnd;
        VM_SAFEPARMCOUNT(1, VM_CL_te_superspike);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 4);
        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);
@@ -1975,82 +2146,81 @@ static void VM_CL_te_superspike (void)
 }
 
 // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_explosion (void)
+static void VM_CL_te_explosion (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t          pos, pos2;
        VM_SAFEPARMCOUNT(1, VM_CL_te_explosion);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 10);
        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)
-static void VM_CL_te_tarexplosion (void)
+static void VM_CL_te_tarexplosion (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t          pos, pos2;
        VM_SAFEPARMCOUNT(1, VM_CL_te_tarexplosion);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 10);
        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)
-static void VM_CL_te_wizspike (void)
+static void VM_CL_te_wizspike (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t          pos, pos2;
        VM_SAFEPARMCOUNT(1, VM_CL_te_wizspike);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 4);
        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)
-static void VM_CL_te_knightspike (void)
+static void VM_CL_te_knightspike (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t          pos, pos2;
        VM_SAFEPARMCOUNT(1, VM_CL_te_knightspike);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 4);
        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)
-static void VM_CL_te_lavasplash (void)
+static void VM_CL_te_lavasplash (prvm_prog_t *prog)
 {
+       vec3_t          pos;
        VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash);
-       CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
+       CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
 }
 
 // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_teleport (void)
+static void VM_CL_te_teleport (prvm_prog_t *prog)
 {
+       vec3_t          pos;
        VM_SAFEPARMCOUNT(1, VM_CL_te_teleport);
-       CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
+       CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
 }
 
 // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_explosion2 (void)
+static void VM_CL_te_explosion2 (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2, color;
+       vec3_t          pos, pos2, color;
        matrix4x4_t     tempmatrix;
        int                     colorStart, colorLength;
        unsigned char           *tempcolor;
        VM_SAFEPARMCOUNT(3, VM_CL_te_explosion2);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        colorStart = (int)PRVM_G_FLOAT(OFS_PARM1);
        colorLength = (int)PRVM_G_FLOAT(OFS_PARM2);
        CL_FindNonSolidLocation(pos, pos2, 10);
@@ -2066,61 +2236,72 @@ static void VM_CL_te_explosion2 (void)
 
 
 // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_lightning1 (void)
+static void VM_CL_te_lightning1 (prvm_prog_t *prog)
 {
+       vec3_t          start, end;
        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);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), start);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM2), end);
+       CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), start, end, cl.model_bolt, true);
 }
 
 // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_lightning2 (void)
+static void VM_CL_te_lightning2 (prvm_prog_t *prog)
 {
+       vec3_t          start, end;
        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);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), start);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM2), end);
+       CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), start, end, cl.model_bolt2, true);
 }
 
 // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_lightning3 (void)
+static void VM_CL_te_lightning3 (prvm_prog_t *prog)
 {
+       vec3_t          start, end;
        VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3);
-       CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), start);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM2), end);
+       CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), start, end, cl.model_bolt3, false);
 }
 
 // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_beam (void)
+static void VM_CL_te_beam (prvm_prog_t *prog)
 {
+       vec3_t          start, end;
        VM_SAFEPARMCOUNT(3, VM_CL_te_beam);
-       CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), start);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM2), end);
+       CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), start, end, cl.model_beam, false);
 }
 
 // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
-static void VM_CL_te_plasmaburn (void)
+static void VM_CL_te_plasmaburn (prvm_prog_t *prog)
 {
-       float           *pos;
-       vec3_t          pos2;
+       vec3_t          pos, pos2;
        VM_SAFEPARMCOUNT(1, VM_CL_te_plasmaburn);
 
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
        CL_FindNonSolidLocation(pos, pos2, 4);
        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)
+static void VM_CL_te_flamejet (prvm_prog_t *prog)
 {
-       float *pos;
-       vec3_t pos2;
+       vec3_t          pos, pos2, vel;
        VM_SAFEPARMCOUNT(3, VM_CL_te_flamejet);
        if (PRVM_G_FLOAT(OFS_PARM2) < 1)
                return;
-       pos = PRVM_G_VECTOR(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), vel);
        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);
+       CL_ParticleEffect(EFFECT_TE_FLAMEJET, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, vel, vel, NULL, 0);
 }
 
 
 // #443 void(entity e, entity tagentity, string tagname) setattachment
-void VM_CL_setattachment (void)
+static void VM_CL_setattachment (prvm_prog_t *prog)
 {
        prvm_edict_t *e;
        prvm_edict_t *tagentity;
@@ -2136,12 +2317,12 @@ void VM_CL_setattachment (void)
 
        if (e == prog->edicts)
        {
-               VM_Warning("setattachment: can not modify world entity\n");
+               VM_Warning(prog, "setattachment: can not modify world entity\n");
                return;
        }
        if (e->priv.server->free)
        {
-               VM_Warning("setattachment: can not modify free entity\n");
+               VM_Warning(prog, "setattachment: can not modify free entity\n");
                return;
        }
 
@@ -2170,7 +2351,7 @@ void VM_CL_setattachment (void)
 /////////////////////////////////////////
 // DP_MD3_TAGINFO extension coded by VorteX
 
-int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
+static int CL_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
 {
        dp_model_t *model = CL_GetModelFromEdict(e);
        if (model)
@@ -2179,7 +2360,7 @@ int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
                return -1;
 }
 
-int CL_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
+static int CL_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
 {
        int r;
        dp_model_t *model;
@@ -2203,7 +2384,7 @@ int CL_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, cons
        return 1;
 }
 
-int CL_GetPitchSign(prvm_edict_t *ent)
+int CL_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent)
 {
        dp_model_t *model;
        if ((model = CL_GetModelFromEdict(ent)) && model->type == mod_alias)
@@ -2211,7 +2392,7 @@ int CL_GetPitchSign(prvm_edict_t *ent)
        return 1;
 }
 
-void CL_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
+void CL_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
 {
        float scale;
        float pitchsign = 1;
@@ -2236,21 +2417,21 @@ void CL_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatri
        }
        else
        {
-               pitchsign = CL_GetPitchSign(ent);
+               pitchsign = CL_GetPitchSign(prog, ent);
                Matrix4x4_CreateFromQuakeEntity(out, PRVM_clientedictvector(ent, origin)[0], PRVM_clientedictvector(ent, origin)[1], PRVM_clientedictvector(ent, origin)[2], pitchsign * PRVM_clientedictvector(ent, angles)[0], PRVM_clientedictvector(ent, angles)[1], PRVM_clientedictvector(ent, angles)[2], scale);
        }
 }
 
-int CL_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
+static int CL_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
 {
        dp_model_t *model;
        if (tagindex >= 0
         && (model = CL_GetModelFromEdict(ent))
         && model->animscenes)
        {
-               VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
-               VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
-               VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
+               VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
+               VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, cl.time);
+               VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
                return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
        }
        *out = identitymatrix;
@@ -2267,12 +2448,13 @@ int CL_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out
 extern cvar_t cl_bob;
 extern cvar_t cl_bobcycle;
 extern cvar_t cl_bobup;
-int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
+int CL_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex, prvm_vec_t *returnshadingorigin)
 {
        int ret;
        int attachloop;
        matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
        dp_model_t *model;
+       vec3_t shadingorigin;
 
        *out = identitymatrix; // warnings and errors return identical matrix
 
@@ -2293,10 +2475,10 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                        return 5;
                // apply transformation by child's tagindex on parent entity and then
                // by parent entity itself
-               ret = CL_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
+               ret = CL_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
                if(ret && attachloop == 0)
                        return ret;
-               CL_GetEntityMatrix(ent, &entitymatrix, false);
+               CL_GetEntityMatrix(prog, ent, &entitymatrix, false);
                Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
                Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
                // next iteration we process the parent entity
@@ -2315,7 +2497,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
        {
                Matrix4x4_Copy(&tagmatrix, out);
 
-               CL_GetEntityMatrix(prog->edicts, &entitymatrix, true);
+               CL_GetEntityMatrix(prog, prog->edicts, &entitymatrix, true);
                Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
 
                /*
@@ -2340,12 +2522,22 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                        Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
                }
                */
+
+               // return the origin of the view
+               Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, shadingorigin);
+       }
+       else
+       {
+               // return the origin of the root entity in the chain
+               Matrix4x4_OriginFromMatrix(out, shadingorigin);
        }
+       if (returnshadingorigin)
+               VectorCopy(shadingorigin, returnshadingorigin);
        return 0;
 }
 
 // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
-void VM_CL_gettagindex (void)
+static void VM_CL_gettagindex (prvm_prog_t *prog)
 {
        prvm_edict_t *ent;
        const char *tag_name;
@@ -2357,12 +2549,12 @@ void VM_CL_gettagindex (void)
        tag_name = PRVM_G_STRING(OFS_PARM1);
        if (ent == prog->edicts)
        {
-               VM_Warning("VM_CL_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
+               VM_Warning(prog, "VM_CL_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
                return;
        }
        if (ent->priv.server->free)
        {
-               VM_Warning("VM_CL_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
+               VM_Warning(prog, "VM_CL_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
                return;
        }
 
@@ -2371,15 +2563,16 @@ void VM_CL_gettagindex (void)
                Con_DPrintf("VM_CL_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
        else
        {
-               tag_index = CL_GetTagIndex(ent, tag_name);
+               tag_index = CL_GetTagIndex(prog, ent, tag_name);
                if (tag_index == 0)
-                       Con_DPrintf("VM_CL_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
+                       if(developer_extra.integer)
+                               Con_DPrintf("VM_CL_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
        }
        PRVM_G_FLOAT(OFS_RETURN) = tag_index;
 }
 
 // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
-void VM_CL_gettaginfo (void)
+static void VM_CL_gettaginfo (prvm_prog_t *prog)
 {
        prvm_edict_t *e;
        int tagindex;
@@ -2388,37 +2581,40 @@ void VM_CL_gettaginfo (void)
        int parentindex;
        const char *tagname;
        int returncode;
-       vec3_t fo, le, up, trans;
+       vec3_t forward, left, up, origin;
        const dp_model_t *model;
 
        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, PRVM_clientglobalvector(v_forward), le, PRVM_clientglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
-       VectorScale(le, -1, PRVM_clientglobalvector(v_right));
+       returncode = CL_GetTagMatrix(prog, &tag_matrix, e, tagindex, NULL);
+       Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
+       VectorCopy(forward, PRVM_clientglobalvector(v_forward));
+       VectorScale(left, -1, PRVM_clientglobalvector(v_right));
+       VectorCopy(up, PRVM_clientglobalvector(v_up));
+       VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
        model = CL_GetModelFromEdict(e);
-       VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
-       VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
-       VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
-       CL_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
-       Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
+       VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
+       VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, cl.time);
+       VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
+       CL_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
+       Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
 
        PRVM_clientglobalfloat(gettaginfo_parent) = parentindex;
-       PRVM_clientglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(tagname) : 0;
-       VectorCopy(trans, PRVM_clientglobalvector(gettaginfo_offset));
-       VectorCopy(fo, PRVM_clientglobalvector(gettaginfo_forward));
-       VectorScale(le, -1, PRVM_clientglobalvector(gettaginfo_right));
+       PRVM_clientglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
+       VectorCopy(forward, PRVM_clientglobalvector(gettaginfo_forward));
+       VectorScale(left, -1, PRVM_clientglobalvector(gettaginfo_right));
        VectorCopy(up, PRVM_clientglobalvector(gettaginfo_up));
+       VectorCopy(origin, PRVM_clientglobalvector(gettaginfo_offset));
 
        switch(returncode)
        {
                case 1:
-                       VM_Warning("gettagindex: can't affect world entity\n");
+                       VM_Warning(prog, "gettagindex: can't affect world entity\n");
                        break;
                case 2:
-                       VM_Warning("gettagindex: can't affect free entity\n");
+                       VM_Warning(prog, "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));
@@ -2481,41 +2677,12 @@ typedef struct vmparticlespawner_s
        qboolean                        verified;
        vmparticletheme_t       *themes;
        int                                     max_themes;
-       // global addresses
-       float *particle_type;
-       float *particle_blendmode; 
-       float *particle_orientation;
-       float *particle_color1;
-       float *particle_color2;
-       float *particle_tex;
-       float *particle_size;
-       float *particle_sizeincrease;
-       float *particle_alpha;
-       float *particle_alphafade;
-       float *particle_time;
-       float *particle_gravity;
-       float *particle_bounce;
-       float *particle_airfriction;
-       float *particle_liquidfriction;
-       float *particle_originjitter;
-       float *particle_velocityjitter;
-       float *particle_qualityreduction;
-       float *particle_stretch;
-       float *particle_staincolor1;
-       float *particle_staincolor2;
-       float *particle_stainalpha;
-       float *particle_stainsize;
-       float *particle_staintex;
-       float *particle_delayspawn;
-       float *particle_delaycollision;
-       float *particle_angle;
-       float *particle_spin;
 }vmparticlespawner_t;
 
 vmparticlespawner_t vmpartspawner;
 
 // TODO: automatic max_themes grow
-static void VM_InitParticleSpawner (int maxthemes)
+static void VM_InitParticleSpawner (prvm_prog_t *prog, int maxthemes)
 {
        // bound max themes to not be an insane value
        if (maxthemes < 4)
@@ -2533,38 +2700,6 @@ static void VM_InitParticleSpawner (int maxthemes)
        vmpartspawner.max_themes = maxthemes;
        vmpartspawner.initialized = true;
        vmpartspawner.verified = true;
-       // get field addresses for fast querying (we can do 1000 calls of spawnparticle in a frame)
-       vmpartspawner.particle_type = &PRVM_clientglobalfloat(particle_type);
-       vmpartspawner.particle_blendmode = &PRVM_clientglobalfloat(particle_blendmode);
-       vmpartspawner.particle_orientation = &PRVM_clientglobalfloat(particle_orientation);
-       vmpartspawner.particle_color1 = PRVM_clientglobalvector(particle_color1);
-       vmpartspawner.particle_color2 = PRVM_clientglobalvector(particle_color2);
-       vmpartspawner.particle_tex = &PRVM_clientglobalfloat(particle_tex);
-       vmpartspawner.particle_size = &PRVM_clientglobalfloat(particle_size);
-       vmpartspawner.particle_sizeincrease = &PRVM_clientglobalfloat(particle_sizeincrease);
-       vmpartspawner.particle_alpha = &PRVM_clientglobalfloat(particle_alpha);
-       vmpartspawner.particle_alphafade = &PRVM_clientglobalfloat(particle_alphafade);
-       vmpartspawner.particle_time = &PRVM_clientglobalfloat(particle_time);
-       vmpartspawner.particle_gravity = &PRVM_clientglobalfloat(particle_gravity);
-       vmpartspawner.particle_bounce = &PRVM_clientglobalfloat(particle_bounce);
-       vmpartspawner.particle_airfriction = &PRVM_clientglobalfloat(particle_airfriction);
-       vmpartspawner.particle_liquidfriction = &PRVM_clientglobalfloat(particle_liquidfriction);
-       vmpartspawner.particle_originjitter = &PRVM_clientglobalfloat(particle_originjitter);
-       vmpartspawner.particle_velocityjitter = &PRVM_clientglobalfloat(particle_velocityjitter);
-       vmpartspawner.particle_qualityreduction = &PRVM_clientglobalfloat(particle_qualityreduction);
-       vmpartspawner.particle_stretch = &PRVM_clientglobalfloat(particle_stretch);
-       vmpartspawner.particle_staincolor1 = PRVM_clientglobalvector(particle_staincolor1);
-       vmpartspawner.particle_staincolor2 = PRVM_clientglobalvector(particle_staincolor2);
-       vmpartspawner.particle_stainalpha = &PRVM_clientglobalfloat(particle_stainalpha);
-       vmpartspawner.particle_stainsize = &PRVM_clientglobalfloat(particle_stainsize);
-       vmpartspawner.particle_staintex = &PRVM_clientglobalfloat(particle_staintex);
-       vmpartspawner.particle_staintex = &PRVM_clientglobalfloat(particle_staintex);
-       vmpartspawner.particle_delayspawn = &PRVM_clientglobalfloat(particle_delayspawn);
-       vmpartspawner.particle_delaycollision = &PRVM_clientglobalfloat(particle_delaycollision);
-       vmpartspawner.particle_angle = &PRVM_clientglobalfloat(particle_angle);
-       vmpartspawner.particle_spin = &PRVM_clientglobalfloat(particle_spin);
-       #undef getglobal
-       #undef getglobalvector
 }
 
 // reset particle theme to default values
@@ -2600,140 +2735,133 @@ static void VM_ResetParticleTheme (vmparticletheme_t *theme)
 }
 
 // particle theme -> QC globals
-void VM_CL_ParticleThemeToGlobals(vmparticletheme_t *theme)
-{
-       *vmpartspawner.particle_type = theme->typeindex;
-       *vmpartspawner.particle_blendmode = theme->blendmode;
-       *vmpartspawner.particle_orientation = theme->orientation;
-       vmpartspawner.particle_color1[0] = (theme->color1 >> 16) & 0xFF; // VorteX: int only can store 0-255, not 0-256 which means 0 - 0,99609375...
-       vmpartspawner.particle_color1[1] = (theme->color1 >> 8) & 0xFF;
-       vmpartspawner.particle_color1[2] = (theme->color1 >> 0) & 0xFF;
-       vmpartspawner.particle_color2[0] = (theme->color2 >> 16) & 0xFF;
-       vmpartspawner.particle_color2[1] = (theme->color2 >> 8) & 0xFF;
-       vmpartspawner.particle_color2[2] = (theme->color2 >> 0) & 0xFF;
-       *vmpartspawner.particle_tex = (float)theme->tex;
-       *vmpartspawner.particle_size = theme->size;
-       *vmpartspawner.particle_sizeincrease = theme->sizeincrease;
-       *vmpartspawner.particle_alpha = theme->alpha/256;
-       *vmpartspawner.particle_alphafade = theme->alphafade/256;
-       *vmpartspawner.particle_time = theme->lifetime;
-       *vmpartspawner.particle_gravity = theme->gravity;
-       *vmpartspawner.particle_bounce = theme->bounce;
-       *vmpartspawner.particle_airfriction = theme->airfriction;
-       *vmpartspawner.particle_liquidfriction = theme->liquidfriction;
-       *vmpartspawner.particle_originjitter = theme->originjitter;
-       *vmpartspawner.particle_velocityjitter = theme->velocityjitter;
-       *vmpartspawner.particle_qualityreduction = theme->qualityreduction;
-       *vmpartspawner.particle_stretch = theme->stretch;
-       vmpartspawner.particle_staincolor1[0] = ((int)theme->staincolor1 >> 16) & 0xFF;
-       vmpartspawner.particle_staincolor1[1] = ((int)theme->staincolor1 >> 8) & 0xFF;
-       vmpartspawner.particle_staincolor1[2] = ((int)theme->staincolor1 >> 0) & 0xFF;
-       vmpartspawner.particle_staincolor2[0] = ((int)theme->staincolor2 >> 16) & 0xFF;
-       vmpartspawner.particle_staincolor2[1] = ((int)theme->staincolor2 >> 8) & 0xFF;
-       vmpartspawner.particle_staincolor2[2] = ((int)theme->staincolor2 >> 0) & 0xFF;
-       *vmpartspawner.particle_staintex = (float)theme->staintex;
-       *vmpartspawner.particle_stainalpha = (float)theme->stainalpha/256;
-       *vmpartspawner.particle_stainsize = (float)theme->stainsize;
-       *vmpartspawner.particle_delayspawn = theme->delayspawn;
-       *vmpartspawner.particle_delaycollision = theme->delaycollision;
-       *vmpartspawner.particle_angle = theme->angle;
-       *vmpartspawner.particle_spin = theme->spin;
+static void VM_CL_ParticleThemeToGlobals(vmparticletheme_t *theme, prvm_prog_t *prog)
+{
+       PRVM_clientglobalfloat(particle_type) = theme->typeindex;
+       PRVM_clientglobalfloat(particle_blendmode) = theme->blendmode;
+       PRVM_clientglobalfloat(particle_orientation) = theme->orientation;
+       // VorteX: int only can store 0-255, not 0-256 which means 0 - 0,99609375...
+       VectorSet(PRVM_clientglobalvector(particle_color1), (theme->color1 >> 16) & 0xFF, (theme->color1 >> 8) & 0xFF, (theme->color1 >> 0) & 0xFF);
+       VectorSet(PRVM_clientglobalvector(particle_color2), (theme->color2 >> 16) & 0xFF, (theme->color2 >> 8) & 0xFF, (theme->color2 >> 0) & 0xFF);
+       PRVM_clientglobalfloat(particle_tex) = (prvm_vec_t)theme->tex;
+       PRVM_clientglobalfloat(particle_size) = theme->size;
+       PRVM_clientglobalfloat(particle_sizeincrease) = theme->sizeincrease;
+       PRVM_clientglobalfloat(particle_alpha) = theme->alpha/256;
+       PRVM_clientglobalfloat(particle_alphafade) = theme->alphafade/256;
+       PRVM_clientglobalfloat(particle_time) = theme->lifetime;
+       PRVM_clientglobalfloat(particle_gravity) = theme->gravity;
+       PRVM_clientglobalfloat(particle_bounce) = theme->bounce;
+       PRVM_clientglobalfloat(particle_airfriction) = theme->airfriction;
+       PRVM_clientglobalfloat(particle_liquidfriction) = theme->liquidfriction;
+       PRVM_clientglobalfloat(particle_originjitter) = theme->originjitter;
+       PRVM_clientglobalfloat(particle_velocityjitter) = theme->velocityjitter;
+       PRVM_clientglobalfloat(particle_qualityreduction) = theme->qualityreduction;
+       PRVM_clientglobalfloat(particle_stretch) = theme->stretch;
+       VectorSet(PRVM_clientglobalvector(particle_staincolor1), ((int)theme->staincolor1 >> 16) & 0xFF, ((int)theme->staincolor1 >> 8) & 0xFF, ((int)theme->staincolor1 >> 0) & 0xFF);
+       VectorSet(PRVM_clientglobalvector(particle_staincolor2), ((int)theme->staincolor2 >> 16) & 0xFF, ((int)theme->staincolor2 >> 8) & 0xFF, ((int)theme->staincolor2 >> 0) & 0xFF);
+       PRVM_clientglobalfloat(particle_staintex) = (prvm_vec_t)theme->staintex;
+       PRVM_clientglobalfloat(particle_stainalpha) = (prvm_vec_t)theme->stainalpha/256;
+       PRVM_clientglobalfloat(particle_stainsize) = (prvm_vec_t)theme->stainsize;
+       PRVM_clientglobalfloat(particle_delayspawn) = theme->delayspawn;
+       PRVM_clientglobalfloat(particle_delaycollision) = theme->delaycollision;
+       PRVM_clientglobalfloat(particle_angle) = theme->angle;
+       PRVM_clientglobalfloat(particle_spin) = theme->spin;
 }
 
 // QC globals ->  particle theme
-void VM_CL_ParticleThemeFromGlobals(vmparticletheme_t *theme)
-{
-       theme->typeindex = (unsigned short)*vmpartspawner.particle_type;
-       theme->blendmode = (pblend_t)(int)*vmpartspawner.particle_blendmode;
-       theme->orientation = (porientation_t)(int)*vmpartspawner.particle_orientation;
-       theme->color1 = ((int)vmpartspawner.particle_color1[0] << 16) + ((int)vmpartspawner.particle_color1[1] << 8) + ((int)vmpartspawner.particle_color1[2]);
-       theme->color2 = ((int)vmpartspawner.particle_color2[0] << 16) + ((int)vmpartspawner.particle_color2[1] << 8) + ((int)vmpartspawner.particle_color2[2]);
-       theme->tex = (int)*vmpartspawner.particle_tex;
-       theme->size = *vmpartspawner.particle_size;
-       theme->sizeincrease = *vmpartspawner.particle_sizeincrease;
-       theme->alpha = *vmpartspawner.particle_alpha*256;
-       theme->alphafade = *vmpartspawner.particle_alphafade*256;
-       theme->lifetime = *vmpartspawner.particle_time;
-       theme->gravity = *vmpartspawner.particle_gravity;
-       theme->bounce = *vmpartspawner.particle_bounce;
-       theme->airfriction = *vmpartspawner.particle_airfriction;
-       theme->liquidfriction = *vmpartspawner.particle_liquidfriction;
-       theme->originjitter = *vmpartspawner.particle_originjitter;
-       theme->velocityjitter = *vmpartspawner.particle_velocityjitter;
-       theme->qualityreduction = (*vmpartspawner.particle_qualityreduction) ? true : false;
-       theme->stretch = *vmpartspawner.particle_stretch;
-       theme->staincolor1 = ((int)vmpartspawner.particle_staincolor1[0])*65536 + (int)(vmpartspawner.particle_staincolor1[1])*256 + (int)(vmpartspawner.particle_staincolor1[2]);
-       theme->staincolor2 = (int)(vmpartspawner.particle_staincolor2[0])*65536 + (int)(vmpartspawner.particle_staincolor2[1])*256 + (int)(vmpartspawner.particle_staincolor2[2]);
-       theme->staintex =(int)*vmpartspawner.particle_staintex;
-       theme->stainalpha = *vmpartspawner.particle_stainalpha*256;
-       theme->stainsize = *vmpartspawner.particle_stainsize;
-       theme->delayspawn = *vmpartspawner.particle_delayspawn;
-       theme->delaycollision = *vmpartspawner.particle_delaycollision;
-       theme->angle = *vmpartspawner.particle_angle;
-       theme->spin = *vmpartspawner.particle_spin;
+static void VM_CL_ParticleThemeFromGlobals(vmparticletheme_t *theme, prvm_prog_t *prog)
+{
+       theme->typeindex = (unsigned short)PRVM_clientglobalfloat(particle_type);
+       theme->blendmode = (pblend_t)(int)PRVM_clientglobalfloat(particle_blendmode);
+       theme->orientation = (porientation_t)(int)PRVM_clientglobalfloat(particle_orientation);
+       theme->color1 = ((int)PRVM_clientglobalvector(particle_color1)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color1)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color1)[2]);
+       theme->color2 = ((int)PRVM_clientglobalvector(particle_color2)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color2)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color2)[2]);
+       theme->tex = (int)PRVM_clientglobalfloat(particle_tex);
+       theme->size = PRVM_clientglobalfloat(particle_size);
+       theme->sizeincrease = PRVM_clientglobalfloat(particle_sizeincrease);
+       theme->alpha = PRVM_clientglobalfloat(particle_alpha)*256;
+       theme->alphafade = PRVM_clientglobalfloat(particle_alphafade)*256;
+       theme->lifetime = PRVM_clientglobalfloat(particle_time);
+       theme->gravity = PRVM_clientglobalfloat(particle_gravity);
+       theme->bounce = PRVM_clientglobalfloat(particle_bounce);
+       theme->airfriction = PRVM_clientglobalfloat(particle_airfriction);
+       theme->liquidfriction = PRVM_clientglobalfloat(particle_liquidfriction);
+       theme->originjitter = PRVM_clientglobalfloat(particle_originjitter);
+       theme->velocityjitter = PRVM_clientglobalfloat(particle_velocityjitter);
+       theme->qualityreduction = PRVM_clientglobalfloat(particle_qualityreduction) != 0 ? true : false;
+       theme->stretch = PRVM_clientglobalfloat(particle_stretch);
+       theme->staincolor1 = ((int)PRVM_clientglobalvector(particle_staincolor1)[0])*65536 + (int)(PRVM_clientglobalvector(particle_staincolor1)[1])*256 + (int)(PRVM_clientglobalvector(particle_staincolor1)[2]);
+       theme->staincolor2 = (int)(PRVM_clientglobalvector(particle_staincolor2)[0])*65536 + (int)(PRVM_clientglobalvector(particle_staincolor2)[1])*256 + (int)(PRVM_clientglobalvector(particle_staincolor2)[2]);
+       theme->staintex =(int)PRVM_clientglobalfloat(particle_staintex);
+       theme->stainalpha = PRVM_clientglobalfloat(particle_stainalpha)*256;
+       theme->stainsize = PRVM_clientglobalfloat(particle_stainsize);
+       theme->delayspawn = PRVM_clientglobalfloat(particle_delayspawn);
+       theme->delaycollision = PRVM_clientglobalfloat(particle_delaycollision);
+       theme->angle = PRVM_clientglobalfloat(particle_angle);
+       theme->spin = PRVM_clientglobalfloat(particle_spin);
 }
 
 // init particle spawner interface
 // # float(float max_themes) initparticlespawner
-void VM_CL_InitParticleSpawner (void)
+static void VM_CL_InitParticleSpawner (prvm_prog_t *prog)
 {
        VM_SAFEPARMCOUNTRANGE(0, 1, VM_CL_InitParticleSpawner);
-       VM_InitParticleSpawner((int)PRVM_G_FLOAT(OFS_PARM0));
+       VM_InitParticleSpawner(prog, (int)PRVM_G_FLOAT(OFS_PARM0));
        vmpartspawner.themes[0].initialized = true;
        VM_ResetParticleTheme(&vmpartspawner.themes[0]);
        PRVM_G_FLOAT(OFS_RETURN) = (vmpartspawner.verified == true) ? 1 : 0;
 }
 
 // void() resetparticle
-void VM_CL_ResetParticle (void)
+static void VM_CL_ResetParticle (prvm_prog_t *prog)
 {
        VM_SAFEPARMCOUNT(0, VM_CL_ResetParticle);
        if (vmpartspawner.verified == false)
        {
-               VM_Warning("VM_CL_ResetParticle: particle spawner not initialized\n");
+               VM_Warning(prog, "VM_CL_ResetParticle: particle spawner not initialized\n");
                return;
        }
-       VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]);
+       VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0], prog);
 }
 
 // void(float themenum) particletheme
-void VM_CL_ParticleTheme (void)
+static void VM_CL_ParticleTheme (prvm_prog_t *prog)
 {
        int themenum;
 
        VM_SAFEPARMCOUNT(1, VM_CL_ParticleTheme);
        if (vmpartspawner.verified == false)
        {
-               VM_Warning("VM_CL_ParticleTheme: particle spawner not initialized\n");
+               VM_Warning(prog, "VM_CL_ParticleTheme: particle spawner not initialized\n");
                return;
        }
        themenum = (int)PRVM_G_FLOAT(OFS_PARM0);
        if (themenum < 0 || themenum >= vmpartspawner.max_themes)
        {
-               VM_Warning("VM_CL_ParticleTheme: bad theme number %i\n", themenum);
-               VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]);
+               VM_Warning(prog, "VM_CL_ParticleTheme: bad theme number %i\n", themenum);
+               VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0], prog);
                return;
        }
        if (vmpartspawner.themes[themenum].initialized == false)
        {
-               VM_Warning("VM_CL_ParticleTheme: theme #%i not exists\n", themenum);
-               VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]);
+               VM_Warning(prog, "VM_CL_ParticleTheme: theme #%i not exists\n", themenum);
+               VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0], prog);
                return;
        }
        // load particle theme into globals
-       VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[themenum]);
+       VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[themenum], prog);
 }
 
 // float() saveparticletheme
 // void(float themenum) updateparticletheme
-void VM_CL_ParticleThemeSave (void)
+static void VM_CL_ParticleThemeSave (prvm_prog_t *prog)
 {
        int themenum;
 
        VM_SAFEPARMCOUNTRANGE(0, 1, VM_CL_ParticleThemeSave);
        if (vmpartspawner.verified == false)
        {
-               VM_Warning("VM_CL_ParticleThemeSave: particle spawner not initialized\n");
+               VM_Warning(prog, "VM_CL_ParticleThemeSave: particle spawner not initialized\n");
                return;
        }
        // allocate new theme, save it and return
@@ -2745,14 +2873,14 @@ void VM_CL_ParticleThemeSave (void)
                if (themenum >= vmpartspawner.max_themes)
                {
                        if (vmpartspawner.max_themes == 2048)
-                               VM_Warning("VM_CL_ParticleThemeSave: no free theme slots\n");
+                               VM_Warning(prog, "VM_CL_ParticleThemeSave: no free theme slots\n");
                        else
-                               VM_Warning("VM_CL_ParticleThemeSave: no free theme slots, try initparticlespawner() with highter max_themes\n");
+                               VM_Warning(prog, "VM_CL_ParticleThemeSave: no free theme slots, try initparticlespawner() with highter max_themes\n");
                        PRVM_G_FLOAT(OFS_RETURN) = -1;
                        return;
                }
                vmpartspawner.themes[themenum].initialized = true;
-               VM_CL_ParticleThemeFromGlobals(&vmpartspawner.themes[themenum]);
+               VM_CL_ParticleThemeFromGlobals(&vmpartspawner.themes[themenum], prog);
                PRVM_G_FLOAT(OFS_RETURN) = themenum;
                return;
        }
@@ -2760,35 +2888,35 @@ void VM_CL_ParticleThemeSave (void)
        themenum = (int)PRVM_G_FLOAT(OFS_PARM0);
        if (themenum < 0 || themenum >= vmpartspawner.max_themes)
        {
-               VM_Warning("VM_CL_ParticleThemeSave: bad theme number %i\n", themenum);
+               VM_Warning(prog, "VM_CL_ParticleThemeSave: bad theme number %i\n", themenum);
                return;
        }
        vmpartspawner.themes[themenum].initialized = true;
-       VM_CL_ParticleThemeFromGlobals(&vmpartspawner.themes[themenum]);
+       VM_CL_ParticleThemeFromGlobals(&vmpartspawner.themes[themenum], prog);
 }
 
 // void(float themenum) freeparticletheme
-void VM_CL_ParticleThemeFree (void)
+static void VM_CL_ParticleThemeFree (prvm_prog_t *prog)
 {
        int themenum;
 
        VM_SAFEPARMCOUNT(1, VM_CL_ParticleThemeFree);
        if (vmpartspawner.verified == false)
        {
-               VM_Warning("VM_CL_ParticleThemeFree: particle spawner not initialized\n");
+               VM_Warning(prog, "VM_CL_ParticleThemeFree: particle spawner not initialized\n");
                return;
        }
        themenum = (int)PRVM_G_FLOAT(OFS_PARM0);
        // check parms
        if (themenum <= 0 || themenum >= vmpartspawner.max_themes)
        {
-               VM_Warning("VM_CL_ParticleThemeFree: bad theme number %i\n", themenum);
+               VM_Warning(prog, "VM_CL_ParticleThemeFree: bad theme number %i\n", themenum);
                return;
        }
        if (vmpartspawner.themes[themenum].initialized == false)
        {
-               VM_Warning("VM_CL_ParticleThemeFree: theme #%i already freed\n", themenum);
-               VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]);
+               VM_Warning(prog, "VM_CL_ParticleThemeFree: theme #%i already freed\n", themenum);
+               VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0], prog);
                return;
        }
        // free theme
@@ -2798,9 +2926,9 @@ void VM_CL_ParticleThemeFree (void)
 
 // float(vector org, vector dir, [float theme]) particle
 // returns 0 if failed, 1 if succesful
-void VM_CL_SpawnParticle (void)
+static void VM_CL_SpawnParticle (prvm_prog_t *prog)
 {
-       float *org, *dir;
+       vec3_t org, dir;
        vmparticletheme_t *theme;
        particle_t *part;
        int themenum;
@@ -2808,37 +2936,103 @@ void VM_CL_SpawnParticle (void)
        VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_SpawnParticle2);
        if (vmpartspawner.verified == false)
        {
-               VM_Warning("VM_CL_SpawnParticle: particle spawner not initialized\n");
+               VM_Warning(prog, "VM_CL_SpawnParticle: particle spawner not initialized\n");
                PRVM_G_FLOAT(OFS_RETURN) = 0; 
                return;
        }
-       org = PRVM_G_VECTOR(OFS_PARM0);
-       dir = PRVM_G_VECTOR(OFS_PARM1);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
        
        if (prog->argc < 3) // global-set particle
        {
-               part = CL_NewParticle(org, (unsigned short)*vmpartspawner.particle_type, ((int)(vmpartspawner.particle_color1[0]) << 16) + ((int)(vmpartspawner.particle_color1[1]) << 8) + ((int)(vmpartspawner.particle_color1[2])), ((int)vmpartspawner.particle_color2[0] << 16) + ((int)vmpartspawner.particle_color2[1] << 8) + ((int)vmpartspawner.particle_color2[2]), (int)*vmpartspawner.particle_tex, *vmpartspawner.particle_size, *vmpartspawner.particle_sizeincrease, *vmpartspawner.particle_alpha*256, *vmpartspawner.particle_alphafade*256, *vmpartspawner.particle_gravity, *vmpartspawner.particle_bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], *vmpartspawner.particle_airfriction, *vmpartspawner.particle_liquidfriction, *vmpartspawner.particle_originjitter, *vmpartspawner.particle_velocityjitter, (*vmpartspawner.particle_qualityreduction) ? true : false, *vmpartspawner.particle_time, *vmpartspawner.particle_stretch, (pblend_t)(int)*vmpartspawner.particle_blendmode, (porientation_t)(int)*vmpartspawner.particle_orientation, (int)(vmpartspawner.particle_staincolor1[0])*65536 + (int)(vmpartspawner.particle_staincolor1[1])*256 + (int)(vmpartspawner.particle_staincolor1[2]), (int)(vmpartspawner.particle_staincolor2[0])*65536 + (int)(vmpartspawner.particle_staincolor2[1])*256 + (int)(vmpartspawner.particle_staincolor2[2]), (int)*vmpartspawner.particle_staintex, *vmpartspawner.particle_stainalpha*256, *vmpartspawner.particle_stainsize, *vmpartspawner.particle_angle, *vmpartspawner.particle_spin, NULL);
+               part = CL_NewParticle(org,
+                       (unsigned short)PRVM_clientglobalfloat(particle_type),
+                       ((int)PRVM_clientglobalvector(particle_color1)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color1)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color1)[2]),
+                       ((int)PRVM_clientglobalvector(particle_color2)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color2)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color2)[2]),
+                       (int)PRVM_clientglobalfloat(particle_tex),
+                       PRVM_clientglobalfloat(particle_size),
+                       PRVM_clientglobalfloat(particle_sizeincrease),
+                       PRVM_clientglobalfloat(particle_alpha)*256,
+                       PRVM_clientglobalfloat(particle_alphafade)*256,
+                       PRVM_clientglobalfloat(particle_gravity),
+                       PRVM_clientglobalfloat(particle_bounce),
+                       org[0],
+                       org[1],
+                       org[2],
+                       dir[0],
+                       dir[1],
+                       dir[2],
+                       PRVM_clientglobalfloat(particle_airfriction),
+                       PRVM_clientglobalfloat(particle_liquidfriction),
+                       PRVM_clientglobalfloat(particle_originjitter),
+                       PRVM_clientglobalfloat(particle_velocityjitter),
+                       (PRVM_clientglobalfloat(particle_qualityreduction)) ? true : false,
+                       PRVM_clientglobalfloat(particle_time),
+                       PRVM_clientglobalfloat(particle_stretch),
+                       (pblend_t)(int)PRVM_clientglobalfloat(particle_blendmode),
+                       (porientation_t)(int)PRVM_clientglobalfloat(particle_orientation),
+                       (int)(PRVM_clientglobalvector(particle_staincolor1)[0])*65536 + (int)(PRVM_clientglobalvector(particle_staincolor1)[1])*256 + (int)(PRVM_clientglobalvector(particle_staincolor1)[2]),
+                       (int)(PRVM_clientglobalvector(particle_staincolor2)[0])*65536 + (int)(PRVM_clientglobalvector(particle_staincolor2)[1])*256 + (int)(PRVM_clientglobalvector(particle_staincolor2)[2]),
+                       (int)PRVM_clientglobalfloat(particle_staintex),
+                       PRVM_clientglobalfloat(particle_stainalpha)*256,
+                       PRVM_clientglobalfloat(particle_stainsize),
+                       PRVM_clientglobalfloat(particle_angle),
+                       PRVM_clientglobalfloat(particle_spin),
+                       NULL);
                if (!part)
                {
                        PRVM_G_FLOAT(OFS_RETURN) = 0; 
                        return;
                }
-               if (*vmpartspawner.particle_delayspawn)
-                       part->delayedspawn = cl.time + *vmpartspawner.particle_delayspawn;
-               //if (*vmpartspawner.particle_delaycollision)
-               //      part->delayedcollisions = cl.time + *vmpartspawner.particle_delaycollision;
+               if (PRVM_clientglobalfloat(particle_delayspawn))
+                       part->delayedspawn = cl.time + PRVM_clientglobalfloat(particle_delayspawn);
+               //if (PRVM_clientglobalfloat(particle_delaycollision))
+               //      part->delayedcollisions = cl.time + PRVM_clientglobalfloat(particle_delaycollision);
        }
        else // quick themed particle
        {
                themenum = (int)PRVM_G_FLOAT(OFS_PARM2);
                if (themenum <= 0 || themenum >= vmpartspawner.max_themes)
                {
-                       VM_Warning("VM_CL_SpawnParticle: bad theme number %i\n", themenum);
+                       VM_Warning(prog, "VM_CL_SpawnParticle: bad theme number %i\n", themenum);
                        PRVM_G_FLOAT(OFS_RETURN) = 0; 
                        return;
                }
                theme = &vmpartspawner.themes[themenum];
-               part = CL_NewParticle(org, theme->typeindex, theme->color1, theme->color2, theme->tex, theme->size, theme->sizeincrease, theme->alpha, theme->alphafade, theme->gravity, theme->bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], theme->airfriction, theme->liquidfriction, theme->originjitter, theme->velocityjitter, theme->qualityreduction, theme->lifetime, theme->stretch, theme->blendmode, theme->orientation, theme->staincolor1, theme->staincolor2, theme->staintex, theme->stainalpha, theme->stainsize, theme->angle, theme->spin, NULL);
+               part = CL_NewParticle(org,
+                       theme->typeindex,
+                       theme->color1,
+                       theme->color2,
+                       theme->tex,
+                       theme->size,
+                       theme->sizeincrease,
+                       theme->alpha,
+                       theme->alphafade,
+                       theme->gravity,
+                       theme->bounce,
+                       org[0],
+                       org[1],
+                       org[2],
+                       dir[0],
+                       dir[1],
+                       dir[2],
+                       theme->airfriction,
+                       theme->liquidfriction,
+                       theme->originjitter,
+                       theme->velocityjitter,
+                       theme->qualityreduction,
+                       theme->lifetime,
+                       theme->stretch,
+                       theme->blendmode,
+                       theme->orientation,
+                       theme->staincolor1,
+                       theme->staincolor2,
+                       theme->staintex,
+                       theme->stainalpha,
+                       theme->stainsize,
+                       theme->angle,
+                       theme->spin,
+                       NULL);
                if (!part)
                {
                        PRVM_G_FLOAT(OFS_RETURN) = 0; 
@@ -2854,9 +3048,9 @@ void VM_CL_SpawnParticle (void)
 
 // float(vector org, vector dir, float spawndelay, float collisiondelay, [float theme]) delayedparticle
 // returns 0 if failed, 1 if success
-void VM_CL_SpawnParticleDelayed (void)
+static void VM_CL_SpawnParticleDelayed (prvm_prog_t *prog)
 {
-       float *org, *dir;
+       vec3_t org, dir;
        vmparticletheme_t *theme;
        particle_t *part;
        int themenum;
@@ -2864,25 +3058,91 @@ void VM_CL_SpawnParticleDelayed (void)
        VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_SpawnParticle2);
        if (vmpartspawner.verified == false)
        {
-               VM_Warning("VM_CL_SpawnParticle: particle spawner not initialized\n");
+               VM_Warning(prog, "VM_CL_SpawnParticle: particle spawner not initialized\n");
                PRVM_G_FLOAT(OFS_RETURN) = 0; 
                return;
        }
-       org = PRVM_G_VECTOR(OFS_PARM0);
-       dir = PRVM_G_VECTOR(OFS_PARM1);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
        if (prog->argc < 5) // global-set particle
-               part = CL_NewParticle(org, (unsigned short)*vmpartspawner.particle_type, ((int)vmpartspawner.particle_color1[0] << 16) + ((int)vmpartspawner.particle_color1[1] << 8) + ((int)vmpartspawner.particle_color1[2]), ((int)vmpartspawner.particle_color2[0] << 16) + ((int)vmpartspawner.particle_color2[1] << 8) + ((int)vmpartspawner.particle_color2[2]), (int)*vmpartspawner.particle_tex, *vmpartspawner.particle_size, *vmpartspawner.particle_sizeincrease, *vmpartspawner.particle_alpha*256, *vmpartspawner.particle_alphafade*256, *vmpartspawner.particle_gravity, *vmpartspawner.particle_bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], *vmpartspawner.particle_airfriction, *vmpartspawner.particle_liquidfriction, *vmpartspawner.particle_originjitter, *vmpartspawner.particle_velocityjitter, (*vmpartspawner.particle_qualityreduction) ? true : false, *vmpartspawner.particle_time, *vmpartspawner.particle_stretch, (pblend_t)(int)*vmpartspawner.particle_blendmode, (porientation_t)(int)*vmpartspawner.particle_orientation, ((int)vmpartspawner.particle_staincolor1[0] << 16) + ((int)vmpartspawner.particle_staincolor1[1] << 8) + ((int)vmpartspawner.particle_staincolor1[2]), ((int)vmpartspawner.particle_staincolor2[0] << 16) + ((int)vmpartspawner.particle_staincolor2[1] << 8) + ((int)vmpartspawner.particle_staincolor2[2]), (int)*vmpartspawner.particle_staintex, *vmpartspawner.particle_stainalpha*256, *vmpartspawner.particle_stainsize, *vmpartspawner.particle_angle, *vmpartspawner.particle_spin, NULL);
+               part = CL_NewParticle(org,
+                       (unsigned short)PRVM_clientglobalfloat(particle_type),
+                       ((int)PRVM_clientglobalvector(particle_color1)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color1)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color1)[2]),
+                       ((int)PRVM_clientglobalvector(particle_color2)[0] << 16) + ((int)PRVM_clientglobalvector(particle_color2)[1] << 8) + ((int)PRVM_clientglobalvector(particle_color2)[2]),
+                       (int)PRVM_clientglobalfloat(particle_tex),
+                       PRVM_clientglobalfloat(particle_size),
+                       PRVM_clientglobalfloat(particle_sizeincrease),
+                       PRVM_clientglobalfloat(particle_alpha)*256,
+                       PRVM_clientglobalfloat(particle_alphafade)*256,
+                       PRVM_clientglobalfloat(particle_gravity),
+                       PRVM_clientglobalfloat(particle_bounce),
+                       org[0],
+                       org[1],
+                       org[2],
+                       dir[0],
+                       dir[1],
+                       dir[2],
+                       PRVM_clientglobalfloat(particle_airfriction),
+                       PRVM_clientglobalfloat(particle_liquidfriction),
+                       PRVM_clientglobalfloat(particle_originjitter),
+                       PRVM_clientglobalfloat(particle_velocityjitter),
+                       (PRVM_clientglobalfloat(particle_qualityreduction)) ? true : false,
+                       PRVM_clientglobalfloat(particle_time),
+                       PRVM_clientglobalfloat(particle_stretch),
+                       (pblend_t)(int)PRVM_clientglobalfloat(particle_blendmode),
+                       (porientation_t)(int)PRVM_clientglobalfloat(particle_orientation),
+                       ((int)PRVM_clientglobalvector(particle_staincolor1)[0] << 16) + ((int)PRVM_clientglobalvector(particle_staincolor1)[1] << 8) + ((int)PRVM_clientglobalvector(particle_staincolor1)[2]),
+                       ((int)PRVM_clientglobalvector(particle_staincolor2)[0] << 16) + ((int)PRVM_clientglobalvector(particle_staincolor2)[1] << 8) + ((int)PRVM_clientglobalvector(particle_staincolor2)[2]),
+                       (int)PRVM_clientglobalfloat(particle_staintex),
+                       PRVM_clientglobalfloat(particle_stainalpha)*256,
+                       PRVM_clientglobalfloat(particle_stainsize),
+                       PRVM_clientglobalfloat(particle_angle),
+                       PRVM_clientglobalfloat(particle_spin),
+                       NULL);
        else // themed particle
        {
                themenum = (int)PRVM_G_FLOAT(OFS_PARM4);
                if (themenum <= 0 || themenum >= vmpartspawner.max_themes)
                {
-                       VM_Warning("VM_CL_SpawnParticle: bad theme number %i\n", themenum);
+                       VM_Warning(prog, "VM_CL_SpawnParticle: bad theme number %i\n", themenum);
                        PRVM_G_FLOAT(OFS_RETURN) = 0;  
                        return;
                }
                theme = &vmpartspawner.themes[themenum];
-               part = CL_NewParticle(org, theme->typeindex, theme->color1, theme->color2, theme->tex, theme->size, theme->sizeincrease, theme->alpha, theme->alphafade, theme->gravity, theme->bounce, org[0], org[1], org[2], dir[0], dir[1], dir[2], theme->airfriction, theme->liquidfriction, theme->originjitter, theme->velocityjitter, theme->qualityreduction, theme->lifetime, theme->stretch, theme->blendmode, theme->orientation, theme->staincolor1, theme->staincolor2, theme->staintex, theme->stainalpha, theme->stainsize, theme->angle, theme->spin, NULL);
+               part = CL_NewParticle(org,
+                       theme->typeindex,
+                       theme->color1,
+                       theme->color2,
+                       theme->tex,
+                       theme->size,
+                       theme->sizeincrease,
+                       theme->alpha,
+                       theme->alphafade,
+                       theme->gravity,
+                       theme->bounce,
+                       org[0],
+                       org[1],
+                       org[2],
+                       dir[0],
+                       dir[1],
+                       dir[2],
+                       theme->airfriction,
+                       theme->liquidfriction,
+                       theme->originjitter,
+                       theme->velocityjitter,
+                       theme->qualityreduction,
+                       theme->lifetime,
+                       theme->stretch,
+                       theme->blendmode,
+                       theme->orientation,
+                       theme->staincolor1,
+                       theme->staincolor2,
+                       theme->staintex,
+                       theme->stainalpha,
+                       theme->stainsize,
+                       theme->angle,
+                       theme->spin,
+                       NULL);
        }
        if (!part) 
        { 
@@ -2902,10 +3162,10 @@ void VM_CL_SpawnParticleDelayed (void)
 // vector(float entitynum, float whatfld) getentityvec;
 // querying engine-drawn entity
 // VorteX: currently it's only tested with whatfld = 1..7
-void VM_CL_GetEntity (void)
+static void VM_CL_GetEntity (prvm_prog_t *prog)
 {
        int entnum, fieldnum;
-       float org[3], v1[3], v2[3];
+       vec3_t forward, left, up, org;
        VM_SAFEPARMCOUNT(2, VM_CL_GetEntityVec);
 
        entnum = PRVM_G_FLOAT(OFS_PARM0);
@@ -2921,22 +3181,30 @@ void VM_CL_GetEntity (void)
                        PRVM_G_FLOAT(OFS_RETURN) = cl.entities_active[entnum];
                        break;
                case 1: // origin
-                       Matrix4x4_OriginFromMatrix(&cl.entities[entnum].render.matrix, PRVM_G_VECTOR(OFS_RETURN));
+                       Matrix4x4_OriginFromMatrix(&cl.entities[entnum].render.matrix, org);
+                       VectorCopy(org, PRVM_G_VECTOR(OFS_RETURN));
                        break; 
                case 2: // forward
-                       Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, PRVM_G_VECTOR(OFS_RETURN), v1, v2, org);        
+                       Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, forward, left, up, org);
+                       VectorCopy(forward, PRVM_G_VECTOR(OFS_RETURN));
                        break;
                case 3: // right
-                       Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, v1, PRVM_G_VECTOR(OFS_RETURN), v2, org);        
+                       Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, forward, left, up, org);
+                       VectorNegate(left, PRVM_G_VECTOR(OFS_RETURN));
                        break;
                case 4: // up
-                       Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, v1, v2, PRVM_G_VECTOR(OFS_RETURN), org);        
+                       Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, forward, left, up, org);
+                       VectorCopy(up, PRVM_G_VECTOR(OFS_RETURN));
                        break;
                case 5: // scale
                        PRVM_G_FLOAT(OFS_RETURN) = Matrix4x4_ScaleFromMatrix(&cl.entities[entnum].render.matrix);
                        break;  
                case 6: // origin + v_forward, v_right, v_up
-                       Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, PRVM_clientglobalvector(v_forward), PRVM_clientglobalvector(v_right), PRVM_clientglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));        
+                       Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, forward, left, up, org);
+                       VectorCopy(forward, PRVM_clientglobalvector(v_forward));
+                       VectorNegate(left, PRVM_clientglobalvector(v_right));
+                       VectorCopy(up, PRVM_clientglobalvector(v_up));
+                       VectorCopy(org, PRVM_G_VECTOR(OFS_RETURN));
                        break;  
                case 7: // alpha
                        PRVM_G_FLOAT(OFS_RETURN) = cl.entities[entnum].render.alpha;
@@ -2968,7 +3236,7 @@ void VM_CL_GetEntity (void)
                        VectorAdd(cl.entities[entnum].render.maxs, org, PRVM_G_VECTOR(OFS_RETURN));             
                        break;
                case 16: // light
-                       VectorMA(cl.entities[entnum].render.modellight_ambient, 0.5, cl.entities[entnum].render.modellight_diffuse, PRVM_G_VECTOR(OFS_RETURN));
+                       VectorMA(cl.entities[entnum].render.render_modellight_ambient, 0.5, cl.entities[entnum].render.render_modellight_diffuse, PRVM_G_VECTOR(OFS_RETURN));
                        break;  
                default:
                        PRVM_G_FLOAT(OFS_RETURN) = 0;
@@ -2980,393 +3248,128 @@ void VM_CL_GetEntity (void)
 //QC POLYGON functions
 //====================
 
-#define VMPOLYGONS_MAXPOINTS 64
-
-typedef struct vmpolygons_triangle_s
-{
-       rtexture_t              *texture;
-       int                             drawflag;
-       qboolean hasalpha;
-       unsigned short  elements[3];
-}vmpolygons_triangle_t;
-
-typedef struct vmpolygons_s
-{
-       mempool_t               *pool;
-       qboolean                initialized;
-       double          progstarttime;
-
-       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;
-       unsigned short  *data_sortedelement3s;
-
-       qboolean                begin_active;
-       int     begin_draw2d;
-       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];
-       qboolean                begin_texture_hasalpha;
-} vmpolygons_t;
-
-// FIXME: make VM_CL_R_Polygon functions use Debug_Polygon functions?
-vmpolygons_t vmpolygons[PRVM_MAXPROGS];
-
 //#304 void() renderscene (EXT_CSQC)
 // moved that here to reset the polygons,
 // resetting them earlier causes R_Mesh_Draw to be called with numvertices = 0
 // --blub
-void VM_CL_R_RenderScene (void)
+static void VM_CL_R_RenderScene (prvm_prog_t *prog)
 {
-       double t = Sys_DoubleTime();
-       vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+       qboolean ismain = r_refdef.view.ismain;
+       double t = Sys_DirtyTime();
        VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene);
 
+       // update the views
+       if(ismain)
+       {
+               // set the main view
+               csqc_main_r_refdef_view = r_refdef.view;
+       }
+
        // we need to update any RENDER_VIEWMODEL entities at this point because
        // csqc supplies its own view matrix
        CL_UpdateViewEntities();
+       CL_MeshEntities_AddToScene();
+       CL_UpdateEntityShading();
+
        // now draw stuff!
-       R_RenderView();
+       R_RenderView(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
 
-       polys->num_vertices = polys->num_triangles = 0;
-       polys->progstarttime = prog->starttime;
+       Mod_Mesh_Reset(CL_Mesh_CSQC());
 
        // callprofile fixing hack: do not include this time in what is counted for CSQC_UpdateView
-       prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= Sys_DoubleTime() - t;
-}
-
-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;
-       unsigned short *oldsortedelement3s = polys->data_sortedelement3s;
-       polys->max_vertices = min(polys->max_triangles*3, 65536);
-       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_sortedelement3s = (unsigned short *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(unsigned short[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_sortedelement3s, oldsortedelement3s, polys->num_triangles*sizeof(unsigned short[3]));
-       }
-       if (oldvertex3f)
-               Mem_Free(oldvertex3f);
-       if (oldcolor4f)
-               Mem_Free(oldcolor4f);
-       if (oldtexcoord2f)
-               Mem_Free(oldtexcoord2f);
-       if (oldtriangles)
-               Mem_Free(oldtriangles);
-       if (oldsortedelement3s)
-               Mem_Free(oldsortedelement3s);
-}
+       t = Sys_DirtyTime() - t;if (t < 0 || t >= 1800) t = 0;
+       prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= t;
 
-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;
-}
+       // polygonbegin without draw2d arg has to guess
+       prog->polygonbegin_guess2d = false;
 
-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();
-       if(polys->progstarttime != prog->starttime) // from other progs? won't draw these (this can cause crashes!)
-               return;
-//     R_Mesh_ResetTextureState();
-       R_EntityMatrix(&identitymatrix);
-       GL_CullFace(GL_NONE);
-       GL_DepthTest(true); // polys in 3D space shall always have depth test
-       GL_DepthRange(0, 1);
-       R_Mesh_PrepareVertices_Generic_Arrays(polys->num_vertices, polys->data_vertex3f, polys->data_color4f, polys->data_texcoord2f);
-
-       for (surfacelistindex = 0;surfacelistindex < numsurfaces;)
+       // update the views
+       if (ismain)
        {
-               int numtriangles = 0;
-               rtexture_t *tex = polys->data_triangles[surfacelist[surfacelistindex]].texture;
-               int drawflag = polys->data_triangles[surfacelist[surfacelistindex]].drawflag;
-               DrawQ_ProcessDrawFlag(drawflag, polys->data_triangles[surfacelist[surfacelistindex]].hasalpha);
-               R_SetupShader_Generic(tex, NULL, GL_MODULATE, 1, false, false);
-               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]].elements, polys->data_sortedelement3s + 3*numtriangles);
-                       numtriangles++;
-               }
-               R_Mesh_Draw(0, polys->num_vertices, 0, numtriangles, NULL, NULL, 0, polys->data_sortedelement3s, NULL, 0);
+               // clear the flags so no other view becomes "main" unless CSQC sets VF_MAINVIEW
+               r_refdef.view.ismain = false;
+               csqc_original_r_refdef_view.ismain = false;
        }
 }
 
-void VMPolygons_Store(vmpolygons_t *polys)
-{
-       qboolean hasalpha;
-       int i;
-
-       // detect if we have alpha
-       hasalpha = polys->begin_texture_hasalpha;
-       for(i = 0; !hasalpha && (i < polys->begin_vertices); ++i)
-               if(polys->begin_color[i][3] < 1)
-                       hasalpha = true;
-
-       if (polys->begin_draw2d)
-       {
-               // 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 = polygonelement3i;
-               mesh.data_element3s = polygonelement3s;
-               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, hasalpha);
-       }
-       else
-       {
-               // queue the polygon as 3D for sorted transparent rendering later
-               int i;
-               if (polys->max_triangles < polys->num_triangles + polys->begin_vertices-2)
-               {
-                       while (polys->max_triangles < polys->num_triangles + polys->begin_vertices-2)
-                               polys->max_triangles *= 2;
-                       VM_ResizePolygons(polys);
-               }
-               if (polys->num_vertices + polys->begin_vertices <= polys->max_vertices)
-               {
-                       // needle in a haystack!
-                       // polys->num_vertices was used for copying where we actually want to copy begin_vertices
-                       // that also caused it to not render the first polygon that is added
-                       // --blub
-                       memcpy(polys->data_vertex3f + polys->num_vertices * 3, polys->begin_vertex[0], polys->begin_vertices * sizeof(float[3]));
-                       memcpy(polys->data_color4f + polys->num_vertices * 4, polys->begin_color[0], polys->begin_vertices * sizeof(float[4]));
-                       memcpy(polys->data_texcoord2f + polys->num_vertices * 2, polys->begin_texcoord[0], polys->begin_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].elements[0] = polys->num_vertices;
-                               polys->data_triangles[polys->num_triangles].elements[1] = polys->num_vertices + i+1;
-                               polys->data_triangles[polys->num_triangles].elements[2] = polys->num_vertices + i+2;
-                               polys->data_triangles[polys->num_triangles].hasalpha = hasalpha;
-                               polys->num_triangles++;
-                       }
-                       polys->num_vertices += polys->begin_vertices;
-               }
-       }
-       polys->begin_active = false;
-}
-
-// 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;
-       vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
-       vec3_t center;
-
-       // only add polygons of the currently active prog to the queue - if there is none, we're done
-       if( !prog )
-               return;
-
-       if (!polys->num_triangles)
-               return;
-
-       for (i = 0;i < polys->num_triangles;i++)
-       {
-               VectorMAMAM(1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[0], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[1], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[2], center);
-               R_MeshQueue_AddTransparent(center, VM_DrawPolygonCallback, NULL, i, NULL);
-       }
-
-       /*polys->num_triangles = 0; // now done after rendering the scene,
-         polys->num_vertices = 0;  // otherwise it's not rendered at all and prints an error message --blub */
-}
-
 //void(string texturename, float flag[, float is2d]) R_BeginPolygon
-void VM_CL_R_PolygonBegin (void)
+static void VM_CL_R_PolygonBegin (prvm_prog_t *prog)
 {
-       const char              *picname;
-       skinframe_t     *sf;
-       vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
-       int tf;
-
-       // TODO instead of using skinframes here (which provides the benefit of
-       // better management of flags, and is more suited for 3D rendering), what
-       // about supporting Q3 shaders?
+       const char *texname;
+       int drawflags;
+       qboolean draw2d;
+       dp_model_t *mod;
 
        VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_R_PolygonBegin);
 
-       if (!polys->initialized)
-               VM_InitPolygons(polys);
-       if(polys->progstarttime != prog->starttime)
-       {
-               // from another progs? then reset the polys first (fixes crashes on map change, because that can make skinframe textures invalid)
-               polys->num_vertices = polys->num_triangles = 0;
-               polys->progstarttime = prog->starttime;
-       }
-       if (polys->begin_active)
-       {
-               VM_Warning("VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonBegin after first\n");
-               return;
-       }
-       picname = PRVM_G_STRING(OFS_PARM0);
-
-       sf = NULL;
-       if(*picname)
+       texname = PRVM_G_STRING(OFS_PARM0);
+       drawflags = (int)PRVM_G_FLOAT(OFS_PARM1);
+       if (prog->argc >= 3)
+               draw2d = PRVM_G_FLOAT(OFS_PARM2) != 0;
+       else
        {
-               tf = TEXF_ALPHA;
-               if((int)PRVM_G_FLOAT(OFS_PARM1) & DRAWFLAG_MIPMAP)
-                       tf |= TEXF_MIPMAP;
-
-               do
-               {
-                       sf = R_SkinFrame_FindNextByName(sf, picname);
-               }
-               while(sf && sf->textureflags != tf);
-
-               if(!sf || !sf->base)
-                       sf = R_SkinFrame_LoadExternal(picname, tf, true);
-
-               if(sf)
-                       R_SkinFrame_MarkUsed(sf);
+               // weird hacky way to figure out if this is a 2D HUD polygon or a scene
+               // polygon, for compatibility with mods aimed at old darkplaces versions
+               // - polygonbegin_guess2d is 0 if the most recent major call was
+               // clearscene, 1 if the most recent major call was drawpic (and similar)
+               // or renderscene
+               draw2d = prog->polygonbegin_guess2d;
        }
 
-       polys->begin_texture = (sf && sf->base) ? sf->base : r_texture_white;
-       polys->begin_texture_hasalpha = (sf && sf->base) ? sf->hasalpha : false;
-       polys->begin_drawflag = (int)PRVM_G_FLOAT(OFS_PARM1) & DRAWFLAG_MASK;
-       polys->begin_vertices = 0;
-       polys->begin_active = true;
-       polys->begin_draw2d = (prog->argc >= 3 ? (int)PRVM_G_FLOAT(OFS_PARM2) : r_refdef.draw2dstage);
+       // we need to remember whether this is a 2D or 3D mesh we're adding to
+       mod = draw2d ? CL_Mesh_UI() : CL_Mesh_CSQC();
+       prog->polygonbegin_model = mod;
+       Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, texname, drawflags, TEXF_ALPHA, MATERIALFLAG_WALL | MATERIALFLAG_VERTEXCOLOR | MATERIALFLAG_ALPHAGEN_VERTEX), draw2d);
 }
 
 //void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
-void VM_CL_R_PolygonVertex (void)
+static void VM_CL_R_PolygonVertex (prvm_prog_t *prog)
 {
-       vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+       const prvm_vec_t *v = PRVM_G_VECTOR(OFS_PARM0);
+       const prvm_vec_t *tc = PRVM_G_VECTOR(OFS_PARM1);
+       const prvm_vec_t *c = PRVM_G_VECTOR(OFS_PARM2);
+       const prvm_vec_t a = PRVM_G_FLOAT(OFS_PARM3);
+       dp_model_t *mod = prog->polygonbegin_model;
+       int e0, e1, e2;
+       msurface_t *surf;
 
        VM_SAFEPARMCOUNT(4, VM_CL_R_PolygonVertex);
 
-       if (!polys->begin_active)
+       if (!mod || mod->num_surfaces == 0)
        {
-               VM_Warning("VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n");
+               VM_Warning(prog, "VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n");
                return;
        }
 
-       if (polys->begin_vertices >= VMPOLYGONS_MAXPOINTS)
+       surf = &mod->data_surfaces[mod->num_surfaces - 1];
+       e2 = Mod_Mesh_IndexForVertex(mod, surf, v[0], v[1], v[2], 0, 0, 0, tc[0], tc[1], 0, 0, c[0], c[1], c[2], a);
+       if (surf->num_vertices >= 3)
        {
-               VM_Warning("VM_CL_R_PolygonVertex: may have %i vertices max\n", VMPOLYGONS_MAXPOINTS);
-               return;
+               // the first element is the start of the triangle fan
+               e0 = surf->num_firstvertex;
+               // the second element is the previous vertex
+               e1 = e0 + 1;
+               if (surf->num_triangles > 0)
+                       e1 = mod->surfmesh.data_element3i[(surf->num_firsttriangle + surf->num_triangles) * 3 - 1];
+               Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2);
        }
-
-       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() R_EndPolygon
-void VM_CL_R_PolygonEnd (void)
+static void VM_CL_R_PolygonEnd (prvm_prog_t *prog)
 {
-       vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+       dp_model_t *mod = prog->polygonbegin_model;
+       msurface_t *surf;
 
        VM_SAFEPARMCOUNT(0, VM_CL_R_PolygonEnd);
-       if (!polys->begin_active)
+       if (!mod || mod->num_surfaces == 0)
        {
-               VM_Warning("VM_CL_R_PolygonEnd: VM_CL_R_PolygonBegin wasn't called\n");
+               VM_Warning(prog, "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);
-}
-
-static vmpolygons_t debugPolys;
-
-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_Flags (picname, CACHEPICFLAG_NOTPERSISTENT)->tex : r_texture_white;
-       debugPolys.begin_drawflag = drawflag;
-       debugPolys.begin_vertices = 0;
-       debugPolys.begin_active = true;
-}
-
-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;
-       }
-
-       if(debugPolys.begin_vertices > VMPOLYGONS_MAXPOINTS)
-       {
-               Con_Printf("Debug_PolygonVertex: may have %i vertices max\n", VMPOLYGONS_MAXPOINTS);
-               return;
-       }
-
-       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++;
-}
-
-void Debug_PolygonEnd(void)
-{
-       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);
+       surf = &mod->data_surfaces[mod->num_surfaces - 1];
+       Mod_BuildNormals(surf->num_firstvertex, surf->num_vertices, surf->num_triangles, mod->surfmesh.data_vertex3f, mod->surfmesh.data_element3i + 3 * surf->num_firsttriangle, mod->surfmesh.data_normal3f, true);
+       prog->polygonbegin_model = NULL;
 }
 
 /*
@@ -3378,8 +3381,9 @@ is not a staircase.
 
 =============
 */
-qboolean CL_CheckBottom (prvm_edict_t *ent)
+static qboolean CL_CheckBottom (prvm_edict_t *ent)
 {
+       prvm_prog_t *prog = CLVM_prog;
        vec3_t  mins, maxs, start, stop;
        trace_t trace;
        int             x, y;
@@ -3413,7 +3417,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_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true, false);
+       trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, false, NULL, true, false);
 
        if (trace.fraction == 1.0)
                return false;
@@ -3426,7 +3430,7 @@ realcheck:
                        start[0] = stop[0] = x ? maxs[0] : mins[0];
                        start[1] = stop[1] = y ? maxs[1] : mins[1];
 
-                       trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true, false);
+                       trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, false, NULL, true, false);
 
                        if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
                                bottom = trace.endpos[2];
@@ -3446,15 +3450,19 @@ 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)
+static qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean settrace)
 {
+       prvm_prog_t *prog = CLVM_prog;
        float           dz;
        vec3_t          oldorg, neworg, end, traceendpos;
+       vec3_t          mins, maxs, start;
        trace_t         trace;
        int                     i, svent;
        prvm_edict_t            *enemy;
 
 // try the move
+       VectorCopy(PRVM_clientedictvector(ent, mins), mins);
+       VectorCopy(PRVM_clientedictvector(ent, maxs), maxs);
        VectorCopy (PRVM_clientedictvector(ent, origin), oldorg);
        VectorAdd (PRVM_clientedictvector(ent, origin), move, neworg);
 
@@ -3474,9 +3482,10 @@ qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean
                                if (dz < 30)
                                        neworg[2] += 8;
                        }
-                       trace = CL_TraceBox(PRVM_clientedictvector(ent, origin), PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
+                       VectorCopy(PRVM_clientedictvector(ent, origin), start);
+                       trace = CL_TraceBox(start, mins, maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, true, &svent, true);
                        if (settrace)
-                               CL_VM_SetTraceGlobals(&trace, svent);
+                               CL_VM_SetTraceGlobals(prog, &trace, svent);
 
                        if (trace.fraction == 1)
                        {
@@ -3502,16 +3511,16 @@ qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean
        VectorCopy (neworg, end);
        end[2] -= sv_stepheight.value*2;
 
-       trace = CL_TraceBox(neworg, PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
+       trace = CL_TraceBox(neworg, mins, maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, true, &svent, true);
        if (settrace)
-               CL_VM_SetTraceGlobals(&trace, svent);
+               CL_VM_SetTraceGlobals(prog, &trace, svent);
 
        if (trace.startsolid)
        {
                neworg[2] -= sv_stepheight.value;
-               trace = CL_TraceBox(neworg, PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
+               trace = CL_TraceBox(neworg, mins, maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value, true, true, &svent, true);
                if (settrace)
-                       CL_VM_SetTraceGlobals(&trace, svent);
+                       CL_VM_SetTraceGlobals(prog, &trace, svent);
                if (trace.startsolid)
                        return false;
        }
@@ -3564,7 +3573,7 @@ VM_CL_walkmove
 float(float yaw, float dist[, settrace]) walkmove
 ===============
 */
-static void VM_CL_walkmove (void)
+static void VM_CL_walkmove (prvm_prog_t *prog)
 {
        prvm_edict_t    *ent;
        float   yaw, dist;
@@ -3581,12 +3590,12 @@ static void VM_CL_walkmove (void)
        ent = PRVM_PROG_TO_EDICT(PRVM_clientglobaledict(self));
        if (ent == prog->edicts)
        {
-               VM_Warning("walkmove: can not modify world entity\n");
+               VM_Warning(prog, "walkmove: can not modify world entity\n");
                return;
        }
        if (ent->priv.server->free)
        {
-               VM_Warning("walkmove: can not modify free entity\n");
+               VM_Warning(prog, "walkmove: can not modify free entity\n");
                return;
        }
        yaw = PRVM_G_FLOAT(OFS_PARM0);
@@ -3621,12 +3630,12 @@ VM_CL_serverkey
 string(string key) serverkey
 ===============
 */
-void VM_CL_serverkey(void)
+static void VM_CL_serverkey(prvm_prog_t *prog)
 {
        char string[VM_STRINGTEMP_LENGTH];
        VM_SAFEPARMCOUNT(1, VM_CL_serverkey);
        InfoString_GetValue(cl.qw_serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
 }
 
 /*
@@ -3639,7 +3648,7 @@ Should be fast but can be inexact.
 float checkpvs(vector viewpos, entity viewee) = #240;
 =================
 */
-static void VM_CL_checkpvs (void)
+static void VM_CL_checkpvs (prvm_prog_t *prog)
 {
        vec3_t viewpos;
        prvm_edict_t *viewee;
@@ -3657,7 +3666,7 @@ static void VM_CL_checkpvs (void)
 
        if(viewee->priv.required->free)
        {
-               VM_Warning("checkpvs: can not check free entity\n");
+               VM_Warning(prog, "checkpvs: can not check free entity\n");
                PRVM_G_FLOAT(OFS_RETURN) = 4;
                return;
        }
@@ -3666,41 +3675,41 @@ static void VM_CL_checkpvs (void)
        VectorAdd(PRVM_serveredictvector(viewee, origin), PRVM_serveredictvector(viewee, maxs), ma);
 
 #if 1
-       if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
+       if(!cl.worldmodel || !cl.worldmodel->brush.GetPVS || !cl.worldmodel->brush.BoxTouchingPVS)
        {
                // no PVS support on this worldmodel... darn
                PRVM_G_FLOAT(OFS_RETURN) = 3;
                return;
        }
-       pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
+       pvs = cl.worldmodel->brush.GetPVS(cl.worldmodel, viewpos);
        if(!pvs)
        {
                // viewpos isn't in any PVS... darn
                PRVM_G_FLOAT(OFS_RETURN) = 2;
                return;
        }
-       PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, mi, ma);
+       PRVM_G_FLOAT(OFS_RETURN) = cl.worldmodel->brush.BoxTouchingPVS(cl.worldmodel, pvs, mi, ma);
 #else
        // using fat PVS like FTEQW does (slow)
-       if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
+       if(!cl.worldmodel || !cl.worldmodel->brush.FatPVS || !cl.worldmodel->brush.BoxTouchingPVS)
        {
                // no PVS support on this worldmodel... darn
                PRVM_G_FLOAT(OFS_RETURN) = 3;
                return;
        }
-       fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
+       fatpvsbytes = cl.worldmodel->brush.FatPVS(cl.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
        if(!fatpvsbytes)
        {
                // viewpos isn't in any PVS... darn
                PRVM_G_FLOAT(OFS_RETURN) = 2;
                return;
        }
-       PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, mi, ma);
+       PRVM_G_FLOAT(OFS_RETURN) = cl.worldmodel->brush.BoxTouchingPVS(cl.worldmodel, fatpvs, mi, ma);
 #endif
 }
 
 // #263 float(float modlindex) skel_create = #263; // (FTE_CSQC_SKELETONOBJECTS) create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure  (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex.
-static void VM_CL_skel_create(void)
+static void VM_CL_skel_create(prvm_prog_t *prog)
 {
        int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
        dp_model_t *model = CL_GetModelByIndex(modelindex);
@@ -3724,7 +3733,7 @@ static void VM_CL_skel_create(void)
 }
 
 // #264 float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // (FTE_CSQC_SKELETONOBJECTS) blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
-static void VM_CL_skel_build(void)
+static void VM_CL_skel_build(prvm_prog_t *prog)
 {
        int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
        skeleton_t *skeleton;
@@ -3734,13 +3743,12 @@ static void VM_CL_skel_build(void)
        int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
        int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
        dp_model_t *model = CL_GetModelByIndex(modelindex);
-       float blendfrac;
        int numblends;
        int bonenum;
        int blendindex;
        framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
        frameblend_t frameblend[MAX_FRAMEBLENDS];
-       matrix4x4_t blendedmatrix;
+       matrix4x4_t bonematrix;
        matrix4x4_t matrix;
        PRVM_G_FLOAT(OFS_RETURN) = 0;
        if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
@@ -3748,27 +3756,26 @@ static void VM_CL_skel_build(void)
        firstbone = max(0, firstbone);
        lastbone = min(lastbone, model->num_bones - 1);
        lastbone = min(lastbone, skeleton->model->num_bones - 1);
-       VM_GenerateFrameGroupBlend(framegroupblend, ed);
-       VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
-       blendfrac = 1.0f - retainfrac;
+       VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
+       VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, cl.time);
        for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
-               frameblend[numblends].lerp *= blendfrac;
+               ;
        for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
        {
-               memset(&blendedmatrix, 0, sizeof(blendedmatrix));
-               Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
+               memset(&bonematrix, 0, sizeof(bonematrix));
                for (blendindex = 0;blendindex < numblends;blendindex++)
                {
-                       Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
-                       Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
+                       Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
+                       Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
                }
-               skeleton->relativetransforms[bonenum] = blendedmatrix;
+               Matrix4x4_Normalize3(&bonematrix, &bonematrix);
+               Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
        }
        PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
 }
 
 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
-static void VM_CL_skel_get_numbones(void)
+static void VM_CL_skel_get_numbones(prvm_prog_t *prog)
 {
        int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
        skeleton_t *skeleton;
@@ -3779,7 +3786,7 @@ static void VM_CL_skel_get_numbones(void)
 }
 
 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
-static void VM_CL_skel_get_bonename(void)
+static void VM_CL_skel_get_bonename(prvm_prog_t *prog)
 {
        int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
        int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
@@ -3789,11 +3796,11 @@ static void VM_CL_skel_get_bonename(void)
                return;
        if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
                return;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
 }
 
 // #267 float(float skel, float bonenum) skel_get_boneparent = #267; // (FTE_CSQC_SKELETONOBJECTS) returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
-static void VM_CL_skel_get_boneparent(void)
+static void VM_CL_skel_get_boneparent(prvm_prog_t *prog)
 {
        int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
        int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
@@ -3807,7 +3814,7 @@ static void VM_CL_skel_get_boneparent(void)
 }
 
 // #268 float(float skel, string tagname) skel_find_bone = #268; // (FTE_CSQC_SKELETONOBJECTS) get number of bone with specified name, 0 on failure, tagindex (bonenum+1) on success, same as using gettagindex on the modelindex
-static void VM_CL_skel_find_bone(void)
+static void VM_CL_skel_find_bone(prvm_prog_t *prog)
 {
        int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
        const char *tagname = PRVM_G_STRING(OFS_PARM1);
@@ -3819,7 +3826,7 @@ static void VM_CL_skel_find_bone(void)
 }
 
 // #269 vector(float skel, float bonenum) skel_get_bonerel = #269; // (FTE_CSQC_SKELETONOBJECTS) get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
-static void VM_CL_skel_get_bonerel(void)
+static void VM_CL_skel_get_bonerel(prvm_prog_t *prog)
 {
        int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
        int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
@@ -3843,7 +3850,7 @@ static void VM_CL_skel_get_bonerel(void)
 }
 
 // #270 vector(float skel, float bonenum) skel_get_boneabs = #270; // (FTE_CSQC_SKELETONOBJECTS) get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
-static void VM_CL_skel_get_boneabs(void)
+static void VM_CL_skel_get_boneabs(prvm_prog_t *prog)
 {
        int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
        int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
@@ -3874,7 +3881,7 @@ static void VM_CL_skel_get_boneabs(void)
 }
 
 // #271 void(float skel, float bonenum, vector org) skel_set_bone = #271; // (FTE_CSQC_SKELETONOBJECTS) set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
-static void VM_CL_skel_set_bone(void)
+static void VM_CL_skel_set_bone(prvm_prog_t *prog)
 {
        int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
        int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
@@ -3894,7 +3901,7 @@ static void VM_CL_skel_set_bone(void)
 }
 
 // #272 void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (FTE_CSQC_SKELETONOBJECTS) transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
-static void VM_CL_skel_mul_bone(void)
+static void VM_CL_skel_mul_bone(prvm_prog_t *prog)
 {
        int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
        int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
@@ -3916,7 +3923,7 @@ static void VM_CL_skel_mul_bone(void)
 }
 
 // #273 void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // (FTE_CSQC_SKELETONOBJECTS) transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
-static void VM_CL_skel_mul_bones(void)
+static void VM_CL_skel_mul_bones(prvm_prog_t *prog)
 {
        int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
        int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
@@ -3943,7 +3950,7 @@ static void VM_CL_skel_mul_bones(void)
 }
 
 // #274 void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // (FTE_CSQC_SKELETONOBJECTS) copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
-static void VM_CL_skel_copybones(void)
+static void VM_CL_skel_copybones(prvm_prog_t *prog)
 {
        int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
        int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
@@ -3964,7 +3971,7 @@ static void VM_CL_skel_copybones(void)
 }
 
 // #275 void(float skel) skel_delete = #275; // (FTE_CSQC_SKELETONOBJECTS) deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
-static void VM_CL_skel_delete(void)
+static void VM_CL_skel_delete(prvm_prog_t *prog)
 {
        int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
        skeleton_t *skeleton;
@@ -3975,7 +3982,7 @@ static void VM_CL_skel_delete(void)
 }
 
 // #276 float(float modlindex, string framename) frameforname = #276; // (FTE_CSQC_SKELETONOBJECTS) finds number of a specified frame in the animation, returns -1 if no match found
-static void VM_CL_frameforname(void)
+static void VM_CL_frameforname(prvm_prog_t *prog)
 {
        int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
        dp_model_t *model = CL_GetModelByIndex(modelindex);
@@ -3995,7 +4002,7 @@ static void VM_CL_frameforname(void)
 }
 
 // #277 float(float modlindex, float framenum) frameduration = #277; // (FTE_CSQC_SKELETONOBJECTS) returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
-static void VM_CL_frameduration(void)
+static void VM_CL_frameduration(prvm_prog_t *prog)
 {
        int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
        dp_model_t *model = CL_GetModelByIndex(modelindex);
@@ -4007,7 +4014,7 @@ static void VM_CL_frameduration(void)
                PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
 }
 
-void VM_CL_RotateMoves(void)
+static void VM_CL_RotateMoves(prvm_prog_t *prog)
 {
        /*
         * Obscure builtin used by GAME_XONOTIC.
@@ -4038,15 +4045,16 @@ void VM_CL_RotateMoves(void)
     */
        matrix4x4_t m;
        vec3_t v = {0, 0, 0};
-       vec3_t x, y, z;
+       vec3_t a, x, y, z;
        VM_SAFEPARMCOUNT(1, VM_CL_RotateMoves);
-       AngleVectorsFLU(PRVM_G_VECTOR(OFS_PARM0), x, y, z);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), a);
+       AngleVectorsFLU(a, x, y, z);
        Matrix4x4_FromVectors(&m, x, y, z, v);
        CL_RotateMoves(&m);
 }
 
 // #358 void(string cubemapname) loadcubemap
-static void VM_CL_loadcubemap(void)
+static void VM_CL_loadcubemap(prvm_prog_t *prog)
 {
        const char *name;
 
@@ -4055,6 +4063,47 @@ static void VM_CL_loadcubemap(void)
        R_GetCubemap(name);
 }
 
+#define REFDEFFLAG_TELEPORTED 1
+#define REFDEFFLAG_JUMPING 2
+#define REFDEFFLAG_DEAD 4
+#define REFDEFFLAG_INTERMISSION 8
+static void VM_CL_V_CalcRefdef(prvm_prog_t *prog)
+{
+       matrix4x4_t entrendermatrix;
+       vec3_t clviewangles;
+       vec3_t clvelocity;
+       qboolean teleported;
+       qboolean clonground;
+       qboolean clcmdjump;
+       qboolean cldead;
+       qboolean clintermission;
+       float clstatsviewheight;
+       prvm_edict_t *ent;
+       int flags;
+
+       VM_SAFEPARMCOUNT(2, VM_CL_V_CalcRefdef);
+       ent = PRVM_G_EDICT(OFS_PARM0);
+       flags = PRVM_G_FLOAT(OFS_PARM1);
+
+       // use the CL_GetTagMatrix function on self to ensure consistent behavior (duplicate code would be bad)
+       CL_GetTagMatrix(prog, &entrendermatrix, ent, 0, NULL);
+
+       VectorCopy(cl.csqc_viewangles, clviewangles);
+       teleported = (flags & REFDEFFLAG_TELEPORTED) != 0;
+       clonground = ((int)PRVM_clientedictfloat(ent, pmove_flags) & PMF_ONGROUND) != 0;
+       clcmdjump = (flags & REFDEFFLAG_JUMPING) != 0;
+       clstatsviewheight = PRVM_clientedictvector(ent, view_ofs)[2];
+       cldead = (flags & REFDEFFLAG_DEAD) != 0;
+       clintermission = (flags & REFDEFFLAG_INTERMISSION) != 0;
+       VectorCopy(PRVM_clientedictvector(ent, velocity), clvelocity);
+
+       V_CalcRefdefUsing(&entrendermatrix, clviewangles, teleported, clonground, clcmdjump, clstatsviewheight, cldead, clintermission, clvelocity);
+
+       VectorCopy(cl.csqc_vieworiginfromengine, cl.csqc_vieworigin);
+       VectorCopy(cl.csqc_viewanglesfromengine, cl.csqc_viewangles);
+       CSQC_R_RecalcView();
+}
+
 //============================================================================
 
 // To create a almost working builtin file from this replace:
@@ -4604,10 +4653,10 @@ VM_CL_setpause,                                 // #531 float(float ispaused) setpause = #531 (DP_CSQC_SETPA
 VM_log,                                                        // #532
 VM_getsoundtime,                               // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
 VM_soundlength,                                        // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
-NULL,                                                  // #535
-NULL,                                                  // #536
-NULL,                                                  // #537
-NULL,                                                  // #538
+VM_buf_loadfile,                // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
+VM_buf_writefile,               // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
+VM_bufstr_find,                 // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
+VM_matchpattern,                // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
 NULL,                                                  // #539
 VM_physics_enable,                             // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
 VM_physics_addforce,                   // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
@@ -4708,34 +4757,26 @@ NULL,                                                   // #635
 NULL,                                                  // #636
 NULL,                                                  // #637
 VM_CL_RotateMoves,                                     // #638
-NULL,                                                  // #639
+VM_digest_hex,                                         // #639
+VM_CL_V_CalcRefdef,                                    // #640 void(entity e) V_CalcRefdef (DP_CSQC_V_CALCREFDEF)
+NULL,                                                  // #641
+VM_coverage,                                           // #642
+NULL
 };
 
 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)
+void CLVM_init_cmd(prvm_prog_t *prog)
 {
-       VM_Cmd_Init();
-       VM_Polygons_Reset();
+       VM_Cmd_Init(prog);
+       prog->polygonbegin_model = NULL;
+       prog->polygonbegin_guess2d = 0;
 }
 
-void VM_CL_Cmd_Reset(void)
+void CLVM_reset_cmd(prvm_prog_t *prog)
 {
        World_End(&cl.world);
-       VM_Cmd_Reset();
-       VM_Polygons_Reset();
+       VM_Cmd_Reset(prog);
+       prog->polygonbegin_model = NULL;
+       prog->polygonbegin_guess2d = 0;
 }
-
-