]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - clvm_cmds.c
a cosmetic change as suggested by div0:
[xonotic/darkplaces.git] / clvm_cmds.c
index dad081c209df3c6d65ecd8cfcefeb3c6320be008..b0effc637d37691ed2e5ab7ef13175fb16cdedfd 100644 (file)
@@ -1,12 +1,12 @@
 #include "prvm_cmds.h"
 #include "csprogs.h"
 #include "cl_collision.h"
+#include "r_shadow.h"
 
 //============================================================================
 // Client
 //[515]: unsolved PROBLEMS
 //- finish player physics code (cs_runplayerphysics)
-//- fix R_AddDynamicLight
 //- EntWasFreed ?
 //- RF_DEPTHHACK is not like it should be
 //- add builtin that sets cl.viewangles instead of reading "input_angles" global
@@ -18,6 +18,7 @@
 
 //[515]: really need new list ?
 char *vm_cl_extensions =
+"BX_WAL_SUPPORT "
 "DP_CON_SET "
 "DP_CON_SETA "
 "DP_CON_STARTMAP "
@@ -68,11 +69,13 @@ char *vm_cl_extensions =
 "DP_QC_RANDOMVEC "
 "DP_QC_SINCOSSQRTPOW "
 //"DP_QC_STRINGBUFFERS "       //[515]: not needed ?
+"DP_QC_STRFTIME "
 "DP_QC_STRINGCOLORFUNCTIONS "
 "DP_QC_TRACEBOX "
 //"DP_QC_TRACETOSS "
 "DP_QC_TRACE_MOVETYPE_HITMODEL "
 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
+"DP_QC_UNLIMITEDTEMPSTRINGS "
 "DP_QC_VECTORVECTORS "
 "DP_QUAKE2_MODEL "
 "DP_QUAKE2_SPRITE "
@@ -124,6 +127,7 @@ void CSQC_RelinkCSQCEntities (void);
 char *Key_GetBind (int key);
 model_t *CSQC_GetModelByIndex(int modelindex);
 model_t *CSQC_GetModelFromEntity(prvm_edict_t *ed);
+void CL_LinkEdict(prvm_edict_t *ed);
 
 
 
@@ -156,6 +160,7 @@ void VM_CL_setorigin (void)
        }
        org = PRVM_G_VECTOR(OFS_PARM1);
        VectorCopy (org, e->fields.client->origin);
+       CL_LinkEdict(e);
 }
 
 // #3 void(entity e, string m) setmodel
@@ -219,6 +224,8 @@ void VM_CL_setsize (void)
        VectorCopy (min, e->fields.client->mins);
        VectorCopy (max, e->fields.client->maxs);
        VectorSubtract (max, min, e->fields.client->size);
+
+       CL_LinkEdict(e);
 }
 
 // #8 void(entity e, float chan, string samp) sound
@@ -297,10 +304,8 @@ void VM_CL_traceline (void)
 // #19 void(string s) precache_sound
 void VM_CL_precache_sound (void)
 {
-       const char *n;
        VM_SAFEPARMCOUNT(1, VM_CL_precache_sound);
-       n = PRVM_G_STRING(OFS_PARM0);
-       S_PrecacheSound(n, true, false);
+       S_PrecacheSound(PRVM_G_STRING(OFS_PARM0), true, false);
 }
 
 // #20 void(string s) precache_model
@@ -567,104 +572,6 @@ void VM_CL_particle (void)
        CL_ParticleEffect(EFFECT_SVC_PARTICLE, count, org, org, dir, dir, NULL, color);
 }
 
-// #49 void(entity ent, float ideal_yaw, float speed_yaw) ChangeYaw
-void VM_CL_changeyaw (void)
-{
-       prvm_edict_t    *ent;
-       float                   ideal, current, move, speed;
-       VM_SAFEPARMCOUNT(3, VM_CL_changeyaw);
-
-       ent = PRVM_G_EDICT(OFS_PARM0);
-       if (ent == prog->edicts)
-       {
-               VM_Warning("changeyaw: can not modify world entity\n");
-               return;
-       }
-       if (ent->priv.server->free)
-       {
-               VM_Warning("changeyaw: can not modify free entity\n");
-               return;
-       }
-       current = ANGLEMOD(ent->fields.client->angles[1]);
-       ideal = PRVM_G_FLOAT(OFS_PARM1);
-       speed = PRVM_G_FLOAT(OFS_PARM2);
-
-       if (current == ideal)
-               return;
-       move = ideal - current;
-       if (ideal > current)
-       {
-               if (move >= 180)
-                       move = move - 360;
-       }
-       else
-       {
-               if (move <= -180)
-                       move = move + 360;
-       }
-       if (move > 0)
-       {
-               if (move > speed)
-                       move = speed;
-       }
-       else
-       {
-               if (move < -speed)
-                       move = -speed;
-       }
-
-       ent->fields.client->angles[1] = ANGLEMOD (current + move);
-}
-
-// #63 void(entity ent, float ideal_pitch, float speed_pitch) changepitch (DP_QC_CHANGEPITCH)
-void VM_CL_changepitch (void)
-{
-       prvm_edict_t            *ent;
-       float                           ideal, current, move, speed;
-       VM_SAFEPARMCOUNT(3, VM_CL_changepitch);
-
-       ent = PRVM_G_EDICT(OFS_PARM0);
-       if (ent == prog->edicts)
-       {
-               VM_Warning("changepitch: can not modify world entity\n");
-               return;
-       }
-       if (ent->priv.server->free)
-       {
-               VM_Warning("changepitch: can not modify free entity\n");
-               return;
-       }
-       current = ANGLEMOD( ent->fields.client->angles[0] );
-       ideal = PRVM_G_FLOAT(OFS_PARM1);
-       speed = PRVM_G_FLOAT(OFS_PARM2);
-
-       if (current == ideal)
-               return;
-       move = ideal - current;
-       if (ideal > current)
-       {
-               if (move >= 180)
-                       move = move - 360;
-       }
-       else
-       {
-               if (move <= -180)
-                       move = move + 360;
-       }
-       if (move > 0)
-       {
-               if (move > speed)
-                       move = speed;
-       }
-       else
-       {
-               if (move < -speed)
-                       move = -speed;
-       }
-
-       ent->fields.client->angles[0] = ANGLEMOD (current + move);
-}
-
 // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
 void VM_CL_tracetoss (void)
 {
@@ -765,17 +672,18 @@ qboolean csqc_usecsqclistener = false;//[515]: per-frame
 static void CSQC_R_RecalcView (void)
 {
        extern matrix4x4_t viewmodelmatrix;
-       viewmodelmatrix = identitymatrix;
-       r_view.matrix = identitymatrix;
        Matrix4x4_CreateFromQuakeEntity(&r_view.matrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], 1);
        Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], cl_viewmodel_scale.value);
 }
 
+void CL_RelinkLightFlashes(void);
 //#300 void() clearscene (EXT_CSQC)
 void VM_R_ClearScene (void)
 {
        VM_SAFEPARMCOUNT(0, VM_R_ClearScene);
+       // clear renderable entity and light lists
        r_refdef.numentities = 0;
+       r_refdef.numlights = 0;
 }
 
 //#301 void(float mask) addentities (EXT_CSQC)
@@ -788,8 +696,9 @@ void VM_R_AddEntities (void)
        VM_SAFEPARMCOUNT(1, VM_R_AddEntities);
        drawmask = (int)PRVM_G_FLOAT(OFS_PARM0);
        CSQC_RelinkAllEntities(drawmask);
+       CL_RelinkLightFlashes();
 
-       *prog->time = cl.time;
+       prog->globals.client->time = cl.time;
        for(i=1;i<prog->num_edicts;i++)
        {
                ed = &prog->edicts[i];
@@ -910,12 +819,26 @@ void VM_R_SetView (void)
        PRVM_G_FLOAT(OFS_RETURN) = 1;
 }
 
+extern void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit);
 //#304 void() renderscene (EXT_CSQC)
 void VM_R_RenderScene (void) //#134
 {
+       int i;
        VM_SAFEPARMCOUNT(0, VM_R_RenderScene);
-       // update all renderable network entities
-       CL_UpdateEntities();
+       // we need to update any RENDER_VIEWMODEL entities at this point because
+       // csqc supplies its own view matrix
+       for (i = 1;i < cl.num_entities;i++)
+       {
+               if (cl.entities_active[i])
+               {
+                       entity_t *ent = cl.entities + i;
+                       if ((ent->render.flags & RENDER_VIEWMODEL) || ent->state_current.tagentity)
+                               CL_UpdateNetworkEntity(ent, 32);
+               }
+       }
+       // and of course the engine viewmodel needs updating as well
+       CL_UpdateNetworkEntity(&cl.viewent, 32);
+       // now draw stuff!
        R_RenderView();
 }
 
@@ -923,14 +846,17 @@ void VM_R_RenderScene (void) //#134
 void VM_R_AddDynamicLight (void)
 {
        float           *pos, *col;
-       matrix4x4_t     tempmatrix;
+       matrix4x4_t     matrix;
        VM_SAFEPARMCOUNT(3, VM_R_AddDynamicLight);
 
+       // if we've run out of dlights, just return
+       if (r_refdef.numlights >= MAX_DLIGHTS)
+               return;
+
        pos = PRVM_G_VECTOR(OFS_PARM0);
        col = PRVM_G_VECTOR(OFS_PARM2);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
-       CL_AllocDlight(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), col[0], col[1], col[2], 500, 0, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       //CL_AllocDlight(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), col[0], col[1], col[2], 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       Matrix4x4_CreateFromQuakeEntity(&matrix, pos[0], pos[1], pos[2], 0, 0, 0, PRVM_G_FLOAT(OFS_PARM1));
+       R_RTLight_Update(&r_refdef.lights[r_refdef.numlights++], false, &matrix, col, -1, NULL, true, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
 }
 
 //============================================================================
@@ -1001,17 +927,17 @@ void VM_CL_getstati (void)
 void VM_CL_getstats (void)
 {
        int i;
-       char *t;
+       char t[17];
        VM_SAFEPARMCOUNT(1, VM_CL_getstats);
        i = (int)PRVM_G_FLOAT(OFS_PARM0);
        if(i < 0 || i > MAX_CL_STATS-4)
        {
+               PRVM_G_INT(OFS_RETURN) = OFS_NULL;
                VM_Warning("VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
                return;
        }
-       t = VM_GetTempString();
-       strlcpy(t, (char*)&cl.stats[i], 16);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
+       strlcpy(t, (char*)&cl.stats[i], sizeof(t));
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
 }
 
 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
@@ -1050,7 +976,7 @@ void VM_CL_modelnameforindex (void)
 
        VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex);
 
-       PRVM_G_INT(OFS_RETURN) = 0;
+       PRVM_G_INT(OFS_RETURN) = OFS_NULL;
        model = CSQC_GetModelByIndex((int)PRVM_G_FLOAT(OFS_PARM0));
        PRVM_G_INT(OFS_RETURN) = model ? PRVM_SetEngineString(model->name) : 0;
 }
@@ -1058,11 +984,9 @@ void VM_CL_modelnameforindex (void)
 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
 void VM_CL_particleeffectnum (void)
 {
-       const char      *n;
        int                     i;
        VM_SAFEPARMCOUNT(1, VM_CL_particleeffectnum);
-       n = PRVM_G_STRING(OFS_PARM0);
-       i = CL_ParticleEffectIndexForName(n);
+       i = CL_ParticleEffectIndexForName(PRVM_G_STRING(OFS_PARM0));
        if (i == 0)
                i = -1;
        PRVM_G_FLOAT(OFS_RETURN) = i;
@@ -1110,11 +1034,8 @@ void VM_CL_centerprint (void)
 //#342 string(float keynum) getkeybind (EXT_CSQC)
 void VM_CL_getkeybind (void)
 {
-       int i;
-
        VM_SAFEPARMCOUNT(1, VM_CL_getkeybind);
-       i = (int)PRVM_G_FLOAT(OFS_PARM0);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(Key_GetBind(i));
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0)));
 }
 
 //#343 void(float usecursor) setcursormode (EXT_CSQC)
@@ -1169,7 +1090,6 @@ void VM_CL_getplayerkey (void)
        int                     i;
        char            t[128];
        const char      *c;
-       char            *temp;
 
        VM_SAFEPARMCOUNT(2, VM_CL_getplayerkey);
 
@@ -1189,12 +1109,12 @@ void VM_CL_getplayerkey (void)
        else
                if(!strcasecmp(c, "frags"))
                        sprintf(t, "%i", cl.scores[i].frags);
-//     else
-//             if(!strcasecmp(c, "ping"))
-//                     sprintf(t, "%i", cl.scores[i].ping);
-//     else
-//             if(!strcasecmp(c, "entertime"))
-//                     sprintf(t, "%f", cl.scores[i].entertime);
+       else
+               if(!strcasecmp(c, "ping"))
+                       sprintf(t, "%i", cl.scores[i].qw_ping);
+       else
+               if(!strcasecmp(c, "entertime"))
+                       sprintf(t, "%f", cl.scores[i].qw_entertime);
        else
                if(!strcasecmp(c, "colors"))
                        sprintf(t, "%i", cl.scores[i].colors);
@@ -1209,9 +1129,7 @@ void VM_CL_getplayerkey (void)
                        sprintf(t, "%i", i+1);
        if(!t[0])
                return;
-       temp = VM_GetTempString();
-       strlcpy(temp, t, VM_STRINGTEMP_LENGTH);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(temp);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
 }
 
 //#349 float() isdemo (EXT_CSQC)
@@ -1305,15 +1223,7 @@ void VM_CL_ReadAngle (void)
 //#366 string() readstring (EXT_CSQC)
 void VM_CL_ReadString (void)
 {
-       char *t, *s;
-       t = VM_GetTempString();
-       s = MSG_ReadString();
-       PRVM_G_INT(OFS_RETURN) = 0;
-       if(s)
-       {
-               strlcpy(t, s, VM_STRINGTEMP_LENGTH);
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
-       }
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(MSG_ReadString());
 }
 
 //#367 float() readfloat (EXT_CSQC)
@@ -1373,7 +1283,7 @@ void VM_CL_te_explosionrgb (void)
        CL_FindNonSolidLocation(pos, pos2, 10);
        CL_ParticleExplosion(pos2);
        Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 350, PRVM_G_VECTOR(OFS_PARM1)[0], PRVM_G_VECTOR(OFS_PARM1)[1], PRVM_G_VECTOR(OFS_PARM1)[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_AllocLightFlash(NULL, &tempmatrix, 350, PRVM_G_VECTOR(OFS_PARM1)[0], PRVM_G_VECTOR(OFS_PARM1)[1], PRVM_G_VECTOR(OFS_PARM1)[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
 }
 
 // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
@@ -1499,7 +1409,7 @@ void VM_CL_te_customflash (void)
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
        Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM3)[0], PRVM_G_VECTOR(OFS_PARM3)[1], PRVM_G_VECTOR(OFS_PARM3)[2], PRVM_G_FLOAT(OFS_PARM1) / PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM2), 0, -1, true, 1, 0.25, 1, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_AllocLightFlash(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM3)[0], PRVM_G_VECTOR(OFS_PARM3)[1], PRVM_G_VECTOR(OFS_PARM3)[2], PRVM_G_FLOAT(OFS_PARM1) / PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM2), 0, -1, true, 1, 0.25, 1, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
 }
 
 // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
@@ -1642,7 +1552,7 @@ void VM_CL_te_explosion2 (void)
        color[1] = tempcolor[1] * (2.0f / 255.0f);
        color[2] = tempcolor[2] * (2.0f / 255.0f);
        Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_AllocLightFlash(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
        S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
 }
 
@@ -1758,10 +1668,10 @@ void VM_CL_getsurfacetexture(void)
 {
        model_t *model;
        msurface_t *surface;
-       PRVM_G_INT(OFS_RETURN) = 0;
+       PRVM_G_INT(OFS_RETURN) = OFS_NULL;
        if (!(model = CSQC_GetModelFromEntity(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
                return;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
 }
 
 // #438 float(entity e, vector p) getsurfacenearpoint
@@ -1851,11 +1761,11 @@ void VM_CL_setattachment (void)
        if (tagentity == NULL)
                tagentity = prog->edicts;
 
-       v = PRVM_GETEDICTFIELDVALUE(e, csqc_fieldoff_tag_entity);
+       v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
        if (v)
                v->edict = PRVM_EDICT_TO_PROG(tagentity);
 
-       v = PRVM_GETEDICTFIELDVALUE(e, csqc_fieldoff_tag_index);
+       v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
        if (v)
                v->_float = 0;
        if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
@@ -1930,13 +1840,13 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
        else
                tagmatrix = identitymatrix;
 
-       if ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_entity)) && val->edict)
+       if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
        { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
                attachloop = 0;
                do
                {
                        attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
-                       val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_index);
+                       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index);
 
                        model = CSQC_GetModelFromEntity(attachent);
 
@@ -1946,7 +1856,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                                attachmatrix = identitymatrix;
 
                        // apply transformation by child entity matrix
-                       val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
+                       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
                        if (val->_float == 0)
                                val->_float = 1;
                        Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], -ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], val->_float);
@@ -1962,22 +1872,22 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                        if (attachloop > 255) // prevent runaway looping
                                return 5;
                }
-               while ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_entity)) && val->edict);
+               while ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict);
        }
 
        // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
-       val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
+       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
        if (val->_float == 0)
                val->_float = 1;
        // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
        Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], -ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], val->_float);
        Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
 
-       if ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_renderflags)) && (RF_VIEWMODEL & (int)val->_float))
+       if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && (RF_VIEWMODEL & (int)val->_float))
        {// RENDER_VIEWMODEL magic
                Matrix4x4_Copy(&tagmatrix, out);
 
-               val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
+               val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
                if (val->_float == 0)
                        val->_float = 1;
 
@@ -2084,7 +1994,7 @@ void VM_WasFreed (void)
        VM_SAFEPARMCOUNT(1, VM_WasFreed);
 
        e = PRVM_G_EDICT(OFS_PARM0);
-       if (!e->priv.required->free || (e->priv.required->free && (e->priv.required->freetime < 2 || (*prog->time - e->priv.required->freetime) > 0.5 )))
+       if (!e->priv.required->free || (e->priv.required->free && (e->priv.required->freetime < 2 || (prog->globals.client->time - e->priv.required->freetime) > 0.5 )))
                PRVM_G_FLOAT(OFS_RETURN) = false;
        else
                PRVM_G_FLOAT(OFS_RETURN) = true;
@@ -2093,18 +2003,15 @@ void VM_WasFreed (void)
 void VM_CL_select_cube (void)
 {
        int             i;
-       int             chain_of;
        float   *mins2, *maxs2;
        prvm_edict_t    *ent, *chain;
        vec3_t  mins1, maxs1;
 
        VM_SAFEPARMCOUNT(2, VM_CL_select_cube);
 
-       // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
-       if(!prog->flag & PRVM_FE_CHAIN)
+       if (prog->fieldoffsets.chain < 0)
                PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
 
-       chain_of = PRVM_ED_FindField("chain")->ofs;
        chain = prog->edicts;
 
        mins2 = PRVM_G_VECTOR(OFS_PARM0);
@@ -2122,7 +2029,7 @@ void VM_CL_select_cube (void)
                        continue;
                if (maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2])
                        continue;
-               PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
+               PRVM_EDICTFIELDVALUE(ent,prog->fieldoffsets.chain)->edict = PRVM_NUM_FOR_EDICT(chain);
                chain = ent;
        }
 
@@ -2132,7 +2039,6 @@ void VM_CL_select_cube (void)
 void VM_CL_select_super (void)
 {
 /*     int             i;
-       int             chain_of;
        float   *v[8];
        prvm_edict_t    *ent, *chain;
        vec3_t  mins1, maxs1;
@@ -2141,11 +2047,9 @@ void VM_CL_select_super (void)
        for(i=0;i<8;i++)
                v[i] = PRVM_G_VECTOR(OFS_PARM0+i*3);
 
-       // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
-       if(!prog->flag & PRVM_FE_CHAIN)
+       if (prog->fieldoffsets.chain < 0)
                PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
 
-       chain_of = PRVM_ED_FindField("chain")->ofs;
        chain = prog->edicts;
 
        mins2 = PRVM_G_VECTOR(OFS_PARM0);
@@ -2163,7 +2067,7 @@ void VM_CL_select_super (void)
                        continue;
                if (maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2])
                        continue;
-               PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
+               PRVM_EDICTFIELDVALUE(ent,prog->fieldoffsets.chain)->edict = PRVM_NUM_FOR_EDICT(chain);
                chain = ent;
        }
 
@@ -2193,15 +2097,12 @@ static int Is_Text_Color (char c, char t)
 void VM_uncolorstring (void) //#170
 {
        const char      *in;
-       char            *out;
+       char            out[VM_STRINGTEMP_LENGTH];
        int                     k = 0, i = 0;
 
        VM_SAFEPARMCOUNT(1, VM_uncolorstring);
        in = PRVM_G_STRING(OFS_PARM0);
-       if(!in)
-               PRVM_ERROR ("VM_uncolorstring: %s: NULL\n", PRVM_NAME);
        VM_CheckEmptyString (in);
-       out = VM_GetTempString();
 
        while (in[k])
        {
@@ -2215,6 +2116,7 @@ void VM_uncolorstring (void) //#170
                ++k;
                ++i;
        }
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(out);
 }
 
 void VM_CL_selecttraceline (void)
@@ -2241,8 +2143,6 @@ void VM_charindex (void)
 {
        const char *s;
        s = PRVM_G_STRING(OFS_PARM0);
-       if(!s)
-               return;
        if((unsigned)PRVM_G_FLOAT(OFS_PARM1) > strlen(s))
                return;
        PRVM_G_FLOAT(OFS_RETURN) = (unsigned char)s[(int)PRVM_G_FLOAT(OFS_PARM1)];
@@ -2251,13 +2151,12 @@ void VM_charindex (void)
 //#223 string(float c, ...) chr2str (FTE_STRINGS)
 void VM_chr2str (void)
 {
-       char    *t;
+       char    t[128];
        int             i;
-       t = VM_GetTempString();
-       for(i=0;i<prog->argc;i++)
+       for(i = 0;i < prog->argc && i < (int)sizeof(t) - 1;i++)
                t[i] = (unsigned char)PRVM_G_FLOAT(OFS_PARM0+i*3);
        t[i] = 0;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
 }
 
 //#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
@@ -2323,7 +2222,7 @@ VM_cvar,                                  // #45 float(string s) cvar
 VM_localcmd,                           // #46 void(string s) localcmd
 VM_nextent,                                    // #47 entity(entity e) nextent
 VM_CL_particle,                                // #48 void(vector o, vector d, float color, float count) particle
-VM_CL_changeyaw,                       // #49 void(entity ent, float ideal_yaw, float speed_yaw) ChangeYaw
+VM_changeyaw,                          // #49 void(entity ent) ChangeYaw
 NULL,                                          // #50
 VM_vectoangles,                                // #51 vector(vector v) vectoangles
 0,                     // #52 void(float to, float f) WriteByte
@@ -2337,7 +2236,7 @@ VM_vectoangles,                           // #51 vector(vector v) vectoangles
 VM_sin,                                                // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
 VM_cos,                                                // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
 VM_sqrt,                                       // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
-VM_CL_changepitch,                     // #63 void(entity ent, float ideal_pitch, float speed_pitch) changepitch (DP_QC_CHANGEPITCH)
+VM_changepitch,                                // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
 VM_CL_tracetoss,                       // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
 VM_etos,                                       // #65 string(entity ent) etos (DP_QC_ETOS)
 NULL,                                          // #66
@@ -2606,7 +2505,7 @@ VM_atan2,                                 // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2T
 VM_tan,                                                // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
 VM_strlennocol,                                // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
 VM_strdecolorize,                      // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS)
-NULL,                                          // #478
+VM_strftime,                           // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
 NULL,                                          // #479
 e10, e10                       // #480-499 (LordHavoc)
 };