]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - clvm_cmds.c
added DP_QC_STRFTIME extension
[xonotic/darkplaces.git] / clvm_cmds.c
index 4b155e4d5fe9d92bd811db59ec7f741bb6364918..0c52ef5f021c4061338897aa38f1166ef384af47 100644 (file)
 //4 feature darkplaces csqc: add builtin to clientside qc for reading triangles of model meshes (useful to orient a ui along a triangle of a model mesh)
 //4 feature darkplaces csqc: add builtins to clientside qc for gl calls
 
-#ifndef PF_WARNING
-#define PF_WARNING(s) do{Con_Printf(s);PRVM_PrintState();return;}while(0)
-#endif
-
 //[515]: really need new list ?
 char *vm_cl_extensions =
+"BX_WAL_SUPPORT "
 "DP_CON_SET "
 "DP_CON_SETA "
 "DP_CON_STARTMAP "
@@ -39,6 +36,7 @@ char *vm_cl_extensions =
 "DP_ENT_GLOW "
 "DP_ENT_SCALE "
 "DP_GFX_EXTERNALTEXTURES "
+"DP_GFX_EXTERNALTEXTURES_PERMAP "
 "DP_GFX_FOG "
 "DP_GFX_QUAKE3MODELTAGS "
 "DP_GFX_SKINFILES "
@@ -52,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 "
@@ -70,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 "
@@ -116,15 +118,16 @@ char *vm_cl_extensions =
 ;
 
 sfx_t *S_FindName(const char *name);
-int CL_PointQ1Contents(const vec3_t p);
 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);
+
 
 
 
@@ -145,9 +148,15 @@ void VM_CL_setorigin (void)
 
        e = PRVM_G_EDICT(OFS_PARM0);
        if (e == prog->edicts)
-               PF_WARNING("setorigin: can not modify world entity\n");
+       {
+               VM_Warning("setorigin: can not modify world entity\n");
+               return;
+       }
        if (e->priv.required->free)
-               PF_WARNING("setorigin: can not modify free entity\n");
+       {
+               VM_Warning("setorigin: can not modify free entity\n");
+               return;
+       }
        org = PRVM_G_VECTOR(OFS_PARM1);
        VectorCopy (org, e->fields.client->origin);
 }
@@ -164,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;
 }
@@ -196,9 +207,15 @@ void VM_CL_setsize (void)
 
        e = PRVM_G_EDICT(OFS_PARM0);
        if (e == prog->edicts)
-               PF_WARNING("setsize: can not modify world entity\n");
+       {
+               VM_Warning("setsize: can not modify world entity\n");
+               return;
+       }
        if (e->priv.server->free)
-               PF_WARNING("setsize: can not modify free entity\n");
+       {
+               VM_Warning("setsize: can not modify free entity\n");
+               return;
+       }
        min = PRVM_G_VECTOR(OFS_PARM1);
        max = PRVM_G_VECTOR(OFS_PARM2);
 
@@ -219,19 +236,28 @@ void VM_CL_sound (void)
        VM_SAFEPARMCOUNT(5, VM_CL_sound);
 
        entity = PRVM_G_EDICT(OFS_PARM0);
-       channel = PRVM_G_FLOAT(OFS_PARM1);
+       channel = (int)PRVM_G_FLOAT(OFS_PARM1);
        sample = PRVM_G_STRING(OFS_PARM2);
-       volume = PRVM_G_FLOAT(OFS_PARM3)*255;
+       volume = (int)(PRVM_G_FLOAT(OFS_PARM3)*255.0f);
        attenuation = PRVM_G_FLOAT(OFS_PARM4);
 
        if (volume < 0 || volume > 255)
-               PF_WARNING("VM_CL_sound: volume must be in range 0-1\n");
+       {
+               VM_Warning("VM_CL_sound: volume must be in range 0-1\n");
+               return;
+       }
 
        if (attenuation < 0 || attenuation > 4)
-               PF_WARNING("VM_CL_sound: attenuation must be in range 0-4\n");
+       {
+               VM_Warning("VM_CL_sound: attenuation must be in range 0-4\n");
+               return;
+       }
 
        if (channel < 0 || channel > 7)
-               PF_WARNING("VM_CL_sound: channel must be in range 0-7\n");
+       {
+               VM_Warning("VM_CL_sound: channel must be in range 0-7\n");
+               return;
+       }
 
        S_StartSound(32768 + PRVM_NUM_FOR_EDICT(entity), channel, S_FindName(sample), entity->fields.client->origin, volume, attenuation);
 }
@@ -274,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
@@ -290,37 +314,31 @@ 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)
-                       PF_WARNING("VM_CL_precache_model: no free models\n");
-               cl.csqc_model_precache[i] = (model_t*)m;
-               PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
+               for (i = 1;i < MAX_MODELS;i++)
+               {
+                       if (!cl.csqc_model_precache[i])
+                       {
+                               cl.csqc_model_precache[i] = (model_t*)m;
+                               PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
+                               return;
+                       }
+               }
+               VM_Warning("VM_CL_precache_model: no free models\n");
                return;
        }
-       Con_Printf("VM_CL_precache_model: model \"%s\" not found\n", name);
+       VM_Warning("VM_CL_precache_model: model \"%s\" not found\n", name);
 }
 
 int CSQC_EntitiesInBox (vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **list)
@@ -411,9 +429,15 @@ void VM_CL_droptofloor (void)
 
        ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
        if (ent == prog->edicts)
-               PF_WARNING("droptofloor: can not modify world entity\n");
+       {
+               VM_Warning("droptofloor: can not modify world entity\n");
+               return;
+       }
        if (ent->priv.server->free)
-               PF_WARNING("droptofloor: can not modify free entity\n");
+       {
+               VM_Warning("droptofloor: can not modify free entity\n");
+               return;
+       }
 
        VectorCopy (ent->fields.client->origin, end);
        end[2] -= 256;
@@ -439,10 +463,13 @@ void VM_CL_lightstyle (void)
 
        VM_SAFEPARMCOUNT(2, VM_CL_lightstyle);
 
-       i = PRVM_G_FLOAT(OFS_PARM0);
+       i = (int)PRVM_G_FLOAT(OFS_PARM0);
        c = PRVM_G_STRING(OFS_PARM1);
        if (i >= cl.max_lightstyle)
-               PF_WARNING("VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
+       {
+               VM_Warning("VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
+               return;
+       }
        strlcpy (cl.lightstyle[i].map,  MSG_ReadString(), sizeof (cl.lightstyle[i].map));
        cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
        cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map);
@@ -523,7 +550,7 @@ realcheck:
 void VM_CL_pointcontents (void)
 {
        VM_SAFEPARMCOUNT(1, VM_CL_pointcontents);
-       PRVM_G_FLOAT(OFS_RETURN) = CL_PointQ1Contents(PRVM_G_VECTOR(OFS_PARM0));
+       PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, CL_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
 }
 
 // #48 void(vector o, vector d, float color, float count) particle
@@ -536,24 +563,9 @@ void VM_CL_particle (void)
 
        org = PRVM_G_VECTOR(OFS_PARM0);
        dir = PRVM_G_VECTOR(OFS_PARM1);
-       color = PRVM_G_FLOAT(OFS_PARM2);
-       count = PRVM_G_FLOAT(OFS_PARM3);
-       if (cl_particles_blood_bloodhack.integer)
-       {
-               if (color == 73)
-               {
-                       // regular blood
-                       CL_BloodPuff(org, dir, count / 2);
-                       return;
-               }
-               if (color == 225)
-               {
-                       // lightning blood
-                       CL_BloodPuff(org, dir, count / 2);
-                       return;
-               }
-       }
-       CL_RunParticleEffect (org, dir, color, count);
+       color = (int)PRVM_G_FLOAT(OFS_PARM2);
+       count = (int)PRVM_G_FLOAT(OFS_PARM3);
+       CL_ParticleEffect(EFFECT_SVC_PARTICLE, count, org, org, dir, dir, NULL, color);
 }
 
 // #49 void(entity ent, float ideal_yaw, float speed_yaw) ChangeYaw
@@ -565,9 +577,15 @@ void VM_CL_changeyaw (void)
 
        ent = PRVM_G_EDICT(OFS_PARM0);
        if (ent == prog->edicts)
-               PF_WARNING("changeyaw: can not modify world entity\n");
+       {
+               VM_Warning("changeyaw: can not modify world entity\n");
+               return;
+       }
        if (ent->priv.server->free)
-               PF_WARNING("changeyaw: can not modify free entity\n");
+       {
+               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);
@@ -608,9 +626,15 @@ void VM_CL_changepitch (void)
 
        ent = PRVM_G_EDICT(OFS_PARM0);
        if (ent == prog->edicts)
-               PF_WARNING("changepitch: can not modify world entity\n");
+       {
+               VM_Warning("changepitch: can not modify world entity\n");
+               return;
+       }
        if (ent->priv.server->free)
-               PF_WARNING("changepitch: can not modify free entity\n");
+       {
+               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);
@@ -651,7 +675,10 @@ void VM_CL_tracetoss (void)
 
        ent = PRVM_G_EDICT(OFS_PARM0);
        if (ent == prog->edicts)
-               PF_WARNING("tracetoss: can not use world entity\n");
+       {
+               VM_Warning("tracetoss: can not use world entity\n");
+               return;
+       }
        ignore = PRVM_G_EDICT(OFS_PARM1);
 
 //FIXME
@@ -731,103 +758,64 @@ void VM_CL_getlight (void)
 
 //============================================================================
 //[515]: SCENE MANAGER builtins
-void V_CalcRefdef (void);//view.c
-void CSQC_R_ClearScreen (void);//gl_rmain.c
-void CSQC_R_RenderScene (void);//gl_rmain.c
-void CSQC_AddEntity (int n);//csprogs.c
-void CSQC_ClearCSQCEntities (void);
+extern qboolean CSQC_AddRenderEdict (prvm_edict_t *ed);//csprogs.c
 
 matrix4x4_t csqc_listenermatrix;
-qboolean csqc_usecsqclistener = false, csqc_frame = false;//[515]: per-frame
-qboolean csqc_onground;
-
-static char *particleeffect_names[] =
-{
-       "TE_SPIKE",
-       "TE_SUPERSPIKE",
-       "TE_GUNSHOT",
-       "TE_EXPLOSION",
-       "TE_TAREXPLOSION",
-       "TE_LIGHTNING1",//trail
-       "TE_LIGHTNING2",//trail
-       "TE_WIZSPIKE",
-       "TE_KNIGHTSPIKE",
-       "TE_LIGHTNING3",//trail
-       "TE_LAVASPLASH",
-       "TE_TELEPORT",
-       "TE_EXPLOSION2",
-       "TE_BEAM",//trail
-       "TE_EXPLOSION3",
-       "",//TE_LIGHTNING4NEH
-       "TE_BLOOD",
-       "TE_SPARK",
-       "",//TE_BLOODSHOWER
-       "TE_EXPLOSIONRGB",
-       "",//unused
-       "",
-       "",
-       "TE_GUNSHOTQUAD",
-       "TE_SPIKEQUAD",
-       "TE_SUPERSPIKEQUAD",
-       "TE_EXPLOSIONQUAD",
-       "",
-       "",
-       "",
-       "TE_FLAMEJET",
-       "TE_PLASMABURN",
-       "TE_TEI_G3",
-       "TE_TEI_SMOKE",
-       "TE_TEI_BIGEXPLOSION",
-       "TE_TEI_PLASMAHIT",
-
-
-       //trail effects (as modelflags)
-       "EF_ROCKET",
-       "EF_GRENADE",
-       "EF_GIB",
-       "EF_TRACER",
-       "EF_ZOMGIB",
-       "EF_TRACER2",
-       "EF_TRACER3",
-       "EF_NEH_CIGAR",
-       "EF_NEXUIZ_PLASMA",
-       "EF_GLOWTRAIL",
-};
-
-#define CSQC_TRAILSTART 36
-static const int particleeffects_num = sizeof(particleeffect_names)/sizeof(char*);
+qboolean csqc_usecsqclistener = false;//[515]: per-frame
 
 static void CSQC_R_RecalcView (void)
 {
        extern matrix4x4_t viewmodelmatrix;
        viewmodelmatrix = identitymatrix;
-       r_refdef.viewentitymatrix = identitymatrix;
-       Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, 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);
+       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);
 }
 
 //#300 void() clearscene (EXT_CSQC)
 void VM_R_ClearScene (void)
 {
        VM_SAFEPARMCOUNT(0, VM_R_ClearScene);
-//     CSQC_R_RecalcView();
-       if(csqc_frame)
-               CSQC_ClearCSQCEntities();
-       CSQC_R_ClearScreen();
+       r_refdef.numentities = 0;
 }
 
 //#301 void(float mask) addentities (EXT_CSQC)
+extern void CSQC_Predraw (prvm_edict_t *ed);//csprogs.c
+extern void CSQC_Think (prvm_edict_t *ed);//csprogs.c
 void VM_R_AddEntities (void)
 {
+       int                     i, drawmask;
+       prvm_edict_t *ed;
        VM_SAFEPARMCOUNT(1, VM_R_AddEntities);
-       csqc_drawmask = PRVM_G_FLOAT(OFS_PARM0);
+       drawmask = (int)PRVM_G_FLOAT(OFS_PARM0);
+       CSQC_RelinkAllEntities(drawmask);
+
+       *prog->time = cl.time;
+       for(i=1;i<prog->num_edicts;i++)
+       {
+               ed = &prog->edicts[i];
+               if(ed->priv.required->free)
+                       continue;
+               VectorAdd(ed->fields.client->origin, ed->fields.client->mins, ed->fields.client->absmin);
+               VectorAdd(ed->fields.client->origin, ed->fields.client->maxs, ed->fields.client->absmax);
+               CSQC_Think(ed);
+               if(ed->priv.required->free)
+                       continue;
+               // note that for RF_USEAXIS entities, Predraw sets v_forward/v_right/v_up globals that are read by CSQC_AddRenderEdict
+               CSQC_Predraw(ed);
+               if(ed->priv.required->free)
+                       continue;
+               if(!((int)ed->fields.client->drawmask & drawmask))
+                       continue;
+               CSQC_AddRenderEdict(ed);
+       }
 }
 
 //#302 void(entity ent) addentity (EXT_CSQC)
 void VM_R_AddEntity (void)
 {
        VM_SAFEPARMCOUNT(1, VM_R_AddEntity);
-       CSQC_AddEntity(PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)));
+       CSQC_AddRenderEdict(PRVM_G_EDICT(OFS_PARM0));
 }
 
 //#303 float(float property, ...) setproperty (EXT_CSQC)
@@ -840,31 +828,34 @@ void VM_R_SetView (void)
        if(prog->argc < 2)
                VM_SAFEPARMCOUNT(2, VM_R_SetView);
 
-       c = PRVM_G_FLOAT(OFS_PARM0);
+       c = (int)PRVM_G_FLOAT(OFS_PARM0);
        f = PRVM_G_VECTOR(OFS_PARM1);
        k = PRVM_G_FLOAT(OFS_PARM1);
 
        switch(c)
        {
-       case VF_MIN:                    r_refdef.x = f[0];
-                                                       r_refdef.y = f[1];
+       case VF_MIN:                    r_view.x = (int)f[0];
+                                                       r_view.y = (int)f[1];
                                                        break;
-       case VF_MIN_X:                  r_refdef.x = k;
+       case VF_MIN_X:                  r_view.x = (int)k;
                                                        break;
-       case VF_MIN_Y:                  r_refdef.y = k;
+       case VF_MIN_Y:                  r_view.y = (int)k;
                                                        break;
-       case VF_SIZE:                   r_refdef.width = f[0];
-                                                       r_refdef.height = f[1];
+       case VF_SIZE:                   r_view.width = (int)f[0];
+                                                       r_view.height = (int)f[1];
                                                        break;
-       case VF_SIZE_Y:                 r_refdef.width = k;
+       case VF_SIZE_Y:                 r_view.width = (int)k;
                                                        break;
-       case VF_SIZE_X:                 r_refdef.height = k;
+       case VF_SIZE_X:                 r_view.height = (int)k;
                                                        break;
-       case VF_VIEWPORT:               r_refdef.x = f[0];
-                                                       r_refdef.y = f[1];
+       case VF_VIEWPORT:               r_view.x = (int)f[0];
+                                                       r_view.y = (int)f[1];
+                                                       r_view.z = 0;
+                                                       // TODO: make sure that view_z and view_depth are set properly even if csqc does not set them!
                                                        f = PRVM_G_VECTOR(OFS_PARM2);
-                                                       r_refdef.width = f[0];
-                                                       r_refdef.height = f[1];
+                                                       r_view.width = (int)f[0];
+                                                       r_view.height = (int)f[1];
+                                                       r_view.depth = 1;
                                                        break;
        case VF_FOV:                    //r_refdef.fov_x = f[0]; // FIXME!
                                                        //r_refdef.fov_y = f[1]; // FIXME!
@@ -913,8 +904,8 @@ void VM_R_SetView (void)
        case VF_CL_VIEWANGLES_Z:cl.viewangles[2] = k;
                                                        break;
 
-       default:                                Con_Printf("VM_R_SetView : unknown parm %i\n", c);
-                                                       PRVM_G_FLOAT(OFS_RETURN) = 0;
+       default:                                PRVM_G_FLOAT(OFS_RETURN) = 0;
+                                                       VM_Warning("VM_R_SetView : unknown parm %i\n", c);
                                                        return;
        }
        PRVM_G_FLOAT(OFS_RETURN) = 1;
@@ -924,14 +915,9 @@ void VM_R_SetView (void)
 void VM_R_RenderScene (void) //#134
 {
        VM_SAFEPARMCOUNT(0, VM_R_RenderScene);
-
-       if(csqc_frame)
-       {
-               CSQC_RelinkCSQCEntities();
-               CSQC_RelinkAllEntities(csqc_drawmask);
-       }
-
-       CSQC_R_RenderScene();
+       // update all renderable network entities
+       CL_UpdateEntities();
+       R_RenderView();
 }
 
 //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
@@ -958,8 +944,8 @@ void VM_CL_unproject (void)
 
        VM_SAFEPARMCOUNT(1, VM_CL_unproject);
        f = PRVM_G_VECTOR(OFS_PARM0);
-       VectorSet(temp, f[2], f[0] * f[2] * -r_refdef.frustum_x * 2.0 / r_refdef.width, f[1] * f[2] * -r_refdef.frustum_y * 2.0 / r_refdef.height);
-       Matrix4x4_Transform(&r_refdef.viewentitymatrix, temp, PRVM_G_VECTOR(OFS_RETURN));
+       VectorSet(temp, f[2], f[0] * f[2] * -r_view.frustum_x * 2.0 / r_view.width, f[1] * f[2] * -r_view.frustum_y * 2.0 / r_view.height);
+       Matrix4x4_Transform(&r_view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN));
 }
 
 //#311 vector (vector v) cs_project (EXT_CSQC)
@@ -971,9 +957,9 @@ void VM_CL_project (void)
 
        VM_SAFEPARMCOUNT(1, VM_CL_project);
        f = PRVM_G_VECTOR(OFS_PARM0);
-       Matrix4x4_Invert_Simple(&m, &r_refdef.viewentitymatrix);
+       Matrix4x4_Invert_Simple(&m, &r_view.matrix);
        Matrix4x4_Transform(&m, f, v);
-       VectorSet(PRVM_G_VECTOR(OFS_RETURN), v[1]/v[0]/-r_refdef.frustum_x*0.5*r_refdef.width, v[2]/v[0]/-r_refdef.frustum_y*r_refdef.height*0.5, v[0]);
+       VectorSet(PRVM_G_VECTOR(OFS_RETURN), v[1]/v[0]/-r_view.frustum_x*0.5*r_view.width, v[2]/v[0]/-r_view.frustum_y*r_view.height*0.5, v[0]);
 }
 
 //#330 float(float stnum) getstatf (EXT_CSQC)
@@ -986,10 +972,10 @@ void VM_CL_getstatf (void)
                int l;
        }dat;
        VM_SAFEPARMCOUNT(1, VM_CL_getstatf);
-       i = PRVM_G_FLOAT(OFS_PARM0);
+       i = (int)PRVM_G_FLOAT(OFS_PARM0);
        if(i < 0 || i >= MAX_CL_STATS)
        {
-               Con_Printf("VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
+               VM_Warning("VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
                return;
        }
        dat.l = cl.stats[i];
@@ -1001,11 +987,11 @@ void VM_CL_getstati (void)
 {
        int i, index;
        VM_SAFEPARMCOUNT(1, VM_CL_getstati);
-       index = PRVM_G_FLOAT(OFS_PARM0);
+       index = (int)PRVM_G_FLOAT(OFS_PARM0);
 
        if(index < 0 || index >= MAX_CL_STATS)
        {
-               Con_Printf("VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
+               VM_Warning("VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
                return;
        }
        i = cl.stats[index];
@@ -1016,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 = PRVM_G_FLOAT(OFS_PARM0);
+       i = (int)PRVM_G_FLOAT(OFS_PARM0);
        if(i < 0 || i > MAX_CL_STATS-4)
        {
-               Con_Printf("VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
+               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)
@@ -1034,254 +1020,80 @@ 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)
+
+       model = CSQC_GetModelByIndex(i);
+       if (!model)
        {
-               i = -(i+1);
-               if(i >= MAX_MODELS)
-                       PF_WARNING("VM_CL_setmodelindex >= MAX_MODELS\n");
-               m = cl.csqc_model_precache[i];
+               VM_Warning("VM_CL_setmodelindex: null model\n");
+               return;
        }
-       else
-               if(i >= MAX_MODELS)
-                       PF_WARNING("VM_CL_setmodelindex >= MAX_MODELS\n");
-               else
-                       m = cl.model_precache[i];
-       if(!m)
-               PF_WARNING("VM_CL_setmodelindex: null model\n");
-       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 = PRVM_G_FLOAT(OFS_PARM0);
-       if(i<0)
-       {
-               i = -(i+1);
-               if(i >= MAX_MODELS)
-                       PF_WARNING("VM_CL_modelnameforindex >= MAX_MODELS\n");
-               if(cl.csqc_model_precache[i])
-                       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(cl.csqc_model_precache[i]->name);
-               return;
-       }
-       if(i >= MAX_MODELS)
-               PF_WARNING("VM_CL_modelnameforindex >= MAX_MODELS\n");
-       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);
-       for(i=0;i<particleeffects_num;i++)
-               if(!strcasecmp(particleeffect_names[i], n))
-               {
-                       PRVM_G_FLOAT(OFS_RETURN) = i;
-                       return;
-               }
-       PRVM_G_FLOAT(OFS_RETURN) = -1;
-}
-
-void CSQC_ParseBeam (int ent, vec3_t start, vec3_t end, model_t *m, int lightning)
-{
-       int             i;
-       beam_t  *b;
-
-       // override any beam with the same entity
-       for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++)
-       {
-               if (b->entity == ent && ent)
-               {
-                       //b->entity = ent;
-                       b->lightning = lightning;
-                       b->relativestartvalid = (ent && cl.csqcentities[ent].state_current.active) ? 2 : 0;
-                       b->model = m;
-                       b->endtime = cl.time + 0.2;
-                       VectorCopy (start, b->start);
-                       VectorCopy (end, b->end);
-                       return;
-               }
-       }
-
-       // find a free beam
-       for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++)
-       {
-               if (!b->model || b->endtime < cl.time)
-               {
-                       b->entity = ent;
-                       b->lightning = lightning;
-                       b->relativestartvalid = (ent && cl.csqcentities[ent].state_current.active) ? 2 : 0;
-                       b->model = m;
-                       b->endtime = cl.time + 0.2;
-                       VectorCopy (start, b->start);
-                       VectorCopy (end, b->end);
-                       return;
-               }
-       }
-       Con_Print("beam list overflow!\n");
+       i = CL_ParticleEffectIndexForName(PRVM_G_STRING(OFS_PARM0));
+       if (i == 0)
+               i = -1;
+       PRVM_G_FLOAT(OFS_RETURN) = i;
 }
 
 // #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC)
 void VM_CL_trailparticles (void)
 {
-       int                             i, entnum, col;
+       int                             i;
        float                   *start, *end;
-       entity_t                *ent;
+       prvm_edict_t    *t;
        VM_SAFEPARMCOUNT(4, VM_CL_trailparticles);
 
-       entnum  = PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0));
-       i               = PRVM_G_FLOAT(OFS_PARM1);
+       t = PRVM_G_EDICT(OFS_PARM0);
+       i               = (int)PRVM_G_FLOAT(OFS_PARM1);
        start   = PRVM_G_VECTOR(OFS_PARM2);
        end             = PRVM_G_VECTOR(OFS_PARM3);
 
-       if(i >= particleeffects_num)
-               return;
-       if (entnum >= MAX_EDICTS)
-       {
-               Con_Printf("CSQC_ParseBeam: invalid entity number %i\n", entnum);
-               return;
-       }
-       if (entnum >= cl.max_csqcentities)
-               CL_ExpandCSQCEntities(entnum);
-
-       ent = &cl.csqcentities[entnum];
-
-       if(prog->argc > 4)
-               col = PRVM_G_FLOAT(OFS_PARM4);
-       else
-               col = ent->state_current.glowcolor;
-
-       switch(i)
-       {
-       case TE_LIGHTNING1:
-               CSQC_ParseBeam(entnum, start, end, cl.model_bolt, true);
-               break;
-       case TE_LIGHTNING2:
-               CSQC_ParseBeam(entnum, start, end, cl.model_bolt2, true);
-               break;
-       case TE_LIGHTNING3:
-               CSQC_ParseBeam(entnum, start, end, cl.model_bolt3, false);
-               break;
-       case TE_BEAM:
-               CSQC_ParseBeam(entnum, start, end, cl.model_beam, false);
-               break;
-       default:
-               CL_RocketTrail(start, end, i-CSQC_TRAILSTART, col, ent);
-               break;
-       }
+       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)
+//#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
 void VM_CL_pointparticles (void)
 {
        int                     i, n;
        float           *f, *v;
-       if(prog->argc < 2)
-               VM_SAFEPARMCOUNT(2, VM_CL_pointparticles);
-       i = PRVM_G_FLOAT(OFS_PARM0);
+       VM_SAFEPARMCOUNT(4, VM_CL_pointparticles);
+       i = (int)PRVM_G_FLOAT(OFS_PARM0);
        f = PRVM_G_VECTOR(OFS_PARM1);
-       if(prog->argc >= 4)
-       {
-               v = PRVM_G_VECTOR(OFS_PARM2);
-               n = PRVM_G_FLOAT(OFS_PARM3);
-       }
-       else
-       {
-               v = vec3_origin;
-               n = 15;
-       }
-
-       if(i >= particleeffects_num)
-               return;
-
-       switch(i)
-       {
-       case TE_SPIKE:
-       case TE_SPIKEQUAD:
-       case TE_GUNSHOT:
-       case TE_GUNSHOTQUAD:
-               CL_SparkShower(f, v, 15, 1, 0);
-               CL_Smoke(f, v, 15, 0);
-               if (cl_particles_bulletimpacts.integer)
-                       CL_BulletMark(f);
-               break;
-       case TE_SUPERSPIKE:
-       case TE_SUPERSPIKEQUAD:
-               CL_SparkShower(f, v, 30, 1, 0);
-               CL_Smoke(f, v, 30, 0);
-               if (cl_particles_bulletimpacts.integer)
-                       CL_BulletMark(f);
-               break;
-       case TE_EXPLOSION:
-       case TE_EXPLOSIONQUAD:
-       case TE_TEI_BIGEXPLOSION:
-               CL_ParticleExplosion(f);
-               break;
-       case TE_TAREXPLOSION:
-               CL_BlobExplosion(f);
-               break;
-       case TE_WIZSPIKE:
-               CL_RunParticleEffect(f, v, 20, 30);
-               break;
-       case TE_KNIGHTSPIKE:
-               CL_RunParticleEffect(f, v, 226, 20);
-               break;
-       case TE_LAVASPLASH:
-               CL_LavaSplash(f);
-               break;
-       case TE_TELEPORT:
-               CL_TeleportSplash(f);
-               break;
-       case TE_EXPLOSION2:
-       case TE_EXPLOSION3:
-       case TE_EXPLOSIONRGB:
-               CL_ParticleExplosion2(f, v[0], v[1]);
-               break;
-       case TE_BLOOD:
-               CL_BloodPuff(f, v, n);
-               break;
-       case TE_SPARK:
-               CL_SparkShower(f, v, n, 1, 0);
-               break;
-       case TE_FLAMEJET:
-               CL_Flames(f, v, n);
-               break;
-       case TE_PLASMABURN:
-               CL_PlasmaBurn(f);
-               break;
-       case TE_TEI_G3:
-               CL_BeamParticle(f, v, 8, 1, 1, 1, 1, 1);
-               break;
-       case TE_TEI_SMOKE:
-               CL_Tei_Smoke(f, v, n);
-               break;
-       case TE_TEI_PLASMAHIT:
-               CL_Tei_PlasmaHit(f, v, n);
-               break;
-       default:break;
-       }
+       v = PRVM_G_VECTOR(OFS_PARM2);
+       n = (int)PRVM_G_FLOAT(OFS_PARM3);
+       CL_ParticleEffect(i, n, f, f, v, v, NULL, 0);
 }
 
 //#338 void(string s) cprint (EXT_CSQC)
@@ -1297,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 = 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)
@@ -1317,7 +1126,7 @@ void VM_CL_getinputstate (void)
 {
        int i, frame;
        VM_SAFEPARMCOUNT(1, VM_CL_getinputstate);
-       frame = PRVM_G_FLOAT(OFS_PARM0);
+       frame = (int)PRVM_G_FLOAT(OFS_PARM0);
        for (i = 0;i < cl.movement_numqueue;i++)
                if (cl.movement_queue[i].sequence == frame)
                {
@@ -1356,11 +1165,10 @@ void VM_CL_getplayerkey (void)
        int                     i;
        char            t[128];
        const char      *c;
-       char            *temp;
 
        VM_SAFEPARMCOUNT(2, VM_CL_getplayerkey);
 
-       i = PRVM_G_FLOAT(OFS_PARM0);
+       i = (int)PRVM_G_FLOAT(OFS_PARM0);
        c = PRVM_G_STRING(OFS_PARM1);
        PRVM_G_INT(OFS_RETURN) = OFS_NULL;
        Sbar_SortFrags();
@@ -1372,16 +1180,16 @@ void VM_CL_getplayerkey (void)
        t[0] = 0;
 
        if(!strcasecmp(c, "name"))
-               strcpy(t, cl.scores[i].name);
+               strlcpy(t, cl.scores[i].name, sizeof(t));
        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);
@@ -1396,9 +1204,7 @@ void VM_CL_getplayerkey (void)
                        sprintf(t, "%i", i+1);
        if(!t[0])
                return;
-       temp = VM_GetTempString();
-       strcpy(temp, t);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(temp);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
 }
 
 //#349 float() isdemo (EXT_CSQC)
@@ -1422,8 +1228,11 @@ void VM_CL_registercmd (void)
        VM_SAFEPARMCOUNT(1, VM_CL_registercmd);
        if(!Cmd_Exists(PRVM_G_STRING(OFS_PARM0)))
        {
-               t = Z_Malloc(strlen(PRVM_G_STRING(OFS_PARM0))+1);
-               strcpy(t, PRVM_G_STRING(OFS_PARM0));
+               size_t alloclen;
+
+               alloclen = strlen(PRVM_G_STRING(OFS_PARM0)) + 1;
+               t = (char *)Z_Malloc(alloclen);
+               memcpy(t, PRVM_G_STRING(OFS_PARM0), alloclen);
                Cmd_AddCommand(t, NULL, "console command created by QuakeC");
        }
        else
@@ -1447,7 +1256,7 @@ void VM_CL_playernum (void)
 //#355 float() cl_onground (EXT_CSQC)
 void VM_CL_onground (void)
 {
-       PRVM_G_FLOAT(OFS_RETURN) = csqc_onground;
+       PRVM_G_FLOAT(OFS_RETURN) = cl.onground;
 }
 
 //#360 float() readbyte (EXT_CSQC)
@@ -1489,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)
-       {
-               strcpy(t, s);
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
-       }
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(MSG_ReadString());
 }
 
 //#367 float() readfloat (EXT_CSQC)
@@ -1512,7 +1313,7 @@ void VM_CL_ReadFloat (void)
 void VM_CL_effect (void)
 {
        VM_SAFEPARMCOUNT(5, VM_CL_effect);
-       CL_Effect(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
+       CL_Effect(PRVM_G_VECTOR(OFS_PARM0), (int)PRVM_G_FLOAT(OFS_PARM1), (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
 }
 
 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
@@ -1525,16 +1326,25 @@ void VM_CL_te_blood (void)
                return;
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       CL_BloodPuff(pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
+       CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
 }
 
 // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
 void VM_CL_te_bloodshower (void)
 {
+       vec_t speed;
+       vec3_t vel1, vel2;
        VM_SAFEPARMCOUNT(4, VM_CL_te_bloodshower);
        if (PRVM_G_FLOAT(OFS_PARM3) < 1)
                return;
-       CL_BloodShower(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3));
+       speed = PRVM_G_FLOAT(OFS_PARM2);
+       vel1[0] = -speed;
+       vel1[1] = -speed;
+       vel1[2] = -speed;
+       vel2[0] = speed;
+       vel2[1] = speed;
+       vel2[2] = speed;
+       CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), vel1, vel2, NULL, 0);
 }
 
 // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
@@ -1555,27 +1365,21 @@ void VM_CL_te_explosionrgb (void)
 void VM_CL_te_particlecube (void)
 {
        VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube);
-       if (PRVM_G_FLOAT(OFS_PARM3) < 1)
-               return;
-       CL_ParticleCube(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4), PRVM_G_FLOAT(OFS_PARM5), PRVM_G_FLOAT(OFS_PARM6));
+       CL_ParticleCube(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), PRVM_G_FLOAT(OFS_PARM5), PRVM_G_FLOAT(OFS_PARM6));
 }
 
 // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
 void VM_CL_te_particlerain (void)
 {
        VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain);
-       if (PRVM_G_FLOAT(OFS_PARM3) < 1)
-               return;
-       CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4), 0);
+       CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 0);
 }
 
 // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
 void VM_CL_te_particlesnow (void)
 {
        VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow);
-       if (PRVM_G_FLOAT(OFS_PARM3) < 1)
-               return;
-       CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4), 1);
+       CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 1);
 }
 
 // #411 void(vector org, vector vel, float howmany) te_spark
@@ -1585,11 +1389,9 @@ void VM_CL_te_spark (void)
        vec3_t          pos2;
        VM_SAFEPARMCOUNT(3, VM_CL_te_spark);
 
-       if (PRVM_G_FLOAT(OFS_PARM2) < 1)
-               return;
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       CL_SparkShower(pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2), 1, 0);
+       CL_ParticleEffect(EFFECT_TE_SPARK, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
 }
 
 // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
@@ -1597,16 +1399,11 @@ void VM_CL_te_gunshotquad (void)
 {
        float           *pos;
        vec3_t          pos2;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_gunshotquad);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       CL_SparkShower(pos2, vec3_origin, 15, 1, 0);
-       CL_Smoke(pos2, vec3_origin, 15, 0);
-       CL_BulletMark(pos2);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_ParticleEffect(EFFECT_TE_GUNSHOTQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
 }
 
 // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
@@ -1614,20 +1411,12 @@ void VM_CL_te_spikequad (void)
 {
        float           *pos;
        vec3_t          pos2;
-       matrix4x4_t     tempmatrix;
        int                     rnd;
        VM_SAFEPARMCOUNT(1, VM_CL_te_spikequad);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       if (cl_particles_bulletimpacts.integer)
-       {
-               CL_SparkShower(pos2, vec3_origin, 15, 1, 0);
-               CL_Smoke(pos2, vec3_origin, 15, 0);
-               CL_BulletMark(pos2);
-       }
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_ParticleEffect(EFFECT_TE_SPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
        else
        {
@@ -1643,20 +1432,12 @@ void VM_CL_te_superspikequad (void)
 {
        float           *pos;
        vec3_t          pos2;
-       matrix4x4_t     tempmatrix;
        int                     rnd;
        VM_SAFEPARMCOUNT(1, VM_CL_te_superspikequad);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       if (cl_particles_bulletimpacts.integer)
-       {
-               CL_SparkShower(pos2, vec3_origin, 30, 1, 0);
-               CL_Smoke(pos2, vec3_origin, 30, 0);
-               CL_BulletMark(pos2);
-       }
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_ParticleEffect(EFFECT_TE_SUPERSPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos, 1, 1);
        else
        {
@@ -1672,14 +1453,11 @@ void VM_CL_te_explosionquad (void)
 {
        float           *pos;
        vec3_t          pos2;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_explosionquad);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 10);
-       CL_ParticleExplosion(pos2);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 350, 2.5f, 2.0f, 4.0f, 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_ParticleEffect(EFFECT_TE_EXPLOSIONQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
 }
 
@@ -1688,13 +1466,11 @@ void VM_CL_te_smallflash (void)
 {
        float           *pos;
        vec3_t          pos2;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_smallflash);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 10);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 200, 2, 2, 2, 1000, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_ParticleEffect(EFFECT_TE_SMALLFLASH, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
 }
 
 // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
@@ -1720,9 +1496,7 @@ void VM_CL_te_gunshot (void)
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       CL_SparkShower(pos2, vec3_origin, 15, 1, 0);
-       CL_Smoke(pos2, vec3_origin, 15, 0);
-       CL_BulletMark(pos2);
+       CL_ParticleEffect(EFFECT_TE_GUNSHOT, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
 }
 
 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
@@ -1735,12 +1509,7 @@ void VM_CL_te_spike (void)
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       if (cl_particles_bulletimpacts.integer)
-       {
-               CL_SparkShower(pos2, vec3_origin, 15, 1, 0);
-               CL_Smoke(pos2, vec3_origin, 15, 0);
-               CL_BulletMark(pos2);
-       }
+       CL_ParticleEffect(EFFECT_TE_SPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
        else
        {
@@ -1761,12 +1530,7 @@ void VM_CL_te_superspike (void)
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       if (cl_particles_bulletimpacts.integer)
-       {
-               CL_SparkShower(pos2, vec3_origin, 30, 1, 0);
-               CL_Smoke(pos2, vec3_origin, 30, 0);
-               CL_BulletMark(pos2);
-       }
+       CL_ParticleEffect(EFFECT_TE_SUPERSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
        else
        {
@@ -1782,14 +1546,11 @@ void VM_CL_te_explosion (void)
 {
        float           *pos;
        vec3_t          pos2;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_explosion);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 10);
-       CL_ParticleExplosion(pos2);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 350, 4.0f, 2.0f, 0.50f, 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_ParticleEffect(EFFECT_TE_EXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
 }
 
@@ -1798,14 +1559,11 @@ void VM_CL_te_tarexplosion (void)
 {
        float           *pos;
        vec3_t          pos2;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_tarexplosion);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 10);
-       CL_BlobExplosion(pos2);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 600, 1.6f, 0.8f, 2.0f, 1200, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       CL_ParticleEffect(EFFECT_TE_TAREXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
 }
 
@@ -1814,14 +1572,11 @@ void VM_CL_te_wizspike (void)
 {
        float           *pos;
        vec3_t          pos2;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_wizspike);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 100, 0.12f, 0.50f, 0.12f, 500, 0.2, 0, -1, false, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       CL_RunParticleEffect(pos2, vec3_origin, 20, 30);
+       CL_ParticleEffect(EFFECT_TE_WIZSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        S_StartSound(-1, 0, cl.sfx_wizhit, pos2, 1, 1);
 }
 
@@ -1830,14 +1585,11 @@ void VM_CL_te_knightspike (void)
 {
        float           *pos;
        vec3_t          pos2;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_knightspike);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 100, 0.50f, 0.30f, 0.10f, 500, 0.2, 0, -1, false, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       CL_RunParticleEffect(pos2, vec3_origin, 226, 20);
+       CL_ParticleEffect(EFFECT_TE_KNIGHTSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
        S_StartSound(-1, 0, cl.sfx_knighthit, pos2, 1, 1);
 }
 
@@ -1845,20 +1597,14 @@ void VM_CL_te_knightspike (void)
 void VM_CL_te_lavasplash (void)
 {
        VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash);
-       CL_LavaSplash(PRVM_G_VECTOR(OFS_PARM0));
+       CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
 }
 
 // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
 void VM_CL_te_teleport (void)
 {
-       float           *pos;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_teleport);
-
-       pos = PRVM_G_VECTOR(OFS_PARM0);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 200, 1.0f, 1.0f, 1.0f, 600, 99.0f, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       CL_TeleportSplash(pos);
+       CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
 }
 
 // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
@@ -1872,8 +1618,8 @@ void VM_CL_te_explosion2 (void)
        VM_SAFEPARMCOUNT(3, VM_CL_te_explosion2);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
-       colorStart = PRVM_G_FLOAT(OFS_PARM1);
-       colorLength = PRVM_G_FLOAT(OFS_PARM2);
+       colorStart = (int)PRVM_G_FLOAT(OFS_PARM1);
+       colorLength = (int)PRVM_G_FLOAT(OFS_PARM2);
        CL_FindNonSolidLocation(pos, pos2, 10);
        CL_ParticleExplosion2(pos2, colorStart, colorLength);
        tempcolor = (unsigned char *)&palette_complete[(rand()%colorLength) + colorStart];
@@ -1886,74 +1632,32 @@ void VM_CL_te_explosion2 (void)
 }
 
 
-static void VM_CL_NewBeam (int ent, float *start, float *end, model_t *m, qboolean lightning)
-{
-       beam_t  *b;
-       int             i;
-
-       if (ent >= cl.max_csqcentities)
-               CL_ExpandCSQCEntities(ent);
-
-       // override any beam with the same entity
-       for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++)
-       {
-               if (b->entity == ent && ent)
-               {
-                       //b->entity = ent;
-                       b->lightning = lightning;
-                       b->relativestartvalid = (ent && cl.csqcentities[ent].state_current.active) ? 2 : 0;
-                       b->model = m;
-                       b->endtime = cl.time + 0.2;
-                       VectorCopy (start, b->start);
-                       VectorCopy (end, b->end);
-                       return;
-               }
-       }
-
-       // find a free beam
-       for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++)
-       {
-               if (!b->model || b->endtime < cl.time)
-               {
-                       b->entity = ent;
-                       b->lightning = lightning;
-                       b->relativestartvalid = (ent && cl.csqcentities[ent].state_current.active) ? 2 : 0;
-                       b->model = m;
-                       b->endtime = cl.time + 0.2;
-                       VectorCopy (start, b->start);
-                       VectorCopy (end, b->end);
-                       return;
-               }
-       }
-       Con_Print("beam list overflow!\n");
-}
-
 // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
 void VM_CL_te_lightning1 (void)
 {
        VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1);
-       VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
+       CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
 }
 
 // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
 void VM_CL_te_lightning2 (void)
 {
        VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2);
-       VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
+       CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
 }
 
 // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
 void VM_CL_te_lightning3 (void)
 {
        VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3);
-       VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
+       CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
 }
 
 // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
 void VM_CL_te_beam (void)
 {
        VM_SAFEPARMCOUNT(3, VM_CL_te_beam);
-       VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
+       CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
 }
 
 // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
@@ -1961,43 +1665,18 @@ void VM_CL_te_plasmaburn (void)
 {
        float           *pos;
        vec3_t          pos2;
-       matrix4x4_t     tempmatrix;
        VM_SAFEPARMCOUNT(1, VM_CL_te_plasmaburn);
 
        pos = PRVM_G_VECTOR(OFS_PARM0);
        CL_FindNonSolidLocation(pos, pos2, 4);
-       Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
-       CL_AllocDlight(NULL, &tempmatrix, 200, 1, 1, 1, 1000, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       CL_PlasmaBurn(pos2);
+       CL_ParticleEffect(EFFECT_TE_PLASMABURN, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
 }
 
 
 //====================================================================
 //DP_QC_GETSURFACE
 
-void clippointtosurface(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 = 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;
-}
+extern void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out);
 
 static msurface_t *cl_getsurface(model_t *model, int surfacenum)
 {
@@ -2009,10 +1688,10 @@ 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, PRVM_G_FLOAT(OFS_PARM1))))
+       if (!model || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
        {
                PRVM_G_FLOAT(OFS_RETURN) = 0;
                return;
@@ -2031,10 +1710,10 @@ 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, 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 = PRVM_G_FLOAT(OFS_PARM2);
+       pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
        if (pointnum < 0 || pointnum >= surface->num_vertices)
                return;
        // FIXME: implement rotation/scaling
@@ -2048,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, 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
@@ -2064,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, 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
@@ -2082,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
@@ -2101,7 +1780,7 @@ void VM_CL_getsurfacenearpoint(void)
                if (dist < bestdist)
                {
                        // it is, check the nearest point on the actual geometry
-                       clippointtosurface(surface, p, clipped);
+                       clippointtosurface(model, surface, p, clipped);
                        VectorSubtract(clipped, p, clipped);
                        dist += VectorLength2(clipped);
                        if (dist < bestdist)
@@ -2124,11 +1803,11 @@ 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, 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);
-       clippointtosurface(surface, p, out);
+       clippointtosurface(model, surface, p, out);
        // FIXME: implement rotation/scaling
        VectorAdd(out, ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
 }
@@ -2144,9 +1823,15 @@ void VM_CL_setattachment (void)
        model_t *model;
 
        if (e == prog->edicts)
-               PF_WARNING("setattachment: can not modify world entity\n");
+       {
+               VM_Warning("setattachment: can not modify world entity\n");
+               return;
+       }
        if (e->priv.server->free)
-               PF_WARNING("setattachment: can not modify free entity\n");
+       {
+               VM_Warning("setattachment: can not modify free entity\n");
+               return;
+       }
 
        if (tagentity == NULL)
                tagentity = prog->edicts;
@@ -2161,24 +1846,10 @@ 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, tagentity->fields.client->skin, tagname);
+                       v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.client->skin, tagname);
                        if (v->_float == 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);
                }
@@ -2192,27 +1863,11 @@ void VM_CL_setattachment (void)
 
 int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
 {
-       int i;
-       model_t *m;
-
-       i = 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, e->fields.client->skin, tagname);
+               return -1;
 };
 
 // Warnings/errors code:
@@ -2228,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;
@@ -2240,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;
@@ -2280,20 +1923,10 @@ 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 = 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, val->_float - 1, &attachmatrix);
+                               Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.client->frame].firstframe, (int)val->_float - 1, &attachmatrix);
                        else
                                attachmatrix = identitymatrix;
 
@@ -2303,16 +1936,10 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                                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);
                        Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
-                       out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
-                       out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
-                       out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
                        Matrix4x4_Copy(&tagmatrix, out);
 
                        // finally transformate by matrix of tag on parent entity
                        Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
-                       out->m[0][3] = attachmatrix.m[0][3] + attachmatrix.m[0][0]*tagmatrix.m[0][3] + attachmatrix.m[0][1]*tagmatrix.m[1][3] + attachmatrix.m[0][2]*tagmatrix.m[2][3];
-                       out->m[1][3] = attachmatrix.m[1][3] + attachmatrix.m[1][0]*tagmatrix.m[0][3] + attachmatrix.m[1][1]*tagmatrix.m[1][3] + attachmatrix.m[1][2]*tagmatrix.m[2][3];
-                       out->m[2][3] = attachmatrix.m[2][3] + attachmatrix.m[2][0]*tagmatrix.m[0][3] + attachmatrix.m[2][1]*tagmatrix.m[1][3] + attachmatrix.m[2][2]*tagmatrix.m[2][3];
                        Matrix4x4_Copy(&tagmatrix, out);
 
                        ent = attachent;
@@ -2330,9 +1957,6 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
        // 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);
-       out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
-       out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
-       out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
 
        if ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_renderflags)) && (RF_VIEWMODEL & (int)val->_float))
        {// RENDER_VIEWMODEL magic
@@ -2344,9 +1968,6 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
 
                Matrix4x4_CreateFromQuakeEntity(&entitymatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], val->_float);
                Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
-               out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
-               out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
-               out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
 
                /*
                // Cl_bob, ported from rendering code
@@ -2367,7 +1988,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                        // (don't count Z, or jumping messes it up)
                        bob = sqrt(ent->fields.client->velocity[0]*ent->fields.client->velocity[0] + ent->fields.client->velocity[1]*ent->fields.client->velocity[1])*cl_bob.value;
                        bob = bob*0.3 + bob*0.7*cycle;
-                       out->m[2][3] += bound(-7, bob, 4);
+                       Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
                }
                */
        }
@@ -2382,9 +2003,15 @@ void VM_CL_gettagindex (void)
        int modelindex, tag_index;
 
        if (ent == prog->edicts)
-               PF_WARNING("gettagindex: can't affect world entity\n");
+       {
+               VM_Warning("gettagindex: can't affect world entity\n");
+               return;
+       }
        if (ent->priv.server->free)
-               PF_WARNING("gettagindex: can't affect free entity\n");
+       {
+               VM_Warning("gettagindex: can't affect free entity\n");
+               return;
+       }
 
        modelindex = (int)ent->fields.client->modelindex;
        if(modelindex < 0)
@@ -2415,10 +2042,10 @@ void VM_CL_gettaginfo (void)
        switch(returncode)
        {
                case 1:
-                       PF_WARNING("gettagindex: can't affect world entity\n");
+                       VM_Warning("gettagindex: can't affect world entity\n");
                        break;
                case 2:
-                       PF_WARNING("gettagindex: can't affect free entity\n");
+                       VM_Warning("gettagindex: can't affect free entity\n");
                        break;
                case 3:
                        Con_DPrintf("CL_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
@@ -2534,7 +2161,7 @@ static int Is_Text_Color (char c, char t)
        char c2 = c - (c & 128);
        char t2 = t - (t & 128);
 
-       if(c != '^' && c2 != '^')               return 0;
+       if(c != STRING_COLOR_TAG && c2 != STRING_COLOR_TAG)             return 0;
        if(t >= '0' && t <= '9')                a = 1;
        if(t2 >= '0' && t2 <= '9')              a = 1;
 /*     if(t >= 'A' && t <= 'Z')                a = 2;
@@ -2551,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])
        {
@@ -2573,6 +2197,7 @@ void VM_uncolorstring (void) //#170
                ++k;
                ++i;
        }
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(out);
 }
 
 void VM_CL_selecttraceline (void)
@@ -2582,20 +2207,16 @@ void VM_CL_selecttraceline (void)
 
        v1 = PRVM_G_VECTOR(OFS_PARM0);
        v2 = PRVM_G_VECTOR(OFS_PARM1);
-       ignore = PRVM_G_FLOAT(OFS_PARM2);
-       csqcents = PRVM_G_FLOAT(OFS_PARM3);
+       ignore = (int)PRVM_G_FLOAT(OFS_PARM2);
+       csqcents = (int)PRVM_G_FLOAT(OFS_PARM3);
        ent = 0;
 
-       if((csqcents && ignore > cl.num_csqcentities) || (!csqcents && ignore > cl.num_entities))
+       if (csqcents)
        {
-               Con_Printf("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;
 }
 
@@ -2603,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)];
@@ -2613,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)
@@ -2960,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);