]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - svvm_cmds.c
if the two mtimes are identical, also use the max interval as it's better to have...
[xonotic/darkplaces.git] / svvm_cmds.c
index 21a74c0148c0df8fa725f0486da1ed30f26b7eeb..c0ed230ae2e0a0c5883b1b0f292add128ea6cd91 100644 (file)
@@ -8,7 +8,7 @@
 
 
 
-char *vm_sv_extensions =
+const char *vm_sv_extensions =
 "BX_WAL_SUPPORT "
 "DP_BUTTONCHAT "
 "DP_BUTTONUSE "
@@ -19,10 +19,17 @@ char *vm_sv_extensions =
 "DP_CON_SET "
 "DP_CON_SETA "
 "DP_CON_STARTMAP "
-"DP_CSQC_ENTITYNOCULL "
+"DP_CRYPTO "
+"DP_CSQC_BINDMAPS "
+"DP_CSQC_ENTITYWORLDOBJECT "
+"DP_CSQC_ENTITYMODELLIGHT "
 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
 "DP_CSQC_MULTIFRAME_INTERPOLATION "
+"DP_CSQC_BOXPARTICLES "
 "DP_CSQC_SPAWNPARTICLE "
+"DP_CSQC_QUERYRENDERENTITY "
+"DP_CSQC_ROTATEMOVES "
+"DP_CSQC_SETPAUSE "
 "DP_EF_ADDITIVE "
 "DP_EF_BLUE "
 "DP_EF_DOUBLESIDED "
@@ -45,6 +52,7 @@ char *vm_sv_extensions =
 "DP_ENT_GLOWMOD "
 "DP_ENT_LOWPRECISION "
 "DP_ENT_SCALE "
+"DP_ENT_TRAILEFFECTNUM "
 "DP_ENT_VIEWMODEL "
 "DP_GECKO_SUPPORT "
 "DP_GFX_EXTERNALTEXTURES "
@@ -54,6 +62,10 @@ char *vm_sv_extensions =
 "DP_GFX_QUAKE3MODELTAGS "
 "DP_GFX_SKINFILES "
 "DP_GFX_SKYBOX "
+"DP_GFX_FONTS "
+"DP_GFX_FONTS_FREETYPE "
+"DP_UTF8 "
+"DP_FONT_VARIABLEWIDTH "
 "DP_HALFLIFE_MAP "
 "DP_HALFLIFE_MAP_CVAR "
 "DP_HALFLIFE_SPRITE "
@@ -63,6 +75,7 @@ char *vm_sv_extensions =
 "DP_LITSUPPORT "
 "DP_MONSTERWALK "
 "DP_MOVETYPEBOUNCEMISSILE "
+"DP_MOVETYPEFLYWORLDONLY "
 "DP_MOVETYPEFOLLOW "
 "DP_NULL_MODEL "
 "DP_QC_ASINACOSATANATAN2TAN "
@@ -75,6 +88,8 @@ char *vm_sv_extensions =
 "DP_QC_CVAR_DESCRIPTION "
 "DP_QC_CVAR_STRING "
 "DP_QC_CVAR_TYPE "
+"DP_QC_DIGEST "
+"DP_QC_DIGEST_SHA256 "
 "DP_QC_EDICT_NUM "
 "DP_QC_ENTITYDATA "
 "DP_QC_ENTITYSTRING "
@@ -95,6 +110,7 @@ char *vm_sv_extensions =
 "DP_QC_GETTAGINFO_BONEPROPERTIES "
 "DP_QC_GETTIME "
 "DP_QC_GETTIME_CDTRACK "
+"DP_QC_I18N "
 "DP_QC_LOG "
 "DP_QC_MINMAXBOUND "
 "DP_QC_MULTIPLETEMPSTRINGS "
@@ -117,6 +133,7 @@ char *vm_sv_extensions =
 "DP_QC_UNLIMITEDTEMPSTRINGS "
 "DP_QC_URI_ESCAPE "
 "DP_QC_URI_GET "
+"DP_QC_URI_POST "
 "DP_QC_VECTOANGLES_WITH_ROLL "
 "DP_QC_VECTORVECTORS "
 "DP_QC_WHICHPACK "
@@ -128,17 +145,24 @@ char *vm_sv_extensions =
 "DP_SKELETONOBJECTS "
 "DP_SND_DIRECTIONLESSATTNNONE "
 "DP_SND_FAKETRACKS "
+"DP_SND_SOUND7_WIP1 "
+"DP_SND_SOUND7_WIP2 "
 "DP_SND_OGGVORBIS "
 "DP_SND_SETPARAMS "
 "DP_SND_STEREOWAV "
+"DP_SND_GETSOUNDTIME "
+"DP_VIDEO_DPV "
+"DP_VIDEO_SUBTITLES "
 "DP_SOLIDCORPSE "
 "DP_SPRITE32 "
 "DP_SV_BOTCLIENT "
 "DP_SV_BOUNCEFACTOR "
+"DP_SV_CLIENTCAMERA "
 "DP_SV_CLIENTCOLORS "
 "DP_SV_CLIENTNAME "
 "DP_SV_CMD "
 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
+"DP_SV_DISCARDABLEDEMO "
 "DP_SV_DRAWONLYTOCLIENT "
 "DP_SV_DROPCLIENT "
 "DP_SV_EFFECT "
@@ -152,6 +176,7 @@ char *vm_sv_extensions =
 "DP_SV_PING "
 "DP_SV_PING_PACKETLOSS "
 "DP_SV_PLAYERPHYSICS "
+"DP_PHYSICS_ODE "
 "DP_SV_POINTPARTICLES "
 "DP_SV_POINTSOUND "
 "DP_SV_PRECACHEANYTIME "
@@ -225,7 +250,7 @@ static void VM_SV_setorigin (void)
                return;
        }
        org = PRVM_G_VECTOR(OFS_PARM1);
-       VectorCopy (org, e->fields.server->origin);
+       VectorCopy (org, PRVM_serveredictvector(e, origin));
        SV_LinkEdict(e);
 }
 
@@ -239,9 +264,9 @@ static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rot
                        PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
 
 // set derived values
-       VectorCopy (min, e->fields.server->mins);
-       VectorCopy (max, e->fields.server->maxs);
-       VectorSubtract (max, min, e->fields.server->size);
+       VectorCopy (min, PRVM_serveredictvector(e, mins));
+       VectorCopy (max, PRVM_serveredictvector(e, maxs));
+       VectorSubtract (max, min, PRVM_serveredictvector(e, size));
 
        SV_LinkEdict(e);
 }
@@ -308,8 +333,8 @@ static void VM_SV_setmodel (void)
                return;
        }
        i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
-       e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
-       e->fields.server->modelindex = i;
+       PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
+       PRVM_serveredictfloat(e, modelindex) = i;
 
        mod = SV_GetModelByIndex(i);
 
@@ -492,20 +517,39 @@ static void VM_SV_sound (void)
        int                     channel;
        prvm_edict_t            *entity;
        int             volume;
+       int flags;
        float attenuation;
+       float pitchchange;
 
-       VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
+       VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
 
        entity = PRVM_G_EDICT(OFS_PARM0);
        channel = (int)PRVM_G_FLOAT(OFS_PARM1);
        sample = PRVM_G_STRING(OFS_PARM2);
        volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
-       attenuation = PRVM_G_FLOAT(OFS_PARM4);
        if (prog->argc < 5)
        {
                Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
                attenuation = 1;
        }
+       else
+               attenuation = PRVM_G_FLOAT(OFS_PARM4);
+       if (prog->argc < 6)
+               pitchchange = 0;
+       else
+               pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
+
+       if (prog->argc < 7)
+       {
+               flags = 0;
+               if(channel >= 8 && channel <= 15) // weird QW feature
+               {
+                       flags |= CHANFLAG_RELIABLE;
+                       channel -= 8;
+               }
+       }
+       else
+               flags = PRVM_G_FLOAT(OFS_PARM6);
 
        if (volume < 0 || volume > 255)
        {
@@ -519,13 +563,15 @@ static void VM_SV_sound (void)
                return;
        }
 
-       if (channel < 0 || channel > 7)
+       channel = CHAN_USER2ENGINE(channel);
+
+       if (!IS_CHAN(channel))
        {
-               VM_Warning("SV_StartSound: channel must be in range 0-7\n");
+               VM_Warning("SV_StartSound: channel must be in range 0-127\n");
                return;
        }
 
-       SV_StartSound (entity, channel, sample, volume, attenuation);
+       SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
 }
 
 /*
@@ -543,14 +589,16 @@ static void VM_SV_pointsound(void)
        const char      *sample;
        int             volume;
        float           attenuation;
+       float           pitchchange;
        vec3_t          org;
 
-       VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
+       VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
 
        VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
        sample = PRVM_G_STRING(OFS_PARM1);
        volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
        attenuation = PRVM_G_FLOAT(OFS_PARM3);
+       pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
 
        if (volume < 0 || volume > 255)
        {
@@ -564,7 +612,7 @@ static void VM_SV_pointsound(void)
                return;
        }
 
-       SV_StartPointSound (org, sample, volume, attenuation);
+       SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
 }
 
 /*
@@ -650,40 +698,37 @@ static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
        vec3_t original_velocity;
        vec3_t original_angles;
        vec3_t original_avelocity;
-       prvm_eval_t *val;
        trace_t trace;
 
-       VectorCopy(tossent->fields.server->origin   , original_origin   );
-       VectorCopy(tossent->fields.server->velocity , original_velocity );
-       VectorCopy(tossent->fields.server->angles   , original_angles   );
-       VectorCopy(tossent->fields.server->avelocity, original_avelocity);
+       VectorCopy(PRVM_serveredictvector(tossent, origin)   , original_origin   );
+       VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
+       VectorCopy(PRVM_serveredictvector(tossent, angles)   , original_angles   );
+       VectorCopy(PRVM_serveredictvector(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_serveredictfloat(tossent, gravity);
+       if (!gravity)
+               gravity = 1.0f;
        gravity *= sv_gravity.value * 0.025;
 
        for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
        {
                SV_CheckVelocity (tossent);
-               tossent->fields.server->velocity[2] -= gravity;
-               VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
-               VectorScale (tossent->fields.server->velocity, 0.05, move);
-               VectorAdd (tossent->fields.server->origin, move, end);
-               trace = SV_TraceBox(tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
-               VectorCopy (trace.endpos, tossent->fields.server->origin);
-               tossent->fields.server->velocity[2] -= gravity;
+               PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
+               VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
+               VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
+               VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
+               trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
+               VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
+               PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
 
                if (trace.fraction < 1)
                        break;
        }
 
-       VectorCopy(original_origin   , tossent->fields.server->origin   );
-       VectorCopy(original_velocity , tossent->fields.server->velocity );
-       VectorCopy(original_angles   , tossent->fields.server->angles   );
-       VectorCopy(original_avelocity, tossent->fields.server->avelocity);
+       VectorCopy(original_origin   , PRVM_serveredictvector(tossent, origin)   );
+       VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
+       VectorCopy(original_angles   , PRVM_serveredictvector(tossent, angles)   );
+       VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
 
        return trace;
 }
@@ -740,14 +785,14 @@ static int VM_SV_newcheckclient (int check)
                // look up the client's edict
                ent = PRVM_EDICT_NUM(i);
                // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
-               if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
+               if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
                        continue;
                // found a valid client (possibly the same one again)
                break;
        }
 
 // get the PVS for the entity
-       VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
+       VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
        checkpvsbytes = 0;
        if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
                checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
@@ -787,15 +832,15 @@ static void VM_SV_checkclient (void)
 
        // return check if it might be visible
        ent = PRVM_EDICT_NUM(sv.lastcheck);
-       if (ent->priv.server->free || ent->fields.server->health <= 0)
+       if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
        {
                VM_RETURN_EDICT(prog->edicts);
                return;
        }
 
        // if current entity can't possibly see the check entity, return 0
-       self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
-       VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
+       self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
+       VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
        if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
        {
                c_notvis++;
@@ -856,7 +901,7 @@ static void VM_SV_checkpvs (void)
                PRVM_G_FLOAT(OFS_RETURN) = 2;
                return;
        }
-       PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
+       PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
 #else
        // using fat PVS like FTEQW does (slow)
        if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
@@ -872,7 +917,7 @@ static void VM_SV_checkpvs (void)
                PRVM_G_FLOAT(OFS_RETURN) = 2;
                return;
        }
-       PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
+       PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
 #endif
 }
 
@@ -962,23 +1007,23 @@ static void VM_SV_findradius (void)
                prog->xfunction->builtinsprofile++;
                // 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.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
+               if (PRVM_serveredictfloat(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.server->origin, eorg);
+               VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
                if (sv_gameplayfix_findradiusdistancetobox.integer)
                {
-                       eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
-                       eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
-                       eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
+                       eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
+                       eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
+                       eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
                }
                else
-                       VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
+                       VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(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;
                }
        }
@@ -1020,7 +1065,7 @@ static void VM_SV_walkmove (void)
        // assume failure if it returns early
        PRVM_G_FLOAT(OFS_RETURN) = 0;
 
-       ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
+       ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
        if (ent == prog->edicts)
        {
                VM_Warning("walkmove: can not modify world entity\n");
@@ -1035,7 +1080,7 @@ static void VM_SV_walkmove (void)
        dist = PRVM_G_FLOAT(OFS_PARM1);
        settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
 
-       if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
+       if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
                return;
 
        yaw = yaw*M_PI*2 / 360;
@@ -1046,14 +1091,14 @@ static void VM_SV_walkmove (void)
 
 // save program state, because SV_movestep may call other progs
        oldf = prog->xfunction;
-       oldself = prog->globals.server->self;
+       oldself = PRVM_serverglobaledict(self);
 
        PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
 
 
 // restore program state
        prog->xfunction = oldf;
-       prog->globals.server->self = oldself;
+       PRVM_serverglobaledict(self) = oldself;
 }
 
 /*
@@ -1063,6 +1108,7 @@ VM_SV_droptofloor
 void() droptofloor
 ===============
 */
+
 static void VM_SV_droptofloor (void)
 {
        prvm_edict_t            *ent;
@@ -1074,7 +1120,7 @@ static void VM_SV_droptofloor (void)
        // assume failure if it returns early
        PRVM_G_FLOAT(OFS_RETURN) = 0;
 
-       ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
+       ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
        if (ent == prog->edicts)
        {
                VM_Warning("droptofloor: can not modify world entity\n");
@@ -1086,37 +1132,40 @@ static void VM_SV_droptofloor (void)
                return;
        }
 
-       VectorCopy (ent->fields.server->origin, end);
+       VectorCopy (PRVM_serveredictvector(ent, origin), end);
        end[2] -= 256;
 
        if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
-               SV_UnstickEntity(ent);
+               if (sv_gameplayfix_unstickentities.integer)
+                       SV_UnstickEntity(ent);
 
-       trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
+       trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
        if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
        {
                vec3_t offset, org;
-               VectorSet(offset, 0.5f * (ent->fields.server->mins[0] + ent->fields.server->maxs[0]), 0.5f * (ent->fields.server->mins[1] + ent->fields.server->maxs[1]), ent->fields.server->mins[2]);
-               VectorAdd(ent->fields.server->origin, offset, org);
+               VectorSet(offset, 0.5f * (PRVM_serveredictvector(ent, mins)[0] + PRVM_serveredictvector(ent, maxs)[0]), 0.5f * (PRVM_serveredictvector(ent, mins)[1] + PRVM_serveredictvector(ent, maxs)[1]), PRVM_serveredictvector(ent, mins)[2]);
+               VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
                trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
                VectorSubtract(trace.endpos, offset, trace.endpos);
                if (trace.startsolid)
                {
-                       Con_DPrintf("droptofloor at %f %f %f - COULD NOT FIX BADLY PLACED ENTITY\n", ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2]);
-                       SV_UnstickEntity(ent);
+                       Con_DPrintf("droptofloor at %f %f %f - COULD NOT FIX BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
+                       if (sv_gameplayfix_unstickentities.integer)
+                               SV_UnstickEntity(ent);
                        SV_LinkEdict(ent);
-                       ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
-                       ent->fields.server->groundentity = 0;
+                       PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
+                       PRVM_serveredictedict(ent, groundentity) = 0;
                        PRVM_G_FLOAT(OFS_RETURN) = 1;
                }
                else if (trace.fraction < 1)
                {
-                       Con_DPrintf("droptofloor at %f %f %f - FIXED BADLY PLACED ENTITY\n", ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2]);
-                       VectorCopy (trace.endpos, ent->fields.server->origin);
-                       SV_UnstickEntity(ent);
+                       Con_DPrintf("droptofloor at %f %f %f - FIXED BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
+                       VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
+                       if (sv_gameplayfix_unstickentities.integer)
+                               SV_UnstickEntity(ent);
                        SV_LinkEdict(ent);
-                       ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
-                       ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
+                       PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
+                       PRVM_serveredictedict(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;
@@ -1127,10 +1176,10 @@ static void VM_SV_droptofloor (void)
                if (trace.fraction != 1)
                {
                        if (trace.fraction < 1)
-                               VectorCopy (trace.endpos, ent->fields.server->origin);
+                               VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
                        SV_LinkEdict(ent);
-                       ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
-                       ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
+                       PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
+                       PRVM_serveredictedict(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;
@@ -1216,12 +1265,12 @@ static void VM_SV_aim (void)
        int             i, j;
        trace_t tr;
        float   dist, bestdist;
-       float   speed;
+       //float speed;
 
        VM_SAFEPARMCOUNT(2, VM_SV_aim);
 
        // assume failure if it returns early
-       VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
+       VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
        // if sv_aim is so high it can't possibly accept anything, skip out early
        if (sv_aim.value >= 1)
                return;
@@ -1237,19 +1286,19 @@ static void VM_SV_aim (void)
                VM_Warning("aim: can not use free entity\n");
                return;
        }
-       speed = PRVM_G_FLOAT(OFS_PARM1);
+       //speed = PRVM_G_FLOAT(OFS_PARM1);
 
-       VectorCopy (ent->fields.server->origin, start);
+       VectorCopy (PRVM_serveredictvector(ent, origin), start);
        start[2] += 20;
 
 // try sending a trace straight
-       VectorCopy (prog->globals.server->v_forward, dir);
+       VectorCopy (PRVM_serverglobalvector(v_forward), dir);
        VectorMA (start, 2048, dir, end);
        tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
-       if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
-       && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
+       if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
+       && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
        {
-               VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
+               VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
                return;
        }
 
@@ -1263,18 +1312,18 @@ static void VM_SV_aim (void)
        for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
        {
                prog->xfunction->builtinsprofile++;
-               if (check->fields.server->takedamage != DAMAGE_AIM)
+               if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
                        continue;
                if (check == ent)
                        continue;
-               if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
+               if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
                        continue;       // don't aim at teammate
                for (j=0 ; j<3 ; j++)
-                       end[j] = check->fields.server->origin[j]
-                       + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
+                       end[j] = PRVM_serveredictvector(check, origin)[j]
+                       + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
                VectorSubtract (end, start, dir);
                VectorNormalize (dir);
-               dist = DotProduct (dir, prog->globals.server->v_forward);
+               dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
                if (dist < bestdist)
                        continue;       // to far to turn
                tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
@@ -1287,9 +1336,9 @@ static void VM_SV_aim (void)
 
        if (bestent)
        {
-               VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
-               dist = DotProduct (dir, prog->globals.server->v_forward);
-               VectorScale (prog->globals.server->v_forward, dist, end);
+               VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
+               dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
+               VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
                end[2] = dir[2];
                VectorNormalize (end);
                VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
@@ -1327,7 +1376,7 @@ sizebuf_t *WriteDest (void)
                return &sv.datagram;
 
        case MSG_ONE:
-               ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
+               ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
                entnum = PRVM_NUM_FOR_EDICT(ent);
                if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
                {
@@ -1349,7 +1398,7 @@ sizebuf_t *WriteDest (void)
                return sv.writeentitiestoclient_msg;
        }
 
-       return NULL;
+       //return NULL;
 }
 
 static void VM_SV_WriteByte (void)
@@ -1454,7 +1503,7 @@ static void VM_SV_makestatic (void)
        if (prog->argc >= 1)
                ent = PRVM_G_EDICT(OFS_PARM0);
        else
-               ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
+               ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
        if (ent == prog->edicts)
        {
                VM_Warning("makestatic: can not modify world entity\n");
@@ -1467,34 +1516,34 @@ static void VM_SV_makestatic (void)
        }
 
        large = false;
-       if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
+       if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
                large = true;
 
        if (large)
        {
                MSG_WriteByte (&sv.signon,svc_spawnstatic2);
-               MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
-               MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
+               MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
+               MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
        }
        else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
        {
                MSG_WriteByte (&sv.signon,svc_spawnstatic);
-               MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
-               MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
+               MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
+               MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
        }
        else
        {
                MSG_WriteByte (&sv.signon,svc_spawnstatic);
-               MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
-               MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
+               MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
+               MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
        }
 
-       MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
-       MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
+       MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
+       MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
        for (i=0 ; i<3 ; i++)
        {
-               MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
-               MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
+               MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
+               MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
        }
 
 // throw the entity away now
@@ -1527,7 +1576,7 @@ static void VM_SV_setspawnparms (void)
        // copy spawn parms out of the client_t
        client = svs.clients + i-1;
        for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
-               (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
+               (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
 }
 
 /*
@@ -1696,7 +1745,7 @@ static void VM_SV_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);
        SV_LinkEdict(out);
 }
 
@@ -1714,7 +1763,6 @@ static void VM_SV_setcolor (void)
 {
        client_t *client;
        int entnum, i;
-       prvm_eval_t *val;
 
        VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
        entnum = PRVM_G_EDICTNUM(OFS_PARM0);
@@ -1729,9 +1777,8 @@ static void VM_SV_setcolor (void)
        client = svs.clients + entnum-1;
        if (client->edict)
        {
-               if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
-                       val->_float = i;
-               client->edict->fields.server->team = (i & 15) + 1;
+               PRVM_serveredictfloat(client->edict, clientcolors) = i;
+               PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
        }
        client->colors = i;
        if (client->old_colors != client->colors)
@@ -2279,8 +2326,8 @@ static void VM_SV_setattachment (void)
        prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
        prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
        const char *tagname = PRVM_G_STRING(OFS_PARM2);
-       prvm_eval_t *v;
        dp_model_t *model;
+       int tagindex;
        VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
 
        if (e == prog->edicts)
@@ -2297,25 +2344,23 @@ static void VM_SV_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);
+       tagindex = 0;
 
-       v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
-       if (v)
-               v->_float = 0;
        if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
        {
                model = SV_GetModelFromEdict(tagentity);
                if (model)
                {
-                       v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
-                       if (v->_float == 0)
+                       tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(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_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
+       PRVM_serveredictfloat(e, tag_index) = tagindex;
 }
 
 /////////////////////////////////////////
@@ -2325,11 +2370,11 @@ int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
 {
        int i;
 
-       i = (int)e->fields.server->modelindex;
+       i = (int)PRVM_serveredictfloat(e, modelindex);
        if (i < 1 || i >= MAX_MODELS)
                return -1;
 
-       return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)e->fields.server->skin, tagname);
+       return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
 }
 
 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
@@ -2343,7 +2388,7 @@ int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, cons
 
        if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
        {
-               r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
+               r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
 
                if(!r) // success?
                        *parentindex += 1;
@@ -2356,21 +2401,19 @@ int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, cons
 
 void SV_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_serveredictfloat(ent, scale);
+       if (!scale)
+               scale = 1.0f;
        
        if (viewmatrix)
-               Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + ent->fields.server->view_ofs[2], ent->fields.server->v_angle[0], ent->fields.server->v_angle[1], ent->fields.server->v_angle[2], scale * cl_viewmodel_scale.value);
+               Matrix4x4_CreateFromQuakeEntity(out, PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2] + PRVM_serveredictvector(ent, view_ofs)[2], PRVM_serveredictvector(ent, v_angle)[0], PRVM_serveredictvector(ent, v_angle)[1], PRVM_serveredictvector(ent, v_angle)[2], scale * cl_viewmodel_scale.value);
        else
        {
                pitchsign = SV_GetPitchSign(ent);
-               Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], pitchsign * ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], scale);
+               Matrix4x4_CreateFromQuakeEntity(out, PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], pitchsign * PRVM_serveredictvector(ent, angles)[0], PRVM_serveredictvector(ent, angles)[1], PRVM_serveredictvector(ent, angles)[2], scale);
        }
 }
 
@@ -2401,7 +2444,6 @@ extern cvar_t cl_bobup;
 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
 {
        int ret;
-       prvm_eval_t *val;
        int modelindex, attachloop;
        matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
        dp_model_t *model;
@@ -2413,7 +2455,7 @@ int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
        if (ent->priv.server->free)
                return 2;
 
-       modelindex = (int)ent->fields.server->modelindex;
+       modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
        if (modelindex <= 0 || modelindex >= MAX_MODELS)
                return 3;
 
@@ -2439,10 +2481,10 @@ int SV_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_serveredictedict(ent, tag_entity))
                {
-                       tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
-                       ent = PRVM_EDICT_NUM(val->edict);
+                       tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
+                       ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
                }
                else
                        break;
@@ -2450,17 +2492,17 @@ int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
        }
 
        // RENDER_VIEWMODEL magic
-       if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
+       if (PRVM_serveredictedict(ent, viewmodelforclient))
        {
                Matrix4x4_Copy(&tagmatrix, out);
-               ent = PRVM_EDICT_NUM(val->edict);
+               ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
 
                SV_GetEntityMatrix(ent, &entitymatrix, true);
                Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
 
                /*
                // Cl_bob, ported from rendering code
-               if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
+               if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
                {
                        double bob, cycle;
                        // LordHavoc: this code is *weird*, but not replacable (I think it
@@ -2475,7 +2517,7 @@ int SV_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.server->velocity[0]*ent->fields.server->velocity[0] + ent->fields.server->velocity[1]*ent->fields.server->velocity[1])*cl_bob.value;
+                       bob = sqrt(PRVM_serveredictvector(ent, velocity)[0]*PRVM_serveredictvector(ent, velocity)[0] + PRVM_serveredictvector(ent, velocity)[1]*PRVM_serveredictvector(ent, velocity)[1])*cl_bob.value;
                        bob = bob*0.3 + bob*0.7*cycle;
                        Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
                }
@@ -2531,7 +2573,6 @@ static void VM_SV_gettaginfo (void)
        int parentindex;
        const char *tagname;
        int returncode;
-       prvm_eval_t *val;
        vec3_t fo, le, up, trans;
        const dp_model_t *model;
 
@@ -2541,8 +2582,8 @@ static void VM_SV_gettaginfo (void)
        tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
 
        returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
-       Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
-       VectorScale(le, -1, prog->globals.server->v_right);
+       Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
+       VectorScale(le, -1, PRVM_serverglobalvector(v_right));
        model = SV_GetModelFromEdict(e);
        VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
        VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
@@ -2550,18 +2591,12 @@ static void VM_SV_gettaginfo (void)
        SV_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_serverglobalfloat(gettaginfo_parent) = parentindex;
+       PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(tagname) : 0;
+       VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
+       VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
+       VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
+       VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
 
        switch(returncode)
        {
@@ -2692,8 +2727,8 @@ static void VM_SV_setmodelindex (void)
                return;
        }
 
-       e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
-       e->fields.server->modelindex = i;
+       PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
+       PRVM_serveredictfloat(e, modelindex) = i;
 
        mod = SV_GetModelByIndex(i);
 
@@ -2825,13 +2860,13 @@ static void VM_SV_skel_create(void)
                        break;
        if (i == MAX_EDICTS)
                return;
-       prog->skeletons[i] = skeleton = Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
+       prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
+       PRVM_G_FLOAT(OFS_RETURN) = i + 1;
        skeleton->model = model;
        skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
        // initialize to identity matrices
        for (i = 0;i < skeleton->model->num_bones;i++)
                skeleton->relativetransforms[i] = identitymatrix;
-       PRVM_G_FLOAT(OFS_RETURN) = i + 1;
 }
 
 // #264 float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // (FTE_CSQC_SKELETONOBJECTS) blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
@@ -2842,8 +2877,8 @@ static void VM_SV_skel_build(void)
        prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
        int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
        float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
-       int firstbone = PRVM_G_FLOAT(OFS_PARM4);
-       int lastbone = PRVM_G_FLOAT(OFS_PARM5);
+       int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
+       int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
        dp_model_t *model = SV_GetModelByIndex(modelindex);
        float blendfrac;
        int numblends;
@@ -2938,18 +2973,18 @@ static void VM_SV_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));
 }
 
@@ -2963,9 +2998,9 @@ static void VM_SV_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)
@@ -2978,9 +3013,9 @@ static void VM_SV_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));
 }
 
@@ -2996,9 +3031,9 @@ static void VM_SV_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;
@@ -3018,9 +3053,9 @@ static void VM_SV_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);
@@ -3040,9 +3075,9 @@ static void VM_SV_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);
@@ -3637,7 +3672,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 = #513; (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)
@@ -3657,16 +3692,16 @@ VM_loadfromdata,                                // #529
 VM_loadfromfile,                               // #530
 VM_SV_setpause,                                        // #531 void(float pause) setpause = #531;
 VM_log,                                                        // #532
-NULL,                                                  // #533
-NULL,                                                  // #534
+VM_getsoundtime,                               // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
+VM_soundlength,                                        // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
 NULL,                                                  // #535
 NULL,                                                  // #536
 NULL,                                                  // #537
 NULL,                                                  // #538
 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
@@ -3755,6 +3790,16 @@ VM_sprintf,                     // #627 string sprintf(string format, ...)
 VM_getsurfacenumtriangles,             // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
 VM_getsurfacetriangle,                 // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
 NULL,                                                  // #630
+NULL,                                                  // #631
+NULL,                                                  // #632
+NULL,                                                  // #633
+NULL,                                                  // #634
+NULL,                                                  // #635
+NULL,                                                  // #636
+NULL,                                                  // #637
+NULL,                                                  // #638
+VM_digest_hex,                                         // #639
+NULL,                                                  // #640
 };
 
 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
@@ -3767,10 +3812,10 @@ void VM_SV_Cmd_Init(void)
 void VM_SV_Cmd_Reset(void)
 {
        World_End(&sv.world);
-       if(prog->funcoffsets.SV_Shutdown)
+       if(PRVM_serverfunction(SV_Shutdown))
        {
-               func_t s = prog->funcoffsets.SV_Shutdown;
-               prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
+               func_t s = PRVM_serverfunction(SV_Shutdown);
+               PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
                PRVM_ExecuteProgram(s,"SV_Shutdown() required");
        }