]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - clvm_cmds.c
added DP_QC_STRFTIME extension
[xonotic/darkplaces.git] / clvm_cmds.c
index 4f9f3680f81c77686a4cadb93bed75f1dafceb14..0c52ef5f021c4061338897aa38f1166ef384af47 100644 (file)
@@ -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 "
@@ -49,6 +50,7 @@ char *vm_cl_extensions =
 "DP_MONSTERWALK "
 "DP_MOVETYPEBOUNCEMISSILE "
 "DP_MOVETYPEFOLLOW "
+"DP_QC_ASINACOSATANATAN2TAN "
 "DP_QC_CHANGEPITCH "
 "DP_QC_COPYENTITY "
 "DP_QC_CVAR_STRING "
@@ -67,10 +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 "
@@ -117,10 +122,12 @@ void PF_registercvar (void);
 int Sbar_GetPlayer (int index);
 void Sbar_SortFrags (void);
 void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius);
-void CL_ExpandCSQCEntities(int num);
 void CSQC_RelinkAllEntities (int drawmask);
 void CSQC_RelinkCSQCEntities (void);
 char *Key_GetBind (int key);
+model_t *CSQC_GetModelByIndex(int modelindex);
+model_t *CSQC_GetModelFromEntity(prvm_edict_t *ed);
+
 
 
 
@@ -166,25 +173,27 @@ void VM_CL_setmodel (void)
 
        e = PRVM_G_EDICT(OFS_PARM0);
        m = PRVM_G_STRING(OFS_PARM1);
-       for(i=0;i<MAX_MODELS;i++)
-               if(!cl.csqc_model_precache[i])
-                       break;
-               else
-               if(!strcmp(cl.csqc_model_precache[i]->name, m))
+       for (i = 0;i < MAX_MODELS && cl.csqc_model_precache[i];i++)
+       {
+               if (!strcmp(cl.csqc_model_precache[i]->name, m))
                {
                        e->fields.client->model = PRVM_SetEngineString(cl.csqc_model_precache[i]->name);
                        e->fields.client->modelindex = -(i+1);
                        return;
                }
+       }
 
-       for (i=0, mod = cl.model_precache[0] ; i < MAX_MODELS ; i++, mod = cl.model_precache[i])
-               if(mod)
-               if(!strcmp(mod->name, m))
+       for (i = 0;i < MAX_MODELS;i++)
+       {
+               mod = cl.model_precache[i];
+               if (mod && !strcmp(mod->name, m))
                {
                        e->fields.client->model = PRVM_SetEngineString(mod->name);
                        e->fields.client->modelindex = i;
                        return;
                }
+       }
+
        e->fields.client->modelindex = 0;
        e->fields.client->model = 0;
 }
@@ -291,10 +300,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
@@ -307,37 +314,28 @@ void VM_CL_precache_model (void)
        VM_SAFEPARMCOUNT(1, VM_CL_precache_model);
 
        name = PRVM_G_STRING(OFS_PARM0);
-       for(i=1;i<MAX_MODELS;i++)
-               if(!cl.csqc_model_precache[i])
-               {
-                       i = 0;
-                       break;
-               }
-               else
+       for (i = 1;i < MAX_MODELS && cl.csqc_model_precache[i];i++)
+       {
                if(!strcmp(cl.csqc_model_precache[i]->name, name))
                {
-                       i = -(i+1);
-                       break;
+                       PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
+                       return;
                }
-       if(i)
-       {
-               PRVM_G_FLOAT(OFS_RETURN) = i;
-               return;
        }
        PRVM_G_FLOAT(OFS_RETURN) = 0;
        m = Mod_ForName(name, false, false, false);
        if(m && m->loaded)
        {
-               for(i=1;i<MAX_MODELS;i++)
-                       if(!cl.csqc_model_precache[i])
-                               break;
-               if(i == MAX_MODELS)
+               for (i = 1;i < MAX_MODELS;i++)
                {
-                       VM_Warning("VM_CL_precache_model: no free models\n");
-                       return;
+                       if (!cl.csqc_model_precache[i])
+                       {
+                               cl.csqc_model_precache[i] = (model_t*)m;
+                               PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
+                               return;
+                       }
                }
-               cl.csqc_model_precache[i] = (model_t*)m;
-               PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
+               VM_Warning("VM_CL_precache_model: no free models\n");
                return;
        }
        VM_Warning("VM_CL_precache_model: model \"%s\" not found\n", name);
@@ -760,12 +758,10 @@ void VM_CL_getlight (void)
 
 //============================================================================
 //[515]: SCENE MANAGER builtins
-extern void V_CalcRefdef (void);//view.c
 extern qboolean CSQC_AddRenderEdict (prvm_edict_t *ed);//csprogs.c
-extern void CSQC_ClearCSQCEntities (void);//csprogs.c
 
 matrix4x4_t csqc_listenermatrix;
-qboolean csqc_usecsqclistener = false, csqc_frame = false;//[515]: per-frame
+qboolean csqc_usecsqclistener = false;//[515]: per-frame
 
 static void CSQC_R_RecalcView (void)
 {
@@ -773,15 +769,14 @@ static void CSQC_R_RecalcView (void)
        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], 0.3);
+       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);
 }
 
 //#300 void() clearscene (EXT_CSQC)
 void VM_R_ClearScene (void)
 {
        VM_SAFEPARMCOUNT(0, VM_R_ClearScene);
-//     CSQC_R_RecalcView();
-       CSQC_ClearCSQCEntities();
+       r_refdef.numentities = 0;
 }
 
 //#301 void(float mask) addentities (EXT_CSQC)
@@ -920,6 +915,8 @@ void VM_R_SetView (void)
 void VM_R_RenderScene (void) //#134
 {
        VM_SAFEPARMCOUNT(0, VM_R_RenderScene);
+       // update all renderable network entities
+       CL_UpdateEntities();
        R_RenderView();
 }
 
@@ -1005,17 +1002,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)
@@ -1023,83 +1020,48 @@ void VM_CL_setmodelindex (void)
 {
        int                             i;
        prvm_edict_t    *t;
-       struct model_s  *m;
+       struct model_s  *model;
 
        VM_SAFEPARMCOUNT(2, VM_CL_setmodelindex);
 
        t = PRVM_G_EDICT(OFS_PARM0);
+
        i = (int)PRVM_G_FLOAT(OFS_PARM1);
 
        t->fields.client->model = 0;
        t->fields.client->modelindex = 0;
 
-       if(!i)
+       if (!i)
                return;
-       if(i<0)
-       {
-               i = -(i+1);
-               if(i >= MAX_MODELS)
-               {
-                       VM_Warning("VM_CL_setmodelindex >= MAX_MODELS\n");
-                       return;
-               }
-               m = cl.csqc_model_precache[i];
-       }
-       else
-               if(i >= MAX_MODELS)
-               {
-                       VM_Warning("VM_CL_setmodelindex >= MAX_MODELS\n");
-                       return;
-               }
-               else
-                       m = cl.model_precache[i];
-       if(!m)
+
+       model = CSQC_GetModelByIndex(i);
+       if (!model)
        {
                VM_Warning("VM_CL_setmodelindex: null model\n");
                return;
        }
-       t->fields.client->model = PRVM_SetEngineString(m->name);
+       t->fields.client->model = PRVM_SetEngineString(model->name);
        t->fields.client->modelindex = i;
 }
 
 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
 void VM_CL_modelnameforindex (void)
 {
-       int i;
+       model_t *model;
 
        VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex);
 
-       PRVM_G_INT(OFS_RETURN) = 0;
-       i = (int)PRVM_G_FLOAT(OFS_PARM0);
-       if(i<0)
-       {
-               i = -(i+1);
-               if(i >= MAX_MODELS)
-               {
-                       VM_Warning("VM_CL_modelnameforindex >= MAX_MODELS\n");
-                       return;
-               }
-               if(cl.csqc_model_precache[i])
-                       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(cl.csqc_model_precache[i]->name);
-               return;
-       }
-       if(i >= MAX_MODELS)
-       {
-               VM_Warning("VM_CL_modelnameforindex >= MAX_MODELS\n");
-               return;
-       }
-       if(cl.model_precache[i])
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(cl.model_precache[i]->name);
+       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;
 }
 
 //#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;
@@ -1108,26 +1070,17 @@ void VM_CL_particleeffectnum (void)
 // #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC)
 void VM_CL_trailparticles (void)
 {
-       int                             i, entnum;
+       int                             i;
        float                   *start, *end;
        prvm_edict_t    *t;
        VM_SAFEPARMCOUNT(4, VM_CL_trailparticles);
 
        t = PRVM_G_EDICT(OFS_PARM0);
-       entnum  = PRVM_NUM_FOR_EDICT(t);
        i               = (int)PRVM_G_FLOAT(OFS_PARM1);
        start   = PRVM_G_VECTOR(OFS_PARM2);
        end             = PRVM_G_VECTOR(OFS_PARM3);
 
-       if (entnum >= MAX_EDICTS)
-       {
-               VM_Warning("CSQC_ParseBeam: invalid entity number %i\n", entnum);
-               return;
-       }
-       if (entnum >= cl.max_csqcentities)
-               CL_ExpandCSQCEntities(entnum);
-
-       CL_ParticleEffect(i, VectorDistance(start, end), start, end, t->fields.client->velocity, t->fields.client->velocity, &cl.csqcentities[entnum], (int)PRVM_G_FLOAT(OFS_PARM4));
+       CL_ParticleEffect(i, VectorDistance(start, end), start, end, t->fields.client->velocity, t->fields.client->velocity, NULL, (int)PRVM_G_FLOAT(OFS_PARM4));
 }
 
 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
@@ -1156,11 +1109,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)
@@ -1215,7 +1165,6 @@ void VM_CL_getplayerkey (void)
        int                     i;
        char            t[128];
        const char      *c;
-       char            *temp;
 
        VM_SAFEPARMCOUNT(2, VM_CL_getplayerkey);
 
@@ -1235,12 +1184,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);
@@ -1255,9 +1204,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)
@@ -1351,15 +1298,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)
@@ -1738,28 +1677,6 @@ void VM_CL_te_plasmaburn (void)
 //DP_QC_GETSURFACE
 
 extern void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out);
-static model_t *cl_getmodel(prvm_edict_t *ed)
-{
-       int modelindex;
-       model_t *model = NULL;
-       if (!ed || ed->priv.server->free)
-               return NULL;
-       modelindex = (int)ed->fields.client->modelindex;
-       if(!modelindex)
-               return NULL;
-       if(modelindex<0)
-       {
-               modelindex = -(modelindex+1);
-               if(modelindex < MAX_MODELS)
-                       model = cl.csqc_model_precache[modelindex];
-       }
-       else
-       {
-               if(modelindex < MAX_MODELS)
-                       model = cl.model_precache[modelindex];
-       }
-       return model;
-}
 
 static msurface_t *cl_getsurface(model_t *model, int surfacenum)
 {
@@ -1771,7 +1688,7 @@ static msurface_t *cl_getsurface(model_t *model, int surfacenum)
 // #434 float(entity e, float s) getsurfacenumpoints
 void VM_CL_getsurfacenumpoints(void)
 {
-       model_t *model = cl_getmodel(PRVM_G_EDICT(OFS_PARM0));
+       model_t *model = CSQC_GetModelFromEntity(PRVM_G_EDICT(OFS_PARM0));
        msurface_t *surface;
        // return 0 if no such surface
        if (!model || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
@@ -1793,7 +1710,7 @@ void VM_CL_getsurfacepoint(void)
        int pointnum;
        VectorClear(PRVM_G_VECTOR(OFS_RETURN));
        ed = PRVM_G_EDICT(OFS_PARM0);
-       if (!(model = cl_getmodel(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+       if (!(model = CSQC_GetModelFromEntity(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
                return;
        // note: this (incorrectly) assumes it is a simple polygon
        pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
@@ -1810,7 +1727,7 @@ void VM_CL_getsurfacenormal(void)
        msurface_t *surface;
        vec3_t normal;
        VectorClear(PRVM_G_VECTOR(OFS_RETURN));
-       if (!(model = cl_getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+       if (!(model = CSQC_GetModelFromEntity(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
                return;
        // FIXME: implement rotation/scaling
        // note: this (incorrectly) assumes it is a simple polygon
@@ -1826,10 +1743,10 @@ void VM_CL_getsurfacetexture(void)
 {
        model_t *model;
        msurface_t *surface;
-       PRVM_G_INT(OFS_RETURN) = 0;
-       if (!(model = cl_getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+       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
@@ -1844,7 +1761,7 @@ void VM_CL_getsurfacenearpoint(void)
        vec_t *point;
        PRVM_G_FLOAT(OFS_RETURN) = -1;
        ed = PRVM_G_EDICT(OFS_PARM0);
-       if(!(model = cl_getmodel(ed)) || !model->num_surfaces)
+       if(!(model = CSQC_GetModelFromEntity(ed)) || !model->num_surfaces)
                return;
 
        // FIXME: implement rotation/scaling
@@ -1886,7 +1803,7 @@ void VM_CL_getsurfaceclippedpoint(void)
        vec3_t p, out;
        VectorClear(PRVM_G_VECTOR(OFS_RETURN));
        ed = PRVM_G_EDICT(OFS_PARM0);
-       if (!(model = cl_getmodel(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+       if (!(model = CSQC_GetModelFromEntity(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
                return;
        // FIXME: implement rotation/scaling
        VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.client->origin, p);
@@ -1929,21 +1846,7 @@ void VM_CL_setattachment (void)
        if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
        {
                modelindex = (int)tagentity->fields.client->modelindex;
-               model = NULL;
-
-               if(modelindex)
-               {
-                       if(modelindex<0)
-                       {
-                               modelindex = -(modelindex+1);
-                               if(modelindex < MAX_MODELS)
-                                       model = cl.csqc_model_precache[modelindex];
-                       }
-                       else
-                               if(modelindex < MAX_MODELS)
-                                       model = cl.model_precache[modelindex];
-               }
-
+               model = CSQC_GetModelByIndex(modelindex);
                if (model)
                {
                        v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.client->skin, tagname);
@@ -1960,27 +1863,11 @@ void VM_CL_setattachment (void)
 
 int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
 {
-       int i;
-       model_t *m;
-
-       i = (int)e->fields.client->modelindex;
-
-       if(!i)
-               return -1;
-       if(i<0)
-       {
-               i = -(i+1);
-               if(i >= MAX_MODELS)
-                       return -1;
-               m = cl.csqc_model_precache[i];
-       }
+       model_t *model = CSQC_GetModelFromEntity(e);
+       if (model)
+               return Mod_Alias_GetTagIndexForName(model, (int)e->fields.client->skin, tagname);
        else
-               if(i >= MAX_MODELS)
-                       return -1;
-               else
-                       m = cl.model_precache[i];
-
-       return Mod_Alias_GetTagIndexForName(m, (int)e->fields.client->skin, tagname);
+               return -1;
 };
 
 // Warnings/errors code:
@@ -1996,7 +1883,7 @@ extern cvar_t cl_bobup;
 int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
 {
        prvm_eval_t *val;
-       int modelindex, reqframe, attachloop, i;
+       int reqframe, attachloop;
        matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
        prvm_edict_t *attachent;
        model_t *model;
@@ -2008,22 +1895,10 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
        if (ent->priv.server->free)
                return 2;
 
-       modelindex = (int)ent->fields.client->modelindex;
+       model = CSQC_GetModelFromEntity(ent);
 
-       if(!modelindex)
+       if(!model)
                return 3;
-       if(modelindex<0)
-       {
-               modelindex = -(modelindex+1);
-               if(modelindex >= MAX_MODELS)
-                       return 3;
-               model = cl.csqc_model_precache[modelindex];
-       }
-       else
-               if(modelindex >= MAX_MODELS)
-                       return 3;
-               else
-                       model = cl.model_precache[modelindex];
 
        if (ent->fields.client->frame >= 0 && ent->fields.client->frame < model->numframes && model->animscenes)
                reqframe = model->animscenes[(int)ent->fields.client->frame].firstframe;
@@ -2048,17 +1923,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                        attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
                        val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_index);
 
-                       model = NULL;
-                       i = (int)attachent->fields.client->modelindex;
-                       if(i<0)
-                       {
-                               i = -(i+1);
-                               if(i < MAX_MODELS)
-                                       model = cl.csqc_model_precache[i];
-                       }
-                       else
-                               if(i < MAX_MODELS)
-                                       model = cl.model_precache[i];
+                       model = CSQC_GetModelFromEntity(attachent);
 
                        if (model && val->_float >= 1 && model->animscenes && attachent->fields.client->frame >= 0 && attachent->fields.client->frame < model->numframes)
                                Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.client->frame].firstframe, (int)val->_float - 1, &attachmatrix);
@@ -2313,15 +2178,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])
        {
@@ -2335,6 +2197,7 @@ void VM_uncolorstring (void) //#170
                ++k;
                ++i;
        }
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(out);
 }
 
 void VM_CL_selecttraceline (void)
@@ -2348,16 +2211,12 @@ void VM_CL_selecttraceline (void)
        csqcents = (int)PRVM_G_FLOAT(OFS_PARM3);
        ent = 0;
 
-       if((csqcents && ignore > cl.num_csqcentities) || (!csqcents && ignore > cl.num_entities))
+       if (csqcents)
        {
-               VM_Warning("VM_CL_selecttraceline: out of entities\n");
+               VM_Warning("VM_CL_selecttraceline: csqcents flag not supported anymore, and this function is deprecated\n");
                return;
        }
-       else
-               if(csqcents)
-                       prog->globals.client->trace_fraction = CL_SelectTraceLine(v1, v2, prog->globals.client->trace_endpos, prog->globals.client->trace_plane_normal, &prog->globals.client->trace_ent, &cl.csqcentities[ignore].render, csqcents);
-               else
-                       prog->globals.client->trace_fraction = CL_SelectTraceLine(v1, v2, prog->globals.client->trace_endpos, prog->globals.client->trace_plane_normal, &ent, &cl.entities[ignore].render, csqcents);
+       prog->globals.client->trace_fraction = CL_SelectTraceLine(v1, v2, prog->globals.client->trace_endpos, prog->globals.client->trace_plane_normal, &ent, &cl.entities[ignore].render);
        PRVM_G_FLOAT(OFS_RETURN) = ent;
 }
 
@@ -2365,8 +2224,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)];
@@ -2375,13 +2232,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)
@@ -2722,7 +2578,17 @@ VM_bufstr_get,                           // #466 string(float bufhandle, float string_index) bufstr_get
 VM_bufstr_set,                         // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
 VM_bufstr_add,                         // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
 VM_bufstr_free,                                // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
-e10, e10, e10                  // #470-499 (LordHavoc)
+NULL,                                          // #470
+VM_asin,                                       // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
+VM_acos,                                       // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
+VM_atan,                                       // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
+VM_atan2,                                      // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
+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)
+VM_strftime,                           // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
+NULL,                                          // #479
+e10, e10                       // #480-499 (LordHavoc)
 };
 
 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);