]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - clvm_cmds.c
DP_SND_SOUND7_WIP1
[xonotic/darkplaces.git] / clvm_cmds.c
index ea5ea17042a1b4f850580627e2abc7410d9a072d..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;
        }
 
@@ -320,10 +335,10 @@ trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore, int *svent)
        vec3_t original_avelocity;
        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);
 
        gravity = PRVM_clientedictfloat(tossent, gravity);
        if (!gravity)
@@ -332,21 +347,21 @@ trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore, int *svent)
 
        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;
 }
@@ -423,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;
@@ -472,20 +487,20 @@ 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_EDICTFIELDEDICT(ent, chainfield) = PRVM_EDICT_TO_PROG(chain);
@@ -508,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");
@@ -520,15 +535,15 @@ 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;
+               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)
@@ -570,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
@@ -683,11 +698,14 @@ static void VM_CL_getlight (void)
 //[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;
+       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_CreateFromQuakeEntity(&viewmodelmatrix, cl.csqc_vieworigin[0], cl.csqc_vieworigin[1], cl.csqc_vieworigin[2], cl.csqc_viewangles[0], cl.csqc_viewangles[1], cl.csqc_viewangles[2], cl_viewmodel_scale.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);
@@ -720,6 +738,7 @@ void VM_CL_R_ClearScene (void)
        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)
@@ -735,7 +754,7 @@ 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
@@ -750,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)
@@ -765,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)
@@ -1034,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;
 }
 
 //============================================================================
@@ -1169,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;
@@ -1181,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)
@@ -1231,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)
@@ -1331,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;
                }
@@ -1414,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);
@@ -1578,13 +1611,13 @@ static void VM_CL_makestatic (void)
 
                // 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.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);
@@ -1604,12 +1637,12 @@ static void VM_CL_makestatic (void)
                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)
@@ -2116,11 +2149,11 @@ void VM_CL_setattachment (void)
        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)
                {
-                       tagindex = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.client->skin, tagname);
+                       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);
                }
@@ -2139,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;
 }
@@ -2157,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;
@@ -2193,16 +2226,16 @@ void CL_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatri
                vec3_t left;
                vec3_t up;
                vec3_t origin;
-               VectorScale(prog->globals.client->v_forward, scale, forward);
-               VectorScale(prog->globals.client->v_right, -scale, left);
-               VectorScale(prog->globals.client->v_up, scale, up);
-               VectorCopy(ent->fields.client->origin, 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);
        }
 }
 
@@ -2285,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
@@ -2300,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));
                }
@@ -2361,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);
@@ -2901,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;
@@ -3006,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 +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++)
                {
@@ -3350,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
@@ -3420,36 +3453,36 @@ qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean
        prvm_edict_t            *enemy;
 
 // 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;
@@ -3467,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)
@@ -3483,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;
                }
 
@@ -3496,23 +3529,23 @@ 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;
 
        PRVM_clientedictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
 
@@ -3543,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");
@@ -3558,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;
@@ -3569,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;
 }
 
 /*
@@ -3627,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)
@@ -3792,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));
 }
 
@@ -3817,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)
@@ -3832,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));
 }
 
@@ -3850,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;
@@ -3872,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);
@@ -3894,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);
@@ -4000,7 +4033,7 @@ void VM_CL_RotateMoves(void)
         * 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;
@@ -4010,6 +4043,16 @@ void VM_CL_RotateMoves(void)
        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:
@@ -4381,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)