]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - clvm_cmds.c
DP_SND_SOUND7_WIP1
[xonotic/darkplaces.git] / clvm_cmds.c
index ed40c0de12511f8bca5bcd4ab8a2964800dc8af2..5b0b804360474f9f11edcb170be92772be8ce12f 100644 (file)
@@ -34,7 +34,7 @@ void CSQC_RelinkCSQCEntities (void);
 static void VM_CL_makevectors (void)
 {
        VM_SAFEPARMCOUNT(1, VM_CL_makevectors);
-       AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up);
+       AngleVectors (PRVM_G_VECTOR(OFS_PARM0), PRVM_clientglobalvector(v_forward), PRVM_clientglobalvector(v_right), PRVM_clientglobalvector(v_up));
 }
 
 // #2 void(entity e, vector o) setorigin
@@ -56,7 +56,7 @@ void VM_CL_setorigin (void)
                return;
        }
        org = PRVM_G_VECTOR(OFS_PARM1);
-       VectorCopy (org, e->fields.client->origin);
+       VectorCopy (org, PRVM_clientedictvector(e, origin));
        CL_LinkEdict(e);
 }
 
@@ -69,9 +69,9 @@ static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max)
                        PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
 
        // set derived values
-       VectorCopy (min, e->fields.client->mins);
-       VectorCopy (max, e->fields.client->maxs);
-       VectorSubtract (max, min, e->fields.client->size);
+       VectorCopy (min, PRVM_clientedictvector(e, mins));
+       VectorCopy (max, PRVM_clientedictvector(e, maxs));
+       VectorSubtract (max, min, PRVM_clientedictvector(e, size));
 
        CL_LinkEdict (e);
 }
@@ -87,8 +87,8 @@ void VM_CL_setmodel (void)
        VM_SAFEPARMCOUNT(2, VM_CL_setmodel);
 
        e = PRVM_G_EDICT(OFS_PARM0);
-       e->fields.client->modelindex = 0;
-       e->fields.client->model = 0;
+       PRVM_clientedictfloat(e, modelindex) = 0;
+       PRVM_clientedictstring(e, model) = 0;
 
        m = PRVM_G_STRING(OFS_PARM1);
        mod = NULL;
@@ -97,8 +97,8 @@ void VM_CL_setmodel (void)
                if (!strcmp(cl.csqc_model_precache[i]->name, m))
                {
                        mod = cl.csqc_model_precache[i];
-                       e->fields.client->model = PRVM_SetEngineString(mod->name);
-                       e->fields.client->modelindex = -(i+1);
+                       PRVM_clientedictstring(e, model) = PRVM_SetEngineString(mod->name);
+                       PRVM_clientedictfloat(e, modelindex) = -(i+1);
                        break;
                }
        }
@@ -109,8 +109,8 @@ void VM_CL_setmodel (void)
                        mod = cl.model_precache[i];
                        if (mod && !strcmp(mod->name, m))
                        {
-                               e->fields.client->model = PRVM_SetEngineString(mod->name);
-                               e->fields.client->modelindex = i;
+                               PRVM_clientedictstring(e, model) = PRVM_SetEngineString(mod->name);
+                               PRVM_clientedictfloat(e, modelindex) = i;
                                break;
                        }
                }
@@ -161,9 +161,11 @@ static void VM_CL_sound (void)
        prvm_edict_t            *entity;
        float                           volume;
        float                           attenuation;
+       float pitchchange;
+       int flags;
        vec3_t                          org;
 
-       VM_SAFEPARMCOUNT(5, VM_CL_sound);
+       VM_SAFEPARMCOUNTRANGE(5, 7, VM_CL_sound);
 
        entity = PRVM_G_EDICT(OFS_PARM0);
        channel = (int)PRVM_G_FLOAT(OFS_PARM1);
@@ -183,9 +185,22 @@ static void VM_CL_sound (void)
                return;
        }
 
-       if (channel < 0 || channel > 7)
+       if (prog->argc < 6)
+               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);
+
+       channel = CHAN_USER2ENGINE(channel);
+
+       if (!IS_CHAN(channel))
        {
-               VM_Warning("VM_CL_sound: channel must be in range 0-7\n");
+               VM_Warning("VM_CL_sound: channel must be in range 0-127\n");
                return;
        }
 
@@ -234,10 +249,8 @@ static void VM_CL_spawn (void)
 
 void CL_VM_SetTraceGlobals(const trace_t *trace, int svent)
 {
-       prvm_eval_t *val;
        VM_SetTraceGlobals(trace);
-       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_networkentity)))
-               val->_float = svent;
+       PRVM_clientglobalfloat(trace_networkentity) = svent;
 }
 
 #define CL_HitNetworkBrushModels(move) !((move) == MOVE_WORLDONLY)
@@ -265,7 +278,7 @@ static void VM_CL_traceline (void)
        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));
 
-       trace = CL_TraceLine(v1, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true);
+       trace = CL_TraceLine(v1, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true, false);
 
        CL_VM_SetTraceGlobals(&trace, svent);
 //     R_TimeReport("traceline");
@@ -320,38 +333,35 @@ trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore, int *svent)
        vec3_t original_velocity;
        vec3_t original_angles;
        vec3_t original_avelocity;
-       prvm_eval_t *val;
        trace_t trace;
 
-       VectorCopy(tossent->fields.client->origin   , original_origin   );
-       VectorCopy(tossent->fields.client->velocity , original_velocity );
-       VectorCopy(tossent->fields.client->angles   , original_angles   );
-       VectorCopy(tossent->fields.client->avelocity, original_avelocity);
+       VectorCopy(PRVM_clientedictvector(tossent, origin)   , original_origin   );
+       VectorCopy(PRVM_clientedictvector(tossent, velocity) , original_velocity );
+       VectorCopy(PRVM_clientedictvector(tossent, angles)   , original_angles   );
+       VectorCopy(PRVM_clientedictvector(tossent, avelocity), original_avelocity);
 
-       val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
-       if (val != NULL && val->_float != 0)
-               gravity = val->_float;
-       else
-               gravity = 1.0;
+       gravity = PRVM_clientedictfloat(tossent, gravity);
+       if (!gravity)
+               gravity = 1.0f;
        gravity *= cl.movevars_gravity * 0.05;
 
        for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
        {
-               tossent->fields.client->velocity[2] -= gravity;
-               VectorMA (tossent->fields.client->angles, 0.05, tossent->fields.client->avelocity, tossent->fields.client->angles);
-               VectorScale (tossent->fields.client->velocity, 0.05, move);
-               VectorAdd (tossent->fields.client->origin, move, end);
-               trace = CL_TraceBox(tossent->fields.client->origin, tossent->fields.client->mins, tossent->fields.client->maxs, end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), true, true, NULL, true);
-               VectorCopy (trace.endpos, tossent->fields.client->origin);
+               PRVM_clientedictvector(tossent, velocity)[2] -= gravity;
+               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 (trace.endpos, PRVM_clientedictvector(tossent, origin));
 
                if (trace.fraction < 1)
                        break;
        }
 
-       VectorCopy(original_origin   , tossent->fields.client->origin   );
-       VectorCopy(original_velocity , tossent->fields.client->velocity );
-       VectorCopy(original_angles   , tossent->fields.client->angles   );
-       VectorCopy(original_avelocity, tossent->fields.client->avelocity);
+       VectorCopy(original_origin   , PRVM_clientedictvector(tossent, origin)   );
+       VectorCopy(original_velocity , PRVM_clientedictvector(tossent, velocity) );
+       VectorCopy(original_angles   , PRVM_clientedictvector(tossent, angles)   );
+       VectorCopy(original_avelocity, PRVM_clientedictvector(tossent, avelocity));
 
        return trace;
 }
@@ -428,7 +438,7 @@ int CSQC_EntitiesInBox (vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **li
        {
                if (ent->priv.required->free)
                        continue;
-               if(BoxesOverlap(mins, maxs, ent->fields.client->absmin, ent->fields.client->absmax))
+               if(BoxesOverlap(mins, maxs, PRVM_clientedictvector(ent, absmin), PRVM_clientedictvector(ent, absmax)))
                        list[k++] = ent;
        }
        return k;
@@ -477,23 +487,23 @@ static void VM_CL_findradius (void)
                ent = touchedicts[i];
                // Quake did not return non-solid entities but darkplaces does
                // (note: this is the reason you can't blow up fallen zombies)
-               if (ent->fields.client->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
+               if (PRVM_clientedictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
                        continue;
                // LordHavoc: compare against bounding box rather than center so it
                // doesn't miss large objects, and use DotProduct instead of Length
                // for a major speedup
-               VectorSubtract(org, ent->fields.client->origin, eorg);
+               VectorSubtract(org, PRVM_clientedictvector(ent, origin), eorg);
                if (sv_gameplayfix_findradiusdistancetobox.integer)
                {
-                       eorg[0] -= bound(ent->fields.client->mins[0], eorg[0], ent->fields.client->maxs[0]);
-                       eorg[1] -= bound(ent->fields.client->mins[1], eorg[1], ent->fields.client->maxs[1]);
-                       eorg[2] -= bound(ent->fields.client->mins[2], eorg[2], ent->fields.client->maxs[2]);
+                       eorg[0] -= bound(PRVM_clientedictvector(ent, mins)[0], eorg[0], PRVM_clientedictvector(ent, maxs)[0]);
+                       eorg[1] -= bound(PRVM_clientedictvector(ent, mins)[1], eorg[1], PRVM_clientedictvector(ent, maxs)[1]);
+                       eorg[2] -= bound(PRVM_clientedictvector(ent, mins)[2], eorg[2], PRVM_clientedictvector(ent, maxs)[2]);
                }
                else
-                       VectorMAMAM(1, eorg, -0.5f, ent->fields.client->mins, -0.5f, ent->fields.client->maxs, eorg);
+                       VectorMAMAM(1, eorg, -0.5f, PRVM_clientedictvector(ent, mins), -0.5f, PRVM_clientedictvector(ent, maxs), eorg);
                if (DotProduct(eorg, eorg) < radius2)
                {
-                       PRVM_EDICTFIELDVALUE(ent, chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
+                       PRVM_EDICTFIELDEDICT(ent, chainfield) = PRVM_EDICT_TO_PROG(chain);
                        chain = ent;
                }
        }
@@ -505,7 +515,6 @@ static void VM_CL_findradius (void)
 static void VM_CL_droptofloor (void)
 {
        prvm_edict_t            *ent;
-       prvm_eval_t                     *val;
        vec3_t                          end;
        trace_t                         trace;
 
@@ -514,7 +523,7 @@ static void VM_CL_droptofloor (void)
        // assume failure if it returns early
        PRVM_G_FLOAT(OFS_RETURN) = 0;
 
-       ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
+       ent = PRVM_PROG_TO_EDICT(PRVM_clientglobaledict(self));
        if (ent == prog->edicts)
        {
                VM_Warning("droptofloor: can not modify world entity\n");
@@ -526,17 +535,16 @@ static void VM_CL_droptofloor (void)
                return;
        }
 
-       VectorCopy (ent->fields.client->origin, end);
+       VectorCopy (PRVM_clientedictvector(ent, origin), end);
        end[2] -= 256;
 
-       trace = CL_TraceBox(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+       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);
 
        if (trace.fraction != 1)
        {
-               VectorCopy (trace.endpos, ent->fields.client->origin);
-               ent->fields.client->flags = (int)ent->fields.client->flags | FL_ONGROUND;
-               if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.groundentity)))
-                       val->edict = PRVM_EDICT_TO_PROG(trace.ent);
+               VectorCopy (trace.endpos, PRVM_clientedictvector(ent, origin));
+               PRVM_clientedictfloat(ent, flags) = (int)PRVM_clientedictfloat(ent, flags) | FL_ONGROUND;
+               PRVM_clientedictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
                PRVM_G_FLOAT(OFS_RETURN) = 1;
                // if support is destroyed, keep suspended (gross hack for floating items in various maps)
 //             ent->priv.server->suspendedinairflag = true;
@@ -577,8 +585,8 @@ static void VM_CL_checkbottom (void)
        ent = PRVM_G_EDICT(OFS_PARM0);
        PRVM_G_FLOAT(OFS_RETURN) = 0;
 
-       VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins);
-       VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs);
+       VectorAdd (PRVM_clientedictvector(ent, origin), PRVM_clientedictvector(ent, mins), mins);
+       VectorAdd (PRVM_clientedictvector(ent, origin), PRVM_clientedictvector(ent, maxs), maxs);
 
 // if all of the points under the corners are solid world, don't bother
 // with the tougher checks
@@ -608,7 +616,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);
+       trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true, false);
 
        if (trace.fraction == 1.0)
                return;
@@ -622,7 +630,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);
+                       trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true, false);
 
                        if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
                                bottom = trace.endpos[2];
@@ -667,33 +675,37 @@ static void VM_CL_ambientsound (void)
        S_StaticSound (s, f, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3)*64);
 }
 
-// #92 vector(vector org) getlight (DP_QC_GETLIGHT)
+// #92 vector(vector org[, float lpflag]) getlight (DP_QC_GETLIGHT)
 static void VM_CL_getlight (void)
 {
        vec3_t ambientcolor, diffusecolor, diffusenormal;
        vec_t *p;
 
-       VM_SAFEPARMCOUNT(1, VM_CL_getlight);
+       VM_SAFEPARMCOUNTRANGE(1, 2, VM_CL_getlight);
 
        p = PRVM_G_VECTOR(OFS_PARM0);
        VectorClear(ambientcolor);
        VectorClear(diffusecolor);
        VectorClear(diffusenormal);
-       if (cl.worldmodel && cl.worldmodel->brush.LightPoint)
+       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);
        VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
 }
 
-
 //============================================================================
 //[515]: SCENE MANAGER builtins
 extern qboolean CSQC_AddRenderEdict (prvm_edict_t *ed, int edictnum);//csprogs.c
 
-static void CSQC_R_RecalcView (void)
+void CSQC_R_RecalcView (void)
 {
-       extern matrix4x4_t viewmodelmatrix;
-       Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], 1);
-       Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], cl_viewmodel_scale.value);
+       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);
+       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);
@@ -721,11 +733,12 @@ void VM_CL_R_ClearScene (void)
        r_refdef.view.ortho_y = scr_fov.value * (3.0 / 4.0);
        r_refdef.view.clear = true;
        r_refdef.view.isoverlay = false;
-       // FIXME: restore cl.csqc_origin
-       // FIXME: restore cl.csqc_angles
+       VectorCopy(cl.csqc_vieworiginfromengine, cl.csqc_vieworigin);
+       VectorCopy(cl.csqc_viewanglesfromengine, cl.csqc_viewangles);
        cl.csqc_vidvars.drawworld = r_drawworld.integer != 0;
        cl.csqc_vidvars.drawenginesbar = false;
        cl.csqc_vidvars.drawcrosshair = false;
+       CSQC_R_RecalcView();
 }
 
 //#301 void(float mask) addentities (EXT_CSQC)
@@ -741,9 +754,11 @@ void VM_CL_R_AddEntities (void)
        CSQC_RelinkAllEntities(drawmask);
        CL_RelinkLightFlashes();
 
-       prog->globals.client->time = cl.time;
+       PRVM_clientglobalfloat(time) = cl.time;
        for(i=1;i<prog->num_edicts;i++)
        {
+               // so we can easily check if CSQC entity #edictnum is currently drawn
+               cl.csqcrenderentities[i].entitynumber = 0;
                ed = &prog->edicts[i];
                if(ed->priv.required->free)
                        continue;
@@ -754,13 +769,13 @@ void VM_CL_R_AddEntities (void)
                CSQC_Predraw(ed);
                if(ed->priv.required->free)
                        continue;
-               if(!((int)ed->fields.client->drawmask & drawmask))
+               if(!((int)PRVM_clientedictfloat(ed, drawmask) & drawmask))
                        continue;
                CSQC_AddRenderEdict(ed, i);
        }
 
        // callprofile fixing hack: do not include this time in what is counted for CSQC_UpdateView
-       prog->functions[prog->funcoffsets.CSQC_UpdateView].totaltime -= Sys_DoubleTime() - t;
+       prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= Sys_DoubleTime() - t;
 }
 
 //#302 void(entity ent) addentity (EXT_CSQC)
@@ -769,7 +784,7 @@ void VM_CL_R_AddEntity (void)
        double t = Sys_DoubleTime();
        VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntity);
        CSQC_AddRenderEdict(PRVM_G_EDICT(OFS_PARM0), 0);
-       prog->functions[prog->funcoffsets.CSQC_UpdateView].totaltime -= Sys_DoubleTime() - t;
+       prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= Sys_DoubleTime() - t;
 }
 
 //#303 float(float property, ...) setproperty (EXT_CSQC)
@@ -822,28 +837,28 @@ void VM_CL_R_SetView (void)
                        PRVM_G_FLOAT(OFS_RETURN) = r_refdef.view.ortho_y;
                        break;
                case VF_ORIGIN:
-                       VectorCopy(cl.csqc_origin, PRVM_G_VECTOR(OFS_RETURN));
+                       VectorCopy(cl.csqc_vieworigin, PRVM_G_VECTOR(OFS_RETURN));
                        break;
                case VF_ORIGIN_X:
-                       PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_origin[0];
+                       PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_vieworigin[0];
                        break;
                case VF_ORIGIN_Y:
-                       PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_origin[1];
+                       PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_vieworigin[1];
                        break;
                case VF_ORIGIN_Z:
-                       PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_origin[2];
+                       PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_vieworigin[2];
                        break;
                case VF_ANGLES:
-                       VectorCopy(cl.csqc_angles, PRVM_G_VECTOR(OFS_RETURN));
+                       VectorCopy(cl.csqc_viewangles, PRVM_G_VECTOR(OFS_RETURN));
                        break;
                case VF_ANGLES_X:
-                       PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_angles[0];
+                       PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_viewangles[0];
                        break;
                case VF_ANGLES_Y:
-                       PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_angles[1];
+                       PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_viewangles[1];
                        break;
                case VF_ANGLES_Z:
-                       PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_angles[2];
+                       PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_viewangles[2];
                        break;
                case VF_DRAWWORLD:
                        PRVM_G_FLOAT(OFS_RETURN) = cl.csqc_vidvars.drawworld;
@@ -929,35 +944,35 @@ void VM_CL_R_SetView (void)
                r_refdef.view.frustum_y = tan(k * M_PI / 360.0);r_refdef.view.ortho_y = k;
                break;
        case VF_ORIGIN:
-               VectorCopy(f, cl.csqc_origin);
+               VectorCopy(f, cl.csqc_vieworigin);
                CSQC_R_RecalcView();
                break;
        case VF_ORIGIN_X:
-               cl.csqc_origin[0] = k;
+               cl.csqc_vieworigin[0] = k;
                CSQC_R_RecalcView();
                break;
        case VF_ORIGIN_Y:
-               cl.csqc_origin[1] = k;
+               cl.csqc_vieworigin[1] = k;
                CSQC_R_RecalcView();
                break;
        case VF_ORIGIN_Z:
-               cl.csqc_origin[2] = k;
+               cl.csqc_vieworigin[2] = k;
                CSQC_R_RecalcView();
                break;
        case VF_ANGLES:
-               VectorCopy(f, cl.csqc_angles);
+               VectorCopy(f, cl.csqc_viewangles);
                CSQC_R_RecalcView();
                break;
        case VF_ANGLES_X:
-               cl.csqc_angles[0] = k;
+               cl.csqc_viewangles[0] = k;
                CSQC_R_RecalcView();
                break;
        case VF_ANGLES_Y:
-               cl.csqc_angles[1] = k;
+               cl.csqc_viewangles[1] = k;
                CSQC_R_RecalcView();
                break;
        case VF_ANGLES_Z:
-               cl.csqc_angles[2] = k;
+               cl.csqc_viewangles[2] = k;
                CSQC_R_RecalcView();
                break;
        case VF_DRAWWORLD:
@@ -1038,14 +1053,14 @@ void VM_CL_R_AddDynamicLight (void)
        coronaintensity = (pflags & PFLAGS_CORONA) != 0;
        castshadow = (pflags & PFLAGS_NOSHADOW) == 0;
 
-       VectorScale(prog->globals.client->v_forward, radius, forward);
-       VectorScale(prog->globals.client->v_right, -radius, left);
-       VectorScale(prog->globals.client->v_up, radius, up);
+       VectorScale(PRVM_clientglobalvector(v_forward), radius, forward);
+       VectorScale(PRVM_clientglobalvector(v_right), -radius, left);
+       VectorScale(PRVM_clientglobalvector(v_up), radius, up);
        Matrix4x4_FromVectors(&matrix, forward, left, up, org);
 
        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[prog->funcoffsets.CSQC_UpdateView].totaltime -= Sys_DoubleTime() - t;
+       prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= Sys_DoubleTime() - t;
 }
 
 //============================================================================
@@ -1173,8 +1188,8 @@ static void VM_CL_setmodelindex (void)
 
        i = (int)PRVM_G_FLOAT(OFS_PARM1);
 
-       t->fields.client->model = 0;
-       t->fields.client->modelindex = 0;
+       PRVM_clientedictstring(t, model) = 0;
+       PRVM_clientedictfloat(t, modelindex) = 0;
 
        if (!i)
                return;
@@ -1185,8 +1200,8 @@ static void VM_CL_setmodelindex (void)
                VM_Warning("VM_CL_setmodelindex: null model\n");
                return;
        }
-       t->fields.client->model = PRVM_SetEngineString(model->name);
-       t->fields.client->modelindex = i;
+       PRVM_clientedictstring(t, model) = PRVM_SetEngineString(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)
@@ -1235,7 +1250,7 @@ static void VM_CL_trailparticles (void)
 
        if (i < 0)
                return;
-       CL_ParticleEffect(i, 1, start, end, t->fields.client->velocity, t->fields.client->velocity, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0);
+       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);
 }
 
 //#337 void(float effectnum, vector origin, vector dir, float count[, float color]) pointparticles (EXT_CSQC)
@@ -1263,7 +1278,6 @@ static void VM_CL_boxparticles (void)
        float count;
        int flags;
        float tintmins[4], tintmaxs[4];
-       prvm_eval_t *val;
        VM_SAFEPARMCOUNTRANGE(7, 8, VM_CL_boxparticles);
 
        effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
@@ -1281,17 +1295,13 @@ static void VM_CL_boxparticles (void)
        Vector4Set(tintmaxs, 1, 1, 1, 1);
        if(flags & 1) // read alpha
        {
-               if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.particles_alphamin)))
-                       tintmins[3] = val->_float;
-               if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.particles_alphamax)))
-                       tintmaxs[3] = val->_float;
+               tintmins[3] = PRVM_clientglobalfloat(particles_alphamin);
+               tintmaxs[3] = PRVM_clientglobalfloat(particles_alphamax);
        }
        if(flags & 2) // read color
        {
-               if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.particles_colormin)))
-                       VectorCopy(val->vector, tintmins);
-               if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.particles_colormax)))
-                       VectorCopy(val->vector, tintmaxs);
+               VectorCopy(PRVM_clientglobalvector(particles_colormin), tintmins);
+               VectorCopy(PRVM_clientglobalvector(particles_colormax), tintmaxs);
        }
        if (effectnum < 0)
                return;
@@ -1340,21 +1350,21 @@ static void VM_CL_getinputstate (void)
        {
                if (cl.movecmd[i].sequence == frame)
                {
-                       VectorCopy(cl.movecmd[i].viewangles, prog->globals.client->input_angles);
-                       prog->globals.client->input_buttons = cl.movecmd[i].buttons; // FIXME: this should not be directly exposed to csqc (translation layer needed?)
-                       prog->globals.client->input_movevalues[0] = cl.movecmd[i].forwardmove;
-                       prog->globals.client->input_movevalues[1] = cl.movecmd[i].sidemove;
-                       prog->globals.client->input_movevalues[2] = cl.movecmd[i].upmove;
-                       prog->globals.client->input_timelength = cl.movecmd[i].frametime;
+                       VectorCopy(cl.movecmd[i].viewangles, PRVM_clientglobalvector(input_angles));
+                       PRVM_clientglobalfloat(input_buttons) = cl.movecmd[i].buttons; // FIXME: this should not be directly exposed to csqc (translation layer needed?)
+                       PRVM_clientglobalvector(input_movevalues)[0] = cl.movecmd[i].forwardmove;
+                       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;
                        if(cl.movecmd[i].crouch)
                        {
-                               VectorCopy(cl.playercrouchmins, prog->globals.client->pmove_mins);
-                               VectorCopy(cl.playercrouchmaxs, prog->globals.client->pmove_maxs);
+                               VectorCopy(cl.playercrouchmins, PRVM_clientglobalvector(pmove_mins));
+                               VectorCopy(cl.playercrouchmaxs, PRVM_clientglobalvector(pmove_maxs));
                        }
                        else
                        {
-                               VectorCopy(cl.playerstandmins, prog->globals.client->pmove_mins);
-                               VectorCopy(cl.playerstandmaxs, prog->globals.client->pmove_maxs);
+                               VectorCopy(cl.playerstandmins, PRVM_clientglobalvector(pmove_mins));
+                               VectorCopy(cl.playerstandmaxs, PRVM_clientglobalvector(pmove_maxs));
                        }
                        PRVM_G_FLOAT(OFS_RETURN) = true;
                }
@@ -1423,6 +1433,20 @@ 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);
@@ -1542,7 +1566,7 @@ static void VM_CL_ReadPicture (void)
                        // texture found and loaded
                        // skip over the jpeg as we don't need it
                        for(i = 0; i < size; ++i)
-                               MSG_ReadByte();
+                               (void) MSG_ReadByte();
                }
                else
                {
@@ -1583,40 +1607,42 @@ static void VM_CL_makestatic (void)
        if (cl.num_static_entities < cl.max_static_entities)
        {
                int renderflags;
-               prvm_eval_t *val;
                entity_t *staticent = &cl.static_entities[cl.num_static_entities++];
 
                // copy it to the current state
                memset(staticent, 0, sizeof(*staticent));
-               staticent->render.model = CL_GetModelByIndex((int)ent->fields.client->modelindex);
-               staticent->render.framegroupblend[0].frame = (int)ent->fields.client->frame;
+               staticent->render.model = CL_GetModelByIndex((int)PRVM_clientedictfloat(ent, modelindex));
+               staticent->render.framegroupblend[0].frame = (int)PRVM_clientedictfloat(ent, frame);
                staticent->render.framegroupblend[0].lerp = 1;
                // make torchs play out of sync
                staticent->render.framegroupblend[0].start = lhrandom(-10, -1);
-               staticent->render.skinnum = (int)ent->fields.client->skin;
-               staticent->render.effects = (int)ent->fields.client->effects;
-               staticent->render.alpha = 1;
-               if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.alpha)) && val->_float) staticent->render.alpha = val->_float;
-               staticent->render.scale = 1;
-               if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)) && val->_float) staticent->render.scale = val->_float;
-               if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.colormod)) && VectorLength2(val->vector)) VectorCopy(val->vector, staticent->render.colormod);
-               if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.glowmod)) && VectorLength2(val->vector)) VectorCopy(val->vector, staticent->render.glowmod);
+               staticent->render.skinnum = (int)PRVM_clientedictfloat(ent, skin);
+               staticent->render.effects = (int)PRVM_clientedictfloat(ent, effects);
+               staticent->render.alpha = PRVM_clientedictfloat(ent, alpha);
+               staticent->render.scale = PRVM_clientedictfloat(ent, scale);
+               VectorCopy(PRVM_clientedictvector(ent, colormod), staticent->render.colormod);
+               VectorCopy(PRVM_clientedictvector(ent, glowmod), staticent->render.glowmod);
+
+               // sanitize values
+               if (!staticent->render.alpha)
+                       staticent->render.alpha = 1.0f;
+               if (!staticent->render.scale)
+                       staticent->render.scale = 1.0f;
                if (!VectorLength2(staticent->render.colormod))
                        VectorSet(staticent->render.colormod, 1, 1, 1);
                if (!VectorLength2(staticent->render.glowmod))
                        VectorSet(staticent->render.glowmod, 1, 1, 1);
 
-               renderflags = 0;
-               if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && val->_float) renderflags = (int)val->_float;
+               renderflags = (int)PRVM_clientedictfloat(ent, renderflags);
                if (renderflags & RF_USEAXIS)
                {
                        vec3_t left;
-                       VectorNegate(prog->globals.client->v_right, left);
-                       Matrix4x4_FromVectors(&staticent->render.matrix, prog->globals.client->v_forward, left, prog->globals.client->v_up, ent->fields.client->origin);
+                       VectorNegate(PRVM_clientglobalvector(v_right), left);
+                       Matrix4x4_FromVectors(&staticent->render.matrix, PRVM_clientglobalvector(v_forward), left, PRVM_clientglobalvector(v_up), PRVM_clientedictvector(ent, origin));
                        Matrix4x4_Scale(&staticent->render.matrix, staticent->render.scale, 1);
                }
                else
-                       Matrix4x4_CreateFromQuakeEntity(&staticent->render.matrix, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], staticent->render.scale);
+                       Matrix4x4_CreateFromQuakeEntity(&staticent->render.matrix, PRVM_clientedictvector(ent, origin)[0], PRVM_clientedictvector(ent, origin)[1], PRVM_clientedictvector(ent, origin)[2], PRVM_clientedictvector(ent, angles)[0], PRVM_clientedictvector(ent, angles)[1], PRVM_clientedictvector(ent, angles)[2], staticent->render.scale);
 
                // either fullbright or lit
                if(!r_fullbright.integer)
@@ -1683,7 +1709,7 @@ static void VM_CL_copyentity (void)
                VM_Warning("copyentity: can not modify free entity\n");
                return;
        }
-       memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
+       memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
        CL_LinkEdict(out);
 }
 
@@ -2097,8 +2123,8 @@ void VM_CL_setattachment (void)
        prvm_edict_t *e;
        prvm_edict_t *tagentity;
        const char *tagname;
-       prvm_eval_t *v;
        int modelindex;
+       int tagindex;
        dp_model_t *model;
        VM_SAFEPARMCOUNT(3, VM_CL_setattachment);
 
@@ -2120,26 +2146,23 @@ void VM_CL_setattachment (void)
        if (tagentity == NULL)
                tagentity = prog->edicts;
 
-       v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
-       if (v)
-               v->edict = PRVM_EDICT_TO_PROG(tagentity);
-
-       v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
-       if (v)
-               v->_float = 0;
+       tagindex = 0;
        if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
        {
-               modelindex = (int)tagentity->fields.client->modelindex;
+               modelindex = (int)PRVM_clientedictfloat(tagentity, modelindex);
                model = CL_GetModelByIndex(modelindex);
                if (model)
                {
-                       v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.client->skin, tagname);
-                       if (v->_float == 0)
+                       tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_clientedictfloat(tagentity, skin), tagname);
+                       if (tagindex == 0)
                                Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", PRVM_NUM_FOR_EDICT(e), PRVM_NUM_FOR_EDICT(tagentity), tagname, tagname, PRVM_NUM_FOR_EDICT(tagentity), model->name);
                }
                else
                        Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", PRVM_NUM_FOR_EDICT(e), PRVM_NUM_FOR_EDICT(tagentity), tagname, tagname, PRVM_NUM_FOR_EDICT(tagentity));
        }
+
+       PRVM_clientedictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
+       PRVM_clientedictfloat(e, tag_index) = tagindex;
 }
 
 /////////////////////////////////////////
@@ -2149,7 +2172,7 @@ int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
 {
        dp_model_t *model = CL_GetModelFromEdict(e);
        if (model)
-               return Mod_Alias_GetTagIndexForName(model, (int)e->fields.client->skin, tagname);
+               return Mod_Alias_GetTagIndexForName(model, (int)PRVM_clientedictfloat(e, skin), tagname);
        else
                return -1;
 }
@@ -2167,7 +2190,7 @@ int CL_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, cons
         && (model = CL_GetModelFromEdict(e))
         && model->animscenes)
        {
-               r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.client->skin, e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
+               r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_clientedictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
 
                if(!r) // success?
                        *parentindex += 1;
@@ -2188,22 +2211,31 @@ int CL_GetPitchSign(prvm_edict_t *ent)
 
 void CL_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
 {
-       prvm_eval_t *val;
        float scale;
        float pitchsign = 1;
 
-       scale = 1;
-       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
-       if (val && val->_float != 0)
-               scale = val->_float;
+       scale = PRVM_clientedictfloat(ent, scale);
+       if (!scale)
+               scale = 1.0f;
 
-       // TODO do we need the same weird angle inverting logic here as in the server side case?
        if(viewmatrix)
-               Matrix4x4_CreateFromQuakeEntity(out, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], scale * cl_viewmodel_scale.value);
+               *out = r_refdef.view.matrix;
+       else if ((int)PRVM_clientedictfloat(ent, renderflags) & RF_USEAXIS)
+       {
+               vec3_t forward;
+               vec3_t left;
+               vec3_t up;
+               vec3_t origin;
+               VectorScale(PRVM_clientglobalvector(v_forward), scale, forward);
+               VectorScale(PRVM_clientglobalvector(v_right), -scale, left);
+               VectorScale(PRVM_clientglobalvector(v_up), scale, up);
+               VectorCopy(PRVM_clientedictvector(ent, origin), origin);
+               Matrix4x4_FromVectors(out, forward, left, up, origin);
+       }
        else
        {
                pitchsign = CL_GetPitchSign(ent);
-               Matrix4x4_CreateFromQuakeEntity(out, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], pitchsign * ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], scale);
+               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);
        }
 }
 
@@ -2236,7 +2268,6 @@ extern cvar_t cl_bobup;
 int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
 {
        int ret;
-       prvm_eval_t *val;
        int attachloop;
        matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
        dp_model_t *model;
@@ -2267,10 +2298,10 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
                Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
                // next iteration we process the parent entity
-               if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
+               if (PRVM_clientedictedict(ent, tag_entity))
                {
-                       tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
-                       ent = PRVM_EDICT_NUM(val->edict);
+                       tagindex = (int)PRVM_clientedictfloat(ent, tag_index);
+                       ent = PRVM_EDICT_NUM(PRVM_clientedictedict(ent, tag_entity));
                }
                else
                        break;
@@ -2278,7 +2309,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
        }
 
        // RENDER_VIEWMODEL magic
-       if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && (RF_VIEWMODEL & (int)val->_float))
+       if ((int)PRVM_clientedictfloat(ent, renderflags) & RF_VIEWMODEL)
        {
                Matrix4x4_Copy(&tagmatrix, out);
 
@@ -2287,7 +2318,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
 
                /*
                // Cl_bob, ported from rendering code
-               if (ent->fields.client->health > 0 && cl_bob.value && cl_bobcycle.value)
+               if (PRVM_clientedictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
                {
                        double bob, cycle;
                        // LordHavoc: this code is *weird*, but not replacable (I think it
@@ -2302,7 +2333,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                                cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
                        // bob is proportional to velocity in the xy plane
                        // (don't count Z, or jumping messes it up)
-                       bob = sqrt(ent->fields.client->velocity[0]*ent->fields.client->velocity[0] + ent->fields.client->velocity[1]*ent->fields.client->velocity[1])*cl_bob.value;
+                       bob = sqrt(PRVM_clientedictvector(ent, velocity)[0]*PRVM_clientedictvector(ent, velocity)[0] + PRVM_clientedictvector(ent, velocity)[1]*PRVM_clientedictvector(ent, velocity)[1])*cl_bob.value;
                        bob = bob*0.3 + bob*0.7*cycle;
                        Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
                }
@@ -2355,7 +2386,6 @@ void VM_CL_gettaginfo (void)
        int parentindex;
        const char *tagname;
        int returncode;
-       prvm_eval_t *val;
        vec3_t fo, le, up, trans;
        const dp_model_t *model;
 
@@ -2364,8 +2394,8 @@ void VM_CL_gettaginfo (void)
        e = PRVM_G_EDICT(OFS_PARM0);
        tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
        returncode = CL_GetTagMatrix(&tag_matrix, e, tagindex);
-       Matrix4x4_ToVectors(&tag_matrix, prog->globals.client->v_forward, le, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN));
-       VectorScale(le, -1, prog->globals.client->v_right);
+       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));
        model = CL_GetModelFromEdict(e);
        VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
        VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
@@ -2373,18 +2403,12 @@ void VM_CL_gettaginfo (void)
        CL_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
        Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
 
-       if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
-               val->_float = parentindex;
-       if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
-               val->string = tagname ? PRVM_SetTempString(tagname) : 0;
-       if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
-               VectorCopy(trans, val->vector);
-       if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
-               VectorCopy(fo, val->vector);
-       if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
-               VectorScale(le, -1, val->vector);
-       if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
-               VectorCopy(up, val->vector);
+       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));
+       VectorCopy(up, PRVM_clientglobalvector(gettaginfo_up));
 
        switch(returncode)
        {
@@ -2491,8 +2515,6 @@ vmparticlespawner_t vmpartspawner;
 // TODO: automatic max_themes grow
 static void VM_InitParticleSpawner (int maxthemes)
 {
-       prvm_eval_t *val;
-
        // bound max themes to not be an insane value
        if (maxthemes < 4)
                maxthemes = 4;
@@ -2510,37 +2532,35 @@ static void VM_InitParticleSpawner (int maxthemes)
        vmpartspawner.initialized = true;
        vmpartspawner.verified = true;
        // get field addresses for fast querying (we can do 1000 calls of spawnparticle in a frame)
-       #define getglobal(v,s) val = PRVM_GLOBALFIELDVALUE(PRVM_ED_FindGlobalOffset(s)); if (val) { vmpartspawner.v = &val->_float; } else { VM_Warning("VM_InitParticleSpawner: missing global '%s', spawner cannot work\n", s); vmpartspawner.verified = false; }
-       #define getglobalvector(v,s) val = PRVM_GLOBALFIELDVALUE(PRVM_ED_FindGlobalOffset(s)); if (val) { vmpartspawner.v = (float *)val->vector; } else { VM_Warning("VM_InitParticleSpawner: missing global '%s', spawner cannot work\n", s); vmpartspawner.verified = false; }
-       getglobal(particle_type, "particle_type");
-       getglobal(particle_blendmode, "particle_blendmode");
-       getglobal(particle_orientation, "particle_orientation");
-       getglobalvector(particle_color1, "particle_color1");
-       getglobalvector(particle_color2, "particle_color2");
-       getglobal(particle_tex, "particle_tex");
-       getglobal(particle_size, "particle_size");
-       getglobal(particle_sizeincrease, "particle_sizeincrease");
-       getglobal(particle_alpha, "particle_alpha");
-       getglobal(particle_alphafade, "particle_alphafade");
-       getglobal(particle_time, "particle_time");
-       getglobal(particle_gravity, "particle_gravity");
-       getglobal(particle_bounce, "particle_bounce");
-       getglobal(particle_airfriction, "particle_airfriction");
-       getglobal(particle_liquidfriction, "particle_liquidfriction");
-       getglobal(particle_originjitter, "particle_originjitter");
-       getglobal(particle_velocityjitter, "particle_velocityjitter");
-       getglobal(particle_qualityreduction, "particle_qualityreduction");
-       getglobal(particle_stretch, "particle_stretch");
-       getglobalvector(particle_staincolor1, "particle_staincolor1");
-       getglobalvector(particle_staincolor2, "particle_staincolor2");
-       getglobal(particle_stainalpha, "particle_stainalpha");
-       getglobal(particle_stainsize, "particle_stainsize");
-       getglobal(particle_staintex, "particle_staintex");
-       getglobal(particle_staintex, "particle_staintex");
-       getglobal(particle_delayspawn, "particle_delayspawn");
-       getglobal(particle_delaycollision, "particle_delaycollision");
-       getglobal(particle_angle, "particle_angle");
-       getglobal(particle_spin, "particle_spin");
+       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
 }
@@ -2914,7 +2934,7 @@ void VM_CL_GetEntity (void)
                        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, prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN)); 
+                       Matrix4x4_ToVectors(&cl.entities[entnum].render.matrix, PRVM_clientglobalvector(v_forward), PRVM_clientglobalvector(v_right), PRVM_clientglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));        
                        break;  
                case 7: // alpha
                        PRVM_G_FLOAT(OFS_RETURN) = cl.entities[entnum].render.alpha;
@@ -3019,7 +3039,7 @@ void VM_CL_R_RenderScene (void)
        polys->progstarttime = prog->starttime;
 
        // callprofile fixing hack: do not include this time in what is counted for CSQC_UpdateView
-       prog->functions[prog->funcoffsets.CSQC_UpdateView].totaltime -= Sys_DoubleTime() - t;
+       prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= Sys_DoubleTime() - t;
 }
 
 static void VM_ResizePolygons(vmpolygons_t *polys)
@@ -3073,7 +3093,7 @@ static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t
        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_Mesh_ResetTextureState();
        R_EntityMatrix(&identitymatrix);
        GL_CullFace(GL_NONE);
        GL_DepthTest(true); // polys in 3D space shall always have depth test
@@ -3086,7 +3106,7 @@ static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t
                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);
+               R_SetupShader_Generic(tex, NULL, GL_MODULATE, 1, false);
                numtriangles = 0;
                for (;surfacelistindex < numsurfaces;surfacelistindex++)
                {
@@ -3363,8 +3383,8 @@ qboolean CL_CheckBottom (prvm_edict_t *ent)
        int             x, y;
        float   mid, bottom;
 
-       VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins);
-       VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs);
+       VectorAdd (PRVM_clientedictvector(ent, origin), PRVM_clientedictvector(ent, mins), mins);
+       VectorAdd (PRVM_clientedictvector(ent, origin), PRVM_clientedictvector(ent, maxs), maxs);
 
 // if all of the points under the corners are solid world, don't bother
 // with the tougher checks
@@ -3391,7 +3411,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);
+       trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true, false);
 
        if (trace.fraction == 1.0)
                return false;
@@ -3404,7 +3424,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);
+                       trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true, false);
 
                        if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
                                bottom = trace.endpos[2];
@@ -3431,39 +3451,38 @@ qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean
        trace_t         trace;
        int                     i, svent;
        prvm_edict_t            *enemy;
-       prvm_eval_t     *val;
 
 // try the move
-       VectorCopy (ent->fields.client->origin, oldorg);
-       VectorAdd (ent->fields.client->origin, move, neworg);
+       VectorCopy (PRVM_clientedictvector(ent, origin), oldorg);
+       VectorAdd (PRVM_clientedictvector(ent, origin), move, neworg);
 
 // flying monsters don't step up
-       if ( (int)ent->fields.client->flags & (FL_SWIM | FL_FLY) )
+       if ( (int)PRVM_clientedictfloat(ent, flags) & (FL_SWIM | FL_FLY) )
        {
        // try one move with vertical motion, then one without
                for (i=0 ; i<2 ; i++)
                {
-                       VectorAdd (ent->fields.client->origin, move, neworg);
-                       enemy = PRVM_PROG_TO_EDICT(ent->fields.client->enemy);
+                       VectorAdd (PRVM_clientedictvector(ent, origin), move, neworg);
+                       enemy = PRVM_PROG_TO_EDICT(PRVM_clientedictedict(ent, enemy));
                        if (i == 0 && enemy != prog->edicts)
                        {
-                               dz = ent->fields.client->origin[2] - PRVM_PROG_TO_EDICT(ent->fields.client->enemy)->fields.client->origin[2];
+                               dz = PRVM_clientedictvector(ent, origin)[2] - PRVM_clientedictvector(PRVM_PROG_TO_EDICT(PRVM_clientedictedict(ent, enemy)), origin)[2];
                                if (dz > 40)
                                        neworg[2] -= 8;
                                if (dz < 30)
                                        neworg[2] += 8;
                        }
-                       trace = CL_TraceBox(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
+                       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);
                        if (settrace)
                                CL_VM_SetTraceGlobals(&trace, svent);
 
                        if (trace.fraction == 1)
                        {
                                VectorCopy(trace.endpos, traceendpos);
-                               if (((int)ent->fields.client->flags & FL_SWIM) && !(CL_PointSuperContents(traceendpos) & SUPERCONTENTS_LIQUIDSMASK))
+                               if (((int)PRVM_clientedictfloat(ent, flags) & FL_SWIM) && !(CL_PointSuperContents(traceendpos) & SUPERCONTENTS_LIQUIDSMASK))
                                        return false;   // swim monster left water
 
-                               VectorCopy (traceendpos, ent->fields.client->origin);
+                               VectorCopy (traceendpos, PRVM_clientedictvector(ent, origin));
                                if (relink)
                                        CL_LinkEdict(ent);
                                return true;
@@ -3481,14 +3500,14 @@ 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, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
+       trace = CL_TraceBox(neworg, PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
        if (settrace)
                CL_VM_SetTraceGlobals(&trace, svent);
 
        if (trace.startsolid)
        {
                neworg[2] -= sv_stepheight.value;
-               trace = CL_TraceBox(neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
+               trace = CL_TraceBox(neworg, PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
                if (settrace)
                        CL_VM_SetTraceGlobals(&trace, svent);
                if (trace.startsolid)
@@ -3497,12 +3516,12 @@ qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean
        if (trace.fraction == 1)
        {
        // if monster had the ground pulled out, go ahead and fall
-               if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
+               if ( (int)PRVM_clientedictfloat(ent, flags) & FL_PARTIALGROUND )
                {
-                       VectorAdd (ent->fields.client->origin, move, ent->fields.client->origin);
+                       VectorAdd (PRVM_clientedictvector(ent, origin), move, PRVM_clientedictvector(ent, origin));
                        if (relink)
                                CL_LinkEdict(ent);
-                       ent->fields.client->flags = (int)ent->fields.client->flags & ~FL_ONGROUND;
+                       PRVM_clientedictfloat(ent, flags) = (int)PRVM_clientedictfloat(ent, flags) & ~FL_ONGROUND;
                        return true;
                }
 
@@ -3510,26 +3529,25 @@ qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean
        }
 
 // check point traces down for dangling corners
-       VectorCopy (trace.endpos, ent->fields.client->origin);
+       VectorCopy (trace.endpos, PRVM_clientedictvector(ent, origin));
 
        if (!CL_CheckBottom (ent))
        {
-               if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
+               if ( (int)PRVM_clientedictfloat(ent, flags) & FL_PARTIALGROUND )
                {       // entity had floor mostly pulled out from underneath it
                        // and is trying to correct
                        if (relink)
                                CL_LinkEdict(ent);
                        return true;
                }
-               VectorCopy (oldorg, ent->fields.client->origin);
+               VectorCopy (oldorg, PRVM_clientedictvector(ent, origin));
                return false;
        }
 
-       if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
-               ent->fields.client->flags = (int)ent->fields.client->flags & ~FL_PARTIALGROUND;
+       if ( (int)PRVM_clientedictfloat(ent, flags) & FL_PARTIALGROUND )
+               PRVM_clientedictfloat(ent, flags) = (int)PRVM_clientedictfloat(ent, flags) & ~FL_PARTIALGROUND;
 
-       if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.groundentity)))
-               val->edict = PRVM_EDICT_TO_PROG(trace.ent);
+       PRVM_clientedictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
 
 // the move is ok
        if (relink)
@@ -3558,7 +3576,7 @@ static void VM_CL_walkmove (void)
        // assume failure if it returns early
        PRVM_G_FLOAT(OFS_RETURN) = 0;
 
-       ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
+       ent = PRVM_PROG_TO_EDICT(PRVM_clientglobaledict(self));
        if (ent == prog->edicts)
        {
                VM_Warning("walkmove: can not modify world entity\n");
@@ -3573,7 +3591,7 @@ static void VM_CL_walkmove (void)
        dist = PRVM_G_FLOAT(OFS_PARM1);
        settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
 
-       if ( !( (int)ent->fields.client->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
+       if ( !( (int)PRVM_clientedictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
                return;
 
        yaw = yaw*M_PI*2 / 360;
@@ -3584,14 +3602,14 @@ static void VM_CL_walkmove (void)
 
 // save program state, because CL_movestep may call other progs
        oldf = prog->xfunction;
-       oldself = prog->globals.client->self;
+       oldself = PRVM_clientglobaledict(self);
 
        PRVM_G_FLOAT(OFS_RETURN) = CL_movestep(ent, move, true, false, settrace);
 
 
 // restore program state
        prog->xfunction = oldf;
-       prog->globals.client->self = oldself;
+       PRVM_clientglobaledict(self) = oldself;
 }
 
 /*
@@ -3642,8 +3660,8 @@ static void VM_CL_checkpvs (void)
                return;
        }
 
-       VectorAdd(viewee->fields.server->origin, viewee->fields.server->mins, mi);
-       VectorAdd(viewee->fields.server->origin, viewee->fields.server->maxs, ma);
+       VectorAdd(PRVM_serveredictvector(viewee, origin), PRVM_serveredictvector(viewee, mins), mi);
+       VectorAdd(PRVM_serveredictvector(viewee, origin), PRVM_serveredictvector(viewee, maxs), ma);
 
 #if 1
        if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
@@ -3807,18 +3825,18 @@ static void VM_CL_skel_get_bonerel(void)
        matrix4x4_t matrix;
        vec3_t forward, left, up, origin;
        VectorClear(PRVM_G_VECTOR(OFS_RETURN));
-       VectorClear(prog->globals.client->v_forward);
-       VectorClear(prog->globals.client->v_right);
-       VectorClear(prog->globals.client->v_up);
+       VectorClear(PRVM_clientglobalvector(v_forward));
+       VectorClear(PRVM_clientglobalvector(v_right));
+       VectorClear(PRVM_clientglobalvector(v_up));
        if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
                return;
        if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
                return;
        matrix = skeleton->relativetransforms[bonenum];
        Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
-       VectorCopy(forward, prog->globals.client->v_forward);
-       VectorNegate(left, prog->globals.client->v_right);
-       VectorCopy(up, prog->globals.client->v_up);
+       VectorCopy(forward, PRVM_clientglobalvector(v_forward));
+       VectorNegate(left, PRVM_clientglobalvector(v_right));
+       VectorCopy(up, PRVM_clientglobalvector(v_up));
        VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
 }
 
@@ -3832,9 +3850,9 @@ static void VM_CL_skel_get_boneabs(void)
        matrix4x4_t temp;
        vec3_t forward, left, up, origin;
        VectorClear(PRVM_G_VECTOR(OFS_RETURN));
-       VectorClear(prog->globals.client->v_forward);
-       VectorClear(prog->globals.client->v_right);
-       VectorClear(prog->globals.client->v_up);
+       VectorClear(PRVM_clientglobalvector(v_forward));
+       VectorClear(PRVM_clientglobalvector(v_right));
+       VectorClear(PRVM_clientglobalvector(v_up));
        if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
                return;
        if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
@@ -3847,9 +3865,9 @@ static void VM_CL_skel_get_boneabs(void)
                Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
        }
        Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
-       VectorCopy(forward, prog->globals.client->v_forward);
-       VectorNegate(left, prog->globals.client->v_right);
-       VectorCopy(up, prog->globals.client->v_up);
+       VectorCopy(forward, PRVM_clientglobalvector(v_forward));
+       VectorNegate(left, PRVM_clientglobalvector(v_right));
+       VectorCopy(up, PRVM_clientglobalvector(v_up));
        VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
 }
 
@@ -3865,9 +3883,9 @@ static void VM_CL_skel_set_bone(void)
                return;
        if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
                return;
-       VectorCopy(prog->globals.client->v_forward, forward);
-       VectorNegate(prog->globals.client->v_right, left);
-       VectorCopy(prog->globals.client->v_up, up);
+       VectorCopy(PRVM_clientglobalvector(v_forward), forward);
+       VectorNegate(PRVM_clientglobalvector(v_right), left);
+       VectorCopy(PRVM_clientglobalvector(v_up), up);
        VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
        Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
        skeleton->relativetransforms[bonenum] = matrix;
@@ -3887,9 +3905,9 @@ static void VM_CL_skel_mul_bone(void)
        if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
                return;
        VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
-       VectorCopy(prog->globals.client->v_forward, forward);
-       VectorNegate(prog->globals.client->v_right, left);
-       VectorCopy(prog->globals.client->v_up, up);
+       VectorCopy(PRVM_clientglobalvector(v_forward), forward);
+       VectorNegate(PRVM_clientglobalvector(v_right), left);
+       VectorCopy(PRVM_clientglobalvector(v_up), up);
        Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
        temp = skeleton->relativetransforms[bonenum];
        Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
@@ -3909,9 +3927,9 @@ static void VM_CL_skel_mul_bones(void)
        if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
                return;
        VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
-       VectorCopy(prog->globals.client->v_forward, forward);
-       VectorNegate(prog->globals.client->v_right, left);
-       VectorCopy(prog->globals.client->v_up, up);
+       VectorCopy(PRVM_clientglobalvector(v_forward), forward);
+       VectorNegate(PRVM_clientglobalvector(v_right), left);
+       VectorCopy(PRVM_clientglobalvector(v_up), up);
        Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
        firstbone = max(0, firstbone);
        lastbone = min(lastbone, skeleton->model->num_bones - 1);
@@ -3987,6 +4005,54 @@ static void VM_CL_frameduration(void)
                PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
 }
 
+void VM_CL_RotateMoves(void)
+{
+       /*
+        * Obscure builtin used by GAME_XONOTIC.
+        *
+        * Edits the input history of cl_movement by rotating all move commands
+        * currently in the queue using the given transform.
+        *
+        * The vector passed is an "angles transform" as used by warpzonelib, i.e.
+        * v_angle-like (non-inverted) euler angles that perform the rotation
+        * of the space that is to be done.
+        *
+        * This is meant to be used as a fixangle replacement after passing
+        * through a warpzone/portal: the client is told about the warp transform,
+        * and calls this function in the same frame as the one on which the
+        * client's origin got changed by the serverside teleport. Then this code
+        * transforms the pre-warp input (which matches the empty space behind
+        * the warp plane) into post-warp input (which matches the target area
+        * of the warp). Also, at the same time, the client has to use
+        * R_SetView to adjust VF_CL_VIEWANGLES according to the same transform.
+        *
+        * This together allows warpzone motion to be perfectly predicted by
+        * the client!
+        *
+        * Furthermore, for perfect warpzone behaviour, the server side also
+        * has to detect input the client sent before it received the origin
+        * update, but after the warp occurred on the server, and has to adjust
+        * input appropriately.
+    */
+       matrix4x4_t m;
+       vec3_t v = {0, 0, 0};
+       vec3_t x, y, z;
+       VM_SAFEPARMCOUNT(1, VM_CL_RotateMoves);
+       AngleVectorsFLU(PRVM_G_VECTOR(OFS_PARM0), x, y, z);
+       Matrix4x4_FromVectors(&m, x, y, z, v);
+       CL_RotateMoves(&m);
+}
+
+// #358 void(string cubemapname) loadcubemap
+static void VM_CL_loadcubemap(void)
+{
+       const char *name;
+
+       VM_SAFEPARMCOUNT(1, VM_CL_loadcubemap);
+       name = PRVM_G_STRING(OFS_PARM0);
+       R_GetCubemap(name);
+}
+
 //============================================================================
 
 // To create a almost working builtin file from this replace:
@@ -4358,7 +4424,7 @@ VM_CL_serverkey,                          // #354 string(string key) serverkey (EXT_CSQC)
 VM_CL_videoplaying,                            // #355
 VM_findfont,                                   // #356 float(string fontname) loadfont (DP_GFX_FONTS)
 VM_loadfont,                                   // #357 float(string fontname, string fontmaps, string sizes, float slot) loadfont (DP_GFX_FONTS)
-NULL,                                                  // #358
+VM_CL_loadcubemap,                             // #358 void(string cubemapname) loadcubemap (DP_GFX_)
 NULL,                                                  // #359
 VM_CL_ReadByte,                                        // #360 float() readbyte (EXT_CSQC)
 VM_CL_ReadChar,                                        // #361 float() readchar (EXT_CSQC)
@@ -4514,7 +4580,7 @@ NULL,                                                     // #509
 VM_uri_escape,                                 // #510 string(string in) uri_escape = #510;
 VM_uri_unescape,                               // #511 string(string in) uri_unescape = #511;
 VM_etof,                                       // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
-VM_uri_get,                                            // #513 float(string uril, float id) uri_get = #512; (DP_QC_URI_GET)
+VM_uri_get,                                            // #513 float(string uri, float id, [string post_contenttype, string post_delim, [float buf]]) uri_get = #513; (DP_QC_URI_GET, DP_QC_URI_POST)
 VM_tokenize_console,                                   // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
 VM_argv_start_index,                                   // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
 VM_argv_end_index,                                             // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
@@ -4541,9 +4607,9 @@ NULL,                                                     // #536
 NULL,                                                  // #537
 NULL,                                                  // #538
 NULL,                                                  // #539
-NULL,                                                  // #540
-NULL,                                                  // #541
-NULL,                                                  // #542
+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)
+VM_physics_addtorque,                  // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
 NULL,                                                  // #543
 NULL,                                                  // #544
 NULL,                                                  // #545
@@ -4635,6 +4701,12 @@ VM_setkeybind,                                           // #630 float(float key, string bind[, float bindmap]) setke
 VM_getbindmaps,                                                // #631 vector(void) getbindmap
 VM_setbindmaps,                                                // #632 float(vector bm) setbindmap
 NULL,                                                  // #633
+NULL,                                                  // #634
+NULL,                                                  // #635
+NULL,                                                  // #636
+NULL,                                                  // #637
+VM_CL_RotateMoves,                                     // #638
+NULL,                                                  // #639
 };
 
 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);