]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - pr_cmds.c
PROTOCOL_DARKPLACES5
[xonotic/darkplaces.git] / pr_cmds.c
index 1665e497119ee3c2bffbd41019a06637c34c6461..32fe4cf7b15177565993092ed1b698e7689617f4 100644 (file)
--- a/pr_cmds.c
+++ b/pr_cmds.c
@@ -20,9 +20,28 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 
-cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default
+cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default
+cvar_t pr_zone_min_strings = {0, "pr_zone_min_strings", "64"};
 
-#define        RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
+mempool_t *pr_strings_mempool;
+
+// LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
+#define STRINGTEMP_BUFFERS 16
+#define STRINGTEMP_LENGTH 4096
+static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH];
+static int pr_string_tempindex = 0;
+
+static char *PR_GetTempString(void)
+{
+       char *s;
+       s = pr_string_temp[pr_string_tempindex];
+       pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS;
+       return s;
+}
+
+#define        RETURN_EDICT(e) (G_INT(OFS_RETURN) = EDICT_TO_PROG(e))
+#define PF_WARNING(s) do{Con_Printf(s);PR_PrintState();return;}while(0)
+#define PF_ERROR(s) do{Host_Error(s);return;}while(0)
 
 
 /*
@@ -34,61 +53,109 @@ cvar_t     sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled au
 */
 
 
-char *PF_VarString (int        first)
+void PF_VarString(int first, char *out, int outlength)
 {
-       int             i;
-       static char out[256];
-
-       out[0] = 0;
-       for (i=first ; i<pr_argc ; i++)
-       {
-               strcat (out, G_STRING((OFS_PARM0+i*3)));
-       }
-       return out;
-}
-
-char *ENGINE_EXTENSIONS = "\
-DP_ENT_ALPHA \
-DP_ENT_COLORMOD \
-DP_ENT_DELTACOMPRESS \
-DP_ENT_GLOW \
-DP_ENT_SCALE \
-DP_ENT_VIEWMODEL \
-DP_GFX_FOG \
-DP_HALFLIFE_MAP \
-DP_INPUTBUTTONS \
-DP_MONSTERWALK \
-DP_MOVETYPEFOLLOW \
-DP_SOLIDCORPSE \
-DP_REGISTERCVAR \
-DP_SPRITE32 \
-DP_SV_DRAWONLYTOCLIENT \
-DP_SV_NODRAWTOCLIENT \
-DP_SV_EXTERIORMODELTOCLIENT \
-DP_SV_SETCOLOR \
-DP_SV_EFFECT \
-DP_TE_BLOOD \
-DP_TE_BLOODSHOWER \
-DP_TE_EXPLOSIONRGB \
-DP_TE_PARTICLECUBE \
-DP_TE_PARTICLERAIN \
-DP_TE_PARTICLESNOW \
-DP_TE_SPARK \
-DP_QC_CHANGEPITCH \
-DP_QC_COPYENTITY \
-DP_QC_ETOS \
-DP_QC_FINDFLOAT \
-DP_QC_FINDCHAIN \
-DP_QC_FINDCHAINFLOAT \
-DP_QC_GETLIGHT \
-DP_QC_SINCOSSQRTPOW \
-DP_QC_MINMAXBOUND \
-DP_QC_RANDOMVEC \
-DP_QC_TRACEBOX \
-DP_QC_TRACETOSS \
-DP_QUAKE2_MODEL \
-NEH_CMD_PLAY2 \
-";
+       int i;
+       const char *s;
+       char *outend;
+
+       outend = out + outlength - 1;
+       for (i = first;i < pr_argc && out < outend;i++)
+       {
+               s = G_STRING((OFS_PARM0+i*3));
+               while (out < outend && *s)
+                       *out++ = *s++;
+       }
+       *out++ = 0;
+}
+
+char *ENGINE_EXTENSIONS =
+"DP_CL_LOADSKY "
+"DP_EF_ADDITIVE "
+"DP_EF_BLUE "
+"DP_EF_FLAME "
+"DP_EF_FULLBRIGHT "
+"DP_EF_NODRAW "
+"DP_EF_NOSHADOW "
+"DP_EF_RED "
+"DP_EF_STARDUST "
+"DP_ENT_ALPHA "
+"DP_ENT_CUSTOMCOLORMAP "
+"DP_ENT_EXTERIORMODELTOCLIENT "
+"DP_ENT_GLOW "
+"DP_ENT_LOWPRECISION "
+"DP_ENT_SCALE "
+"DP_ENT_VIEWMODEL "
+"DP_GFX_EXTERNALTEXTURES "
+"DP_GFX_FOG "
+"DP_GFX_QUAKE3MODELTAGS "
+"DP_GFX_SKINFILES "
+"DP_GFX_SKYBOX "
+"DP_HALFLIFE_MAP "
+"DP_HALFLIFE_MAP_CVAR "
+"DP_INPUTBUTTONS "
+"DP_LITSUPPORT "
+"DP_MONSTERWALK "
+"DP_MOVETYPEBOUNCEMISSILE "
+"DP_MOVETYPEFOLLOW "
+"DP_QC_CHANGEPITCH "
+"DP_QC_COPYENTITY "
+"DP_QC_CVAR_STRING "
+"DP_QC_ETOS "
+"DP_QC_FINDCHAIN "
+"DP_QC_FINDCHAINFLAGS "
+"DP_QC_FINDCHAINFLOAT "
+"DP_QC_FINDFLAGS "
+"DP_QC_FINDFLOAT "
+"DP_QC_FS_SEARCH " // Black: same as in the menu qc
+"DP_QC_GETLIGHT "
+"DP_QC_GETSURFACE "
+"DP_QC_MINMAXBOUND "
+"DP_QC_MULTIPLETEMPSTRINGS "
+"DP_QC_RANDOMVEC "
+"DP_QC_SINCOSSQRTPOW "
+"DP_QC_TRACEBOX "
+"DP_QC_TRACETOSS "
+"DP_QC_TRACE_MOVETYPE_HITMODEL "
+"DP_QC_TRACE_MOVETYPE_WORLDONLY "
+"DP_QC_VECTORVECTORS "
+"DP_QUAKE2_MODEL "
+"DP_QUAKE3_MODEL "
+"DP_REGISTERCVAR "
+"DP_SND_DIRECTIONLESSATTNNONE "
+"DP_SND_OGGVORBIS "
+"DP_SND_STEREOWAV "
+"DP_SOLIDCORPSE "
+"DP_SPRITE32 "
+"DP_SV_DRAWONLYTOCLIENT "
+"DP_SV_EFFECT "
+"DP_SV_EXTERIORMODELTOCLIENT "
+"DP_SV_NODRAWTOCLIENT "
+"DP_SV_PLAYERPHYSICS "
+"DP_SV_ROTATINGBMODEL "
+"DP_SV_SETCOLOR "
+"DP_SV_SLOWMO "
+"DP_TE_BLOOD "
+"DP_TE_BLOODSHOWER "
+"DP_TE_CUSTOMFLASH "
+"DP_TE_EXPLOSIONRGB "
+"DP_TE_FLAMEJET "
+"DP_TE_PARTICLECUBE "
+"DP_TE_PARTICLERAIN "
+"DP_TE_PARTICLESNOW "
+"DP_TE_PLASMABURN "
+"DP_TE_QUADEFFECTS1 "
+"DP_TE_SMALLFLASH "
+"DP_TE_SPARK "
+"DP_TE_STANDARDEFFECTBUILTINS "
+"DP_VIEWZOOM "
+"FRIK_FILE "
+"KRIMZON_SV_PARSECLIENTCOMMAND "
+"NEH_CMD_PLAY2 "
+"NEH_RESTOREGAME "
+"TENEBRAE_GFX_DLIGHTS "
+"TW_SV_STEPCONTROL "
+;
 
 qboolean checkextension(char *name)
 {
@@ -105,7 +172,7 @@ qboolean checkextension(char *name)
                while (*e && *e != ' ')
                        e++;
                if (e - start == len)
-                       if (!strncasecmp(e, name, len))
+                       if (!strncasecmp(start, name, len))
                                return true;
        }
        return false;
@@ -137,15 +204,15 @@ error(value)
 */
 void PF_error (void)
 {
-       char    *s;
        edict_t *ed;
-       
-       s = PF_VarString(0);
-       Con_Printf ("======SERVER ERROR in %s:\n%s\n", pr_strings + pr_xfunction->s_name, s);
+       char string[STRINGTEMP_LENGTH];
+
+       PF_VarString(0, string, sizeof(string));
+       Con_Printf("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
        ed = PROG_TO_EDICT(pr_global_struct->self);
-       ED_Print (ed);
+       ED_Print(ed);
 
-       Host_Error ("Program error");
+       PF_ERROR("Program error");
 }
 
 /*
@@ -160,21 +227,17 @@ objerror(value)
 */
 void PF_objerror (void)
 {
-       char    *s;
        edict_t *ed;
-       
-       s = PF_VarString(0);
-       Con_Printf ("======OBJECT ERROR in %s:\n%s\n", pr_strings + pr_xfunction->s_name, s);
+       char string[STRINGTEMP_LENGTH];
+
+       PF_VarString(0, string, sizeof(string));
+       Con_Printf("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
        ed = PROG_TO_EDICT(pr_global_struct->self);
-       ED_Print (ed);
+       ED_Print(ed);
        ED_Free (ed);
-
-// LordHavoc: bug fix - no longer kills server
-//     Host_Error ("Program error");
 }
 
 
-
 /*
 ==============
 PF_makevectors
@@ -215,94 +278,30 @@ void PF_setorigin (void)
 {
        edict_t *e;
        float   *org;
-       
+
        e = G_EDICT(OFS_PARM0);
+       if (e == sv.edicts)
+               PF_WARNING("setorigin: can not modify world entity\n");
+       if (e->e->free)
+               PF_WARNING("setorigin: can not modify free entity\n");
        org = G_VECTOR(OFS_PARM1);
-       VectorCopy (org, e->v.origin);
+       VectorCopy (org, e->v->origin);
        SV_LinkEdict (e, false);
 }
 
 
 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
 {
-       /*
-       float   *angles;
-       vec3_t  rmin, rmax;
-       float   bounds[2][3];
-       float   xvector[2], yvector[2];
-       float   a;
-       vec3_t  base, transformed;
-       int             i, j, k, l;
-       */
        int             i;
-       
+
        for (i=0 ; i<3 ; i++)
                if (min[i] > max[i])
-                       PR_RunError ("backwards mins/maxs");
+                       PF_ERROR("SetMinMaxSize: backwards mins/maxs\n");
 
-       /*
-       rotate = false;         // FIXME: implement rotation properly again
-
-       if (!rotate)
-       {
-               VectorCopy (min, rmin);
-               VectorCopy (max, rmax);
-       }
-       else
-       {
-       // find min / max for rotations
-               angles = e->v.angles;
-               
-               a = angles[1]/180 * M_PI;
-
-               xvector[0] = cos(a);
-               xvector[1] = sin(a);
-               yvector[0] = -sin(a);
-               yvector[1] = cos(a);
-               
-               VectorCopy (min, bounds[0]);
-               VectorCopy (max, bounds[1]);
-
-               rmin[0] = rmin[1] = rmin[2] = 9999;
-               rmax[0] = rmax[1] = rmax[2] = -9999;
-               
-               for (i=0 ; i<= 1 ; i++)
-               {
-                       base[0] = bounds[i][0];
-                       for (j=0 ; j<= 1 ; j++)
-                       {
-                               base[1] = bounds[j][1];
-                               for (k=0 ; k<= 1 ; k++)
-                               {
-                                       base[2] = bounds[k][2];
-                                       
-                               // transform the point
-                                       transformed[0] = xvector[0]*base[0] + yvector[0]*base[1];
-                                       transformed[1] = xvector[1]*base[0] + yvector[1]*base[1];
-                                       transformed[2] = base[2];
-                                       
-                                       for (l=0 ; l<3 ; l++)
-                                       {
-                                               if (transformed[l] < rmin[l])
-                                                       rmin[l] = transformed[l];
-                                               if (transformed[l] > rmax[l])
-                                                       rmax[l] = transformed[l];
-                                       }
-                               }
-                       }
-               }
-       }
-       
-// set derived values
-       VectorCopy (rmin, e->v.mins);
-       VectorCopy (rmax, e->v.maxs);
-       VectorSubtract (max, min, e->v.size);
-       */
-       
 // set derived values
-       VectorCopy (min, e->v.mins);
-       VectorCopy (max, e->v.maxs);
-       VectorSubtract (max, min, e->v.size);
+       VectorCopy (min, e->v->mins);
+       VectorCopy (max, e->v->maxs);
+       VectorSubtract (max, min, e->v->size);
 
        SV_LinkEdict (e, false);
 }
@@ -321,8 +320,12 @@ void PF_setsize (void)
 {
        edict_t *e;
        float   *min, *max;
-       
+
        e = G_EDICT(OFS_PARM0);
+       if (e == sv.edicts)
+               PF_WARNING("setsize: can not modify world entity\n");
+       if (e->e->free)
+               PF_WARNING("setsize: can not modify free entity\n");
        min = G_VECTOR(OFS_PARM1);
        max = G_VECTOR(OFS_PARM2);
        SetMinMaxSize (e, min, max, false);
@@ -344,6 +347,10 @@ void PF_setmodel (void)
        int             i;
 
        e = G_EDICT(OFS_PARM0);
+       if (e == sv.edicts)
+               PF_WARNING("setmodel: can not modify world entity\n");
+       if (e->e->free)
+               PF_WARNING("setmodel: can not modify free entity\n");
        m = G_STRING(OFS_PARM1);
 
 // check to see if model was properly precached
@@ -352,28 +359,15 @@ void PF_setmodel (void)
                        break;
 
        if (!*check)
-               PR_RunError ("no precache: %s\n", m);
+               PF_WARNING("setmodel: no precache\n");
 
 
-       e->v.model = m - pr_strings;
-       e->v.modelindex = i; //SV_ModelIndex (m);
+       e->v->model = PR_SetString(*check);
+       e->v->modelindex = i;
 
-       mod = sv.models[ (int)e->v.modelindex];  // Mod_ForName (m, true);
+       mod = sv.models[ (int)e->v->modelindex];
 
        if (mod)
-       /*
-       { // LordHavoc: corrected model bounding box, but for compatibility that means I have to break it here
-               vec3_t min, max;
-               if (mod->type == ALIASTYPE_MDL)
-               {
-                       min[0] = min[1] = min[2] = -16;
-                       max[0] = max[1] = max[2] = 16;
-                       SetMinMaxSize (e, min, max, true);
-               }
-               else
-                       SetMinMaxSize (e, mod->mins, mod->maxs, true);
-       }
-       */
                SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
        else
                SetMinMaxSize (e, vec3_origin, vec3_origin, true);
@@ -390,10 +384,9 @@ bprint(value)
 */
 void PF_bprint (void)
 {
-       char            *s;
-
-       s = PF_VarString(0);
-       SV_BroadcastPrintf ("%s", s);
+       char string[STRINGTEMP_LENGTH];
+       PF_VarString(0, string, sizeof(string));
+       SV_BroadcastPrint(string);
 }
 
 /*
@@ -407,23 +400,24 @@ sprint(clientent, value)
 */
 void PF_sprint (void)
 {
-       char            *s;
        client_t        *client;
        int                     entnum;
-       
+       char string[STRINGTEMP_LENGTH];
+
        entnum = G_EDICTNUM(OFS_PARM0);
-       s = PF_VarString(1);
-       
-       if (entnum < 1 || entnum > svs.maxclients)
+
+       if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
        {
-               Con_Print("tried to sprint to a non-client\n");
+               Con_Print("tried to sprint to a non-client\n");
                return;
        }
-               
-       client = &svs.clients[entnum-1];
-               
-       MSG_WriteChar (&client->message,svc_print);
-       MSG_WriteString (&client->message, s );
+
+       client = svs.clients + entnum-1;
+       if (!client->netconnection)
+               return;
+       PF_VarString(1, string, sizeof(string));
+       MSG_WriteChar(&client->message,svc_print);
+       MSG_WriteString(&client->message, string);
 }
 
 
@@ -438,23 +432,24 @@ centerprint(clientent, value)
 */
 void PF_centerprint (void)
 {
-       char            *s;
        client_t        *client;
        int                     entnum;
-       
+       char string[STRINGTEMP_LENGTH];
+
        entnum = G_EDICTNUM(OFS_PARM0);
-       s = PF_VarString(1);
-       
-       if (entnum < 1 || entnum > svs.maxclients)
+
+       if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
        {
-               Con_Print("tried to sprint to a non-client\n");
+               Con_Print("tried to sprint to a non-client\n");
                return;
        }
-               
-       client = &svs.clients[entnum-1];
-               
-       MSG_WriteChar (&client->message,svc_centerprint);
-       MSG_WriteString (&client->message, s );
+
+       client = svs.clients + entnum-1;
+       if (!client->netconnection)
+               return;
+       PF_VarString(1, string, sizeof(string));
+       MSG_WriteChar(&client->message,svc_centerprint);
+       MSG_WriteString(&client->message, string);
 }
 
 
@@ -470,12 +465,12 @@ void PF_normalize (void)
        float   *value1;
        vec3_t  newvalue;
        float   new;
-       
+
        value1 = G_VECTOR(OFS_PARM0);
 
        new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
        new = sqrt(new);
-       
+
        if (new == 0)
                newvalue[0] = newvalue[1] = newvalue[2] = 0;
        else
@@ -485,8 +480,8 @@ void PF_normalize (void)
                newvalue[1] = value1[1] * new;
                newvalue[2] = value1[2] * new;
        }
-       
-       VectorCopy (newvalue, G_VECTOR(OFS_RETURN));    
+
+       VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
 }
 
 /*
@@ -505,7 +500,7 @@ void PF_vlen (void)
 
        new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
        new = sqrt(new);
-       
+
        G_FLOAT(OFS_RETURN) = new;
 }
 
@@ -520,7 +515,7 @@ void PF_vectoyaw (void)
 {
        float   *value1;
        float   yaw;
-       
+
        value1 = G_VECTOR(OFS_PARM0);
 
        if (value1[1] == 0 && value1[0] == 0)
@@ -548,7 +543,7 @@ void PF_vectoangles (void)
        float   *value1;
        float   forward;
        float   yaw, pitch;
-       
+
        value1 = G_VECTOR(OFS_PARM0);
 
        if (value1[1] == 0 && value1[0] == 0)
@@ -596,9 +591,9 @@ random()
 void PF_random (void)
 {
        float           num;
-               
+
        num = (rand ()&0x7fff) / ((float)0x7fff);
-       
+
        G_FLOAT(OFS_RETURN) = num;
 }
 
@@ -614,7 +609,7 @@ void PF_particle (void)
        float           *org, *dir;
        float           color;
        float           count;
-                       
+
        org = G_VECTOR(OFS_PARM0);
        dir = G_VECTOR(OFS_PARM1);
        color = G_FLOAT(OFS_PARM2);
@@ -635,13 +630,13 @@ void PF_ambientsound (void)
        char            *samp;
        float           *pos;
        float           vol, attenuation;
-       int                     i, soundnum, large;
+       int                     soundnum, large;
 
-       pos = G_VECTOR (OFS_PARM0);                     
+       pos = G_VECTOR (OFS_PARM0);
        samp = G_STRING(OFS_PARM1);
        vol = G_FLOAT(OFS_PARM2);
        attenuation = G_FLOAT(OFS_PARM3);
-       
+
 // check to see if samp was properly precached
        for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
                if (!strcmp(*check,samp))
@@ -649,7 +644,7 @@ void PF_ambientsound (void)
 
        if (!*check)
        {
-               Con_Printf ("no precache: %s\n", samp);
+               Con_Printf("no precache: %s\n", samp);
                return;
        }
 
@@ -664,8 +659,7 @@ void PF_ambientsound (void)
        else
                MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
 
-       for (i=0 ; i<3 ; i++)
-               MSG_WriteDPCoord(&sv.signon, pos[i]);
+       MSG_WriteVector(&sv.signon, pos, sv.protocol);
 
        if (large)
                MSG_WriteShort (&sv.signon, soundnum);
@@ -699,21 +693,21 @@ void PF_sound (void)
        edict_t         *entity;
        int             volume;
        float attenuation;
-               
+
        entity = G_EDICT(OFS_PARM0);
        channel = G_FLOAT(OFS_PARM1);
        sample = G_STRING(OFS_PARM2);
        volume = G_FLOAT(OFS_PARM3) * 255;
        attenuation = G_FLOAT(OFS_PARM4);
-       
+
        if (volume < 0 || volume > 255)
-               Host_Error ("SV_StartSound: volume = %i", volume);
+               PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
 
        if (attenuation < 0 || attenuation > 4)
-               Host_Error ("SV_StartSound: attenuation = %f", attenuation);
+               PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
 
        if (channel < 0 || channel > 7)
-               Host_Error ("SV_StartSound: channel = %i", channel);
+               PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
 
        SV_StartSound (entity, channel, sample, volume, attenuation);
 }
@@ -727,9 +721,7 @@ break()
 */
 void PF_break (void)
 {
-//     Con_Printf ("break statement\n");
-//     *(int *)-4 = 0; // dump to debugger
-       PR_RunError ("break statement");
+       PF_ERROR("break: break statement\n");
 }
 
 /*
@@ -747,15 +739,17 @@ void PF_traceline (void)
 {
        float   *v1, *v2;
        trace_t trace;
-       int             nomonsters;
+       int             move;
        edict_t *ent;
 
+       pr_xfunction->builtinsprofile += 30;
+
        v1 = G_VECTOR(OFS_PARM0);
        v2 = G_VECTOR(OFS_PARM1);
-       nomonsters = G_FLOAT(OFS_PARM2);
+       move = G_FLOAT(OFS_PARM2);
        ent = G_EDICT(OFS_PARM3);
 
-       trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent);
+       trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
 
        pr_global_struct->trace_allsolid = trace.allsolid;
        pr_global_struct->trace_startsolid = trace.startsolid;
@@ -789,17 +783,19 @@ void PF_tracebox (void)
 {
        float   *v1, *v2, *m1, *m2;
        trace_t trace;
-       int             nomonsters;
+       int             move;
        edict_t *ent;
 
+       pr_xfunction->builtinsprofile += 30;
+
        v1 = G_VECTOR(OFS_PARM0);
        m1 = G_VECTOR(OFS_PARM1);
        m2 = G_VECTOR(OFS_PARM2);
        v2 = G_VECTOR(OFS_PARM3);
-       nomonsters = G_FLOAT(OFS_PARM4);
+       move = G_FLOAT(OFS_PARM4);
        ent = G_EDICT(OFS_PARM5);
 
-       trace = SV_Move (v1, m1, m2, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent);
+       trace = SV_Move (v1, m1, m2, v2, move, ent);
 
        pr_global_struct->trace_allsolid = trace.allsolid;
        pr_global_struct->trace_startsolid = trace.startsolid;
@@ -808,7 +804,7 @@ void PF_tracebox (void)
        pr_global_struct->trace_inopen = trace.inopen;
        VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
        VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
-       pr_global_struct->trace_plane_dist =  trace.plane.dist; 
+       pr_global_struct->trace_plane_dist =  trace.plane.dist;
        if (trace.ent)
                pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
        else
@@ -822,7 +818,11 @@ void PF_TraceToss (void)
        edict_t *ent;
        edict_t *ignore;
 
+       pr_xfunction->builtinsprofile += 600;
+
        ent = G_EDICT(OFS_PARM0);
+       if (ent == sv.edicts)
+               PF_WARNING("tracetoss: can not use world entity\n");
        ignore = G_EDICT(OFS_PARM1);
 
        trace = SV_Trace_Toss (ent, ignore);
@@ -834,7 +834,7 @@ void PF_TraceToss (void)
        pr_global_struct->trace_inopen = trace.inopen;
        VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
        VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
-       pr_global_struct->trace_plane_dist =  trace.plane.dist; 
+       pr_global_struct->trace_plane_dist =  trace.plane.dist;
        if (trace.ent)
                pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
        else
@@ -858,23 +858,18 @@ void PF_checkpos (void)
 
 //============================================================================
 
-byte   checkpvs[MAX_MAP_LEAFS/8];
+int checkpvsbytes;
+qbyte checkpvs[MAX_MAP_LEAFS/8];
 
 int PF_newcheckclient (int check)
 {
        int             i;
-       byte    *pvs;
        edict_t *ent;
-       mleaf_t *leaf;
        vec3_t  org;
 
 // cycle to the next one
 
-       if (check < 1)
-               check = 1;
-       if (check > svs.maxclients)
-               check = svs.maxclients;
-
+       check = bound(1, check, svs.maxclients);
        if (check == svs.maxclients)
                i = 1;
        else
@@ -882,30 +877,25 @@ int PF_newcheckclient (int check)
 
        for ( ;  ; i++)
        {
+               // count the cost
+               pr_xfunction->builtinsprofile++;
+               // wrap around
                if (i == svs.maxclients+1)
                        i = 1;
-
+               // look up the client's edict
                ent = EDICT_NUM(i);
-
-               if (i == check)
-                       break;  // didn't find anything else
-
-               if (ent->free)
-                       continue;
-               if (ent->v.health <= 0)
+               // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
+               if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
                        continue;
-               if ((int)ent->v.flags & FL_NOTARGET)
-                       continue;
-
-       // anything that is a client, or has a client as an enemy
+               // found a valid client (possibly the same one again)
                break;
        }
 
 // get the PVS for the entity
-       VectorAdd (ent->v.origin, ent->v.view_ofs, org);
-       leaf = Mod_PointInLeaf (org, sv.worldmodel);
-       pvs = Mod_LeafPVS (leaf, sv.worldmodel);
-       memcpy (checkpvs, pvs, (sv.worldmodel->numleafs+7)>>3 );
+       VectorAdd(ent->v->origin, ent->v->view_ofs, org);
+       checkpvsbytes = 0;
+       if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
+               checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
 
        return i;
 }
@@ -929,39 +919,35 @@ int c_invis, c_notvis;
 void PF_checkclient (void)
 {
        edict_t *ent, *self;
-       mleaf_t *leaf;
-       int             l;
        vec3_t  view;
-       
-// find a new check if on a new frame
+
+       // find a new check if on a new frame
        if (sv.time - sv.lastchecktime >= 0.1)
        {
                sv.lastcheck = PF_newcheckclient (sv.lastcheck);
                sv.lastchecktime = sv.time;
        }
 
-// return check if it might be visible 
+       // return check if it might be visible
        ent = EDICT_NUM(sv.lastcheck);
-       if (ent->free || ent->v.health <= 0)
+       if (ent->e->free || ent->v->health <= 0)
        {
                RETURN_EDICT(sv.edicts);
                return;
        }
 
-// if current entity can't possibly see the check entity, return 0
+       // if current entity can't possibly see the check entity, return 0
        self = PROG_TO_EDICT(pr_global_struct->self);
-       VectorAdd (self->v.origin, self->v.view_ofs, view);
-       leaf = Mod_PointInLeaf (view, sv.worldmodel);
-       l = (leaf - sv.worldmodel->leafs) - 1;
-       if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
+       VectorAdd(self->v->origin, self->v->view_ofs, view);
+       if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
        {
-c_notvis++;
+               c_notvis++;
                RETURN_EDICT(sv.edicts);
                return;
        }
 
-// might be able to see it
-c_invis++;
+       // might be able to see it
+       c_invis++;
        RETURN_EDICT(ent);
 }
 
@@ -982,15 +968,18 @@ void PF_stuffcmd (void)
        int             entnum;
        char    *str;
        client_t        *old;
-       
+
        entnum = G_EDICTNUM(OFS_PARM0);
-       if (entnum < 1 || entnum > svs.maxclients)
-               PR_RunError ("Parm 0 not a client");
-       str = G_STRING(OFS_PARM1);      
-       
+       if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
+       {
+               Con_Print("Can't stuffcmd to a non-client\n");
+               return;
+       }
+       str = G_STRING(OFS_PARM1);
+
        old = host_client;
-       host_client = &svs.clients[entnum-1];
-       Host_ClientCommands ("%s", str);
+       if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
+               Host_ClientCommands ("%s", str);
        host_client = old;
 }
 
@@ -998,17 +987,14 @@ void PF_stuffcmd (void)
 =================
 PF_localcmd
 
-Sends text over to the client's execution buffer
+Sends text to server console
 
 localcmd (string)
 =================
 */
 void PF_localcmd (void)
 {
-       char    *str;
-
-       str = G_STRING(OFS_PARM0);      
-       Cbuf_AddText (str);
+       Cbuf_AddText(G_STRING(OFS_PARM0));
 }
 
 /*
@@ -1020,11 +1006,7 @@ float cvar (string)
 */
 void PF_cvar (void)
 {
-       char    *str;
-       
-       str = G_STRING(OFS_PARM0);
-       
-       G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str);
+       G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
 }
 
 /*
@@ -1036,12 +1018,7 @@ float cvar (string)
 */
 void PF_cvar_set (void)
 {
-       char    *var, *val;
-       
-       var = G_STRING(OFS_PARM0);
-       val = G_STRING(OFS_PARM1);
-       
-       Cvar_Set (var, val);
+       Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
 }
 
 /*
@@ -1055,30 +1032,37 @@ findradius (origin, radius)
 */
 void PF_findradius (void)
 {
-       edict_t *ent, *chain;
-       float   rad;
-       float   *org;
-       vec3_t  eorg;
-       int             i, j;
+       edict_t *ent, *chain;
+       float radius;
+       float radius2;
+       float *org;
+       float eorg[3];
+       int i;
 
        chain = (edict_t *)sv.edicts;
-       
+
        org = G_VECTOR(OFS_PARM0);
-       rad = G_FLOAT(OFS_PARM1);
+       radius = G_FLOAT(OFS_PARM1);
+       radius2 = radius * radius;
 
        ent = NEXT_EDICT(sv.edicts);
        for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
        {
-               if (ent->free)
+               pr_xfunction->builtinsprofile++;
+               if (ent->e->free)
                        continue;
-               if (ent->v.solid == SOLID_NOT)
+               if (ent->v->solid == SOLID_NOT)
                        continue;
-               for (j=0 ; j<3 ; j++)
-                       eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j])*0.5);                  
-               if (Length(eorg) > rad)
+
+               // LordHavoc: compare against bounding box rather than center,
+               // and use DotProduct instead of Length, major speedup
+               eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
+               eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
+               eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
+               if (DotProduct(eorg, eorg) > radius2)
                        continue;
-                       
-               ent->v.chain = EDICT_TO_PROG(chain);
+
+               ent->v->chain = EDICT_TO_PROG(chain);
                chain = ent;
        }
 
@@ -1093,21 +1077,12 @@ PF_dprint
 */
 void PF_dprint (void)
 {
-       Con_DPrintf ("%s",PF_VarString(0));
-}
-
-// LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
-#define STRINGTEMP_BUFFERS 16
-#define STRINGTEMP_LENGTH 128
-static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH];
-static int pr_string_tempindex = 0;
-
-static char *PR_GetTempString(void)
-{
-       char *s;
-       s = pr_string_temp[pr_string_tempindex];
-       pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS;
-       return s;
+       char string[STRINGTEMP_LENGTH];
+       if (developer.integer)
+       {
+               PF_VarString(0, string, sizeof(string));
+               Con_Print(string);
+       }
 }
 
 void PF_ftos (void)
@@ -1117,15 +1092,11 @@ void PF_ftos (void)
        v = G_FLOAT(OFS_PARM0);
 
        s = PR_GetTempString();
-       /*
-       if (v == (int)v)
-               sprintf (s, "%d",(int)v);
+       if ((float)((int)v) == v)
+               sprintf(s, "%i", (int)v);
        else
-               sprintf (s, "%5.1f",v);
-       */
-       // LordHavoc: ftos improvement
-       sprintf (s, "%g", v);
-       G_INT(OFS_RETURN) = s - pr_strings;
+               sprintf(s, "%f", v);
+       G_INT(OFS_RETURN) = PR_SetString(s);
 }
 
 void PF_fabs (void)
@@ -1140,7 +1111,7 @@ void PF_vtos (void)
        char *s;
        s = PR_GetTempString();
        sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
-       G_INT(OFS_RETURN) = s - pr_strings;
+       G_INT(OFS_RETURN) = PR_SetString(s);
 }
 
 void PF_etos (void)
@@ -1148,12 +1119,13 @@ void PF_etos (void)
        char *s;
        s = PR_GetTempString();
        sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
-       G_INT(OFS_RETURN) = s - pr_strings;
+       G_INT(OFS_RETURN) = PR_SetString(s);
 }
 
 void PF_Spawn (void)
 {
        edict_t *ed;
+       pr_xfunction->builtinsprofile += 20;
        ed = ED_Alloc();
        RETURN_EDICT(ed);
 }
@@ -1161,12 +1133,16 @@ void PF_Spawn (void)
 void PF_Remove (void)
 {
        edict_t *ed;
+       pr_xfunction->builtinsprofile += 20;
 
        ed = G_EDICT(OFS_PARM0);
        if (ed == sv.edicts)
-               PR_RunError("remove: tried to remove world\n");
+               PF_WARNING("remove: tried to remove world\n");
        if (NUM_FOR_EDICT(ed) <= svs.maxclients)
-               PR_RunError("remove: tried to remove a client\n");
+               PF_WARNING("remove: tried to remove a client\n");
+       // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
+       if (ed->e->free && developer.integer)
+               PF_WARNING("remove: tried to remove an entity that was already removed\n");
        ED_Free (ed);
 }
 
@@ -1190,8 +1166,9 @@ void PF_Find (void)
 
        for (e++ ; e < sv.num_edicts ; e++)
        {
+               pr_xfunction->builtinsprofile++;
                ed = EDICT_NUM(e);
-               if (ed->free)
+               if (ed->e->free)
                        continue;
                t = E_STRING(ed,f);
                if (!t)
@@ -1209,7 +1186,7 @@ void PF_Find (void)
 // LordHavoc: added this for searching float, int, and entity reference fields
 void PF_FindFloat (void)
 {
-       int             e;      
+       int             e;
        int             f;
        float   s;
        edict_t *ed;
@@ -1217,11 +1194,12 @@ void PF_FindFloat (void)
        e = G_EDICTNUM(OFS_PARM0);
        f = G_INT(OFS_PARM1);
        s = G_FLOAT(OFS_PARM2);
-               
+
        for (e++ ; e < sv.num_edicts ; e++)
        {
+               pr_xfunction->builtinsprofile++;
                ed = EDICT_NUM(e);
-               if (ed->free)
+               if (ed->e->free)
                        continue;
                if (E_FLOAT(ed,f) == s)
                {
@@ -1237,7 +1215,7 @@ void PF_FindFloat (void)
 // entity(.string field, string match) findchain = #402;
 void PF_findchain (void)
 {
-       int             i;      
+       int             i;
        int             f;
        char    *s, *t;
        edict_t *ent, *chain;
@@ -1251,11 +1229,12 @@ void PF_findchain (void)
                RETURN_EDICT(sv.edicts);
                return;
        }
-               
+
        ent = NEXT_EDICT(sv.edicts);
        for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
        {
-               if (ent->free)
+               pr_xfunction->builtinsprofile++;
+               if (ent->e->free)
                        continue;
                t = E_STRING(ent,f);
                if (!t)
@@ -1263,7 +1242,7 @@ void PF_findchain (void)
                if (strcmp(t,s))
                        continue;
 
-               ent->v.chain = EDICT_TO_PROG(chain);
+               ent->v->chain = EDICT_TO_PROG(chain);
                chain = ent;
        }
 
@@ -1274,7 +1253,7 @@ void PF_findchain (void)
 // entity(.string field, float match) findchainfloat = #403;
 void PF_findchainfloat (void)
 {
-       int             i;      
+       int             i;
        int             f;
        float   s;
        edict_t *ent, *chain;
@@ -1283,16 +1262,74 @@ void PF_findchainfloat (void)
 
        f = G_INT(OFS_PARM0);
        s = G_FLOAT(OFS_PARM1);
-               
+
        ent = NEXT_EDICT(sv.edicts);
        for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
        {
-               if (ent->free)
+               pr_xfunction->builtinsprofile++;
+               if (ent->e->free)
                        continue;
                if (E_FLOAT(ent,f) != s)
                        continue;
 
-               ent->v.chain = EDICT_TO_PROG(chain);
+               ent->v->chain = EDICT_TO_PROG(chain);
+               chain = ent;
+       }
+
+       RETURN_EDICT(chain);
+}
+
+// LordHavoc: search for flags in float fields
+void PF_findflags (void)
+{
+       int             e;
+       int             f;
+       int             s;
+       edict_t *ed;
+
+       e = G_EDICTNUM(OFS_PARM0);
+       f = G_INT(OFS_PARM1);
+       s = (int)G_FLOAT(OFS_PARM2);
+
+       for (e++ ; e < sv.num_edicts ; e++)
+       {
+               pr_xfunction->builtinsprofile++;
+               ed = EDICT_NUM(e);
+               if (ed->e->free)
+                       continue;
+               if ((int)E_FLOAT(ed,f) & s)
+               {
+                       RETURN_EDICT(ed);
+                       return;
+               }
+       }
+
+       RETURN_EDICT(sv.edicts);
+}
+
+// LordHavoc: chained search for flags in float fields
+void PF_findchainflags (void)
+{
+       int             i;
+       int             f;
+       int             s;
+       edict_t *ent, *chain;
+
+       chain = (edict_t *)sv.edicts;
+
+       f = G_INT(OFS_PARM0);
+       s = (int)G_FLOAT(OFS_PARM1);
+
+       ent = NEXT_EDICT(sv.edicts);
+       for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
+       {
+               pr_xfunction->builtinsprofile++;
+               if (ent->e->free)
+                       continue;
+               if (!((int)E_FLOAT(ent,f) & s))
+                       continue;
+
+               ent->v->chain = EDICT_TO_PROG(chain);
                chain = ent;
        }
 
@@ -1302,7 +1339,7 @@ void PF_findchainfloat (void)
 void PR_CheckEmptyString (char *s)
 {
        if (s[0] <= ' ')
-               PR_RunError ("Bad string");
+               PF_ERROR("Bad string");
 }
 
 void PF_precache_file (void)
@@ -1314,15 +1351,16 @@ void PF_precache_sound (void)
 {
        char    *s;
        int             i;
-       
+       int             limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_SOUNDS);
+
        if (sv.state != ss_loading)
-               PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
+               PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
 
        s = G_STRING(OFS_PARM0);
        G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
        PR_CheckEmptyString (s);
-       
-       for (i=0 ; i<MAX_SOUNDS ; i++)
+
+       for (i=0 ; i<limit ; i++)
        {
                if (!sv.sound_precache[i])
                {
@@ -1332,24 +1370,25 @@ void PF_precache_sound (void)
                if (!strcmp(sv.sound_precache[i], s))
                        return;
        }
-       PR_RunError ("PF_precache_sound: overflow");
+       PF_ERROR("PF_precache_sound: overflow");
 }
 
 void PF_precache_model (void)
 {
        char    *s;
        int             i;
-       
+       int             limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_MODELS);
+
        if (sv.state != ss_loading)
-               PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
+               PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
 
        s = G_STRING(OFS_PARM0);
-       if (sv.worldmodel->ishlbsp && ((!s) || (!s[0])))
+       if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
                return;
        G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
        PR_CheckEmptyString (s);
 
-       for (i=0 ; i<MAX_MODELS ; i++)
+       for (i = 0;i < limit;i++)
        {
                if (!sv.model_precache[i])
                {
@@ -1360,7 +1399,7 @@ void PF_precache_model (void)
                if (!strcmp(sv.model_precache[i], s))
                        return;
        }
-       PR_RunError ("PF_precache_model: overflow");
+       PF_ERROR("PF_precache_model: overflow");
 }
 
 
@@ -1396,21 +1435,25 @@ void PF_walkmove (void)
        edict_t *ent;
        float   yaw, dist;
        vec3_t  move;
-       dfunction_t     *oldf;
+       mfunction_t     *oldf;
        int     oldself;
+
+       // assume failure if it returns early
+       G_FLOAT(OFS_RETURN) = 0;
        
        ent = PROG_TO_EDICT(pr_global_struct->self);
+       if (ent == sv.edicts)
+               PF_WARNING("walkmove: can not modify world entity\n");
+       if (ent->e->free)
+               PF_WARNING("walkmove: can not modify free entity\n");
        yaw = G_FLOAT(OFS_PARM0);
        dist = G_FLOAT(OFS_PARM1);
-       
-       if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
-       {
-               G_FLOAT(OFS_RETURN) = 0;
+
+       if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
                return;
-       }
 
        yaw = yaw*M_PI*2 / 360;
-       
+
        move[0] = cos(yaw)*dist;
        move[1] = sin(yaw)*dist;
        move[2] = 0;
@@ -1418,10 +1461,10 @@ void PF_walkmove (void)
 // save program state, because SV_movestep may call other progs
        oldf = pr_xfunction;
        oldself = pr_global_struct->self;
-       
+
        G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
-       
-       
+
+
 // restore program state
        pr_xfunction = oldf;
        pr_global_struct->self = oldself;
@@ -1439,23 +1482,30 @@ void PF_droptofloor (void)
        edict_t         *ent;
        vec3_t          end;
        trace_t         trace;
-       
+
+       // assume failure if it returns early
+       G_FLOAT(OFS_RETURN) = 0;
+
        ent = PROG_TO_EDICT(pr_global_struct->self);
+       if (ent == sv.edicts)
+               PF_WARNING("droptofloor: can not modify world entity\n");
+       if (ent->e->free)
+               PF_WARNING("droptofloor: can not modify free entity\n");
 
-       VectorCopy (ent->v.origin, end);
+       VectorCopy (ent->v->origin, end);
        end[2] -= 256;
-       
-       trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);
 
-       if (trace.fraction == 1 || trace.allsolid)
-               G_FLOAT(OFS_RETURN) = 0;
-       else
+       trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
+
+       if (trace.fraction != 1)
        {
-               VectorCopy (trace.endpos, ent->v.origin);
+               VectorCopy (trace.endpos, ent->v->origin);
                SV_LinkEdict (ent, false);
-               ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
-               ent->v.groundentity = EDICT_TO_PROG(trace.ent);
+               ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
+               ent->v->groundentity = EDICT_TO_PROG(trace.ent);
                G_FLOAT(OFS_RETURN) = 1;
+               // if support is destroyed, keep suspended (gross hack for floating items in various maps)
+               ent->e->suspendedinairflag = true;
        }
 }
 
@@ -1472,24 +1522,26 @@ void PF_lightstyle (void)
        char    *val;
        client_t        *client;
        int                     j;
-       
+
        style = G_FLOAT(OFS_PARM0);
        val = G_STRING(OFS_PARM1);
 
 // change the string in sv
        sv.lightstyles[style] = val;
-       
+
 // send message to all clients on this server
        if (sv.state != ss_active)
                return;
-       
-       for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
-               if (client->active || client->spawned)
+
+       for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
+       {
+               if (client->netconnection)
                {
                        MSG_WriteChar (&client->message, svc_lightstyle);
                        MSG_WriteChar (&client->message,style);
                        MSG_WriteString (&client->message, val);
                }
+       }
 }
 
 void PF_rint (void)
@@ -1528,7 +1580,7 @@ PF_pointcontents
 */
 void PF_pointcontents (void)
 {
-       G_FLOAT(OFS_RETURN) = SV_PointContents (G_VECTOR(OFS_PARM0));
+       G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
 }
 
 /*
@@ -1542,10 +1594,11 @@ void PF_nextent (void)
 {
        int             i;
        edict_t *ent;
-       
+
        i = G_EDICTNUM(OFS_PARM0);
        while (1)
        {
+               pr_xfunction->builtinsprofile++;
                i++;
                if (i == sv.num_edicts)
                {
@@ -1553,7 +1606,7 @@ void PF_nextent (void)
                        return;
                }
                ent = EDICT_NUM(i);
-               if (!ent->free)
+               if (!ent->e->free)
                {
                        RETURN_EDICT(ent);
                        return;
@@ -1577,19 +1630,26 @@ void PF_aim (void)
        trace_t tr;
        float   dist, bestdist;
        float   speed;
-       
+
+       // assume failure if it returns early
+       VectorClear(G_VECTOR(OFS_RETURN));
+
        ent = G_EDICT(OFS_PARM0);
+       if (ent == sv.edicts)
+               PF_WARNING("aim: can not use world entity\n");
+       if (ent->e->free)
+               PF_WARNING("aim: can not use free entity\n");
        speed = G_FLOAT(OFS_PARM1);
 
-       VectorCopy (ent->v.origin, start);
+       VectorCopy (ent->v->origin, start);
        start[2] += 20;
 
 // try sending a trace straight
        VectorCopy (pr_global_struct->v_forward, dir);
        VectorMA (start, 2048, dir, end);
        tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
-       if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM
-       && (!teamplay.integer || ent->v.team <=0 || ent->v.team != tr.ent->v.team) )
+       if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
+       && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
        {
                VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
                return;
@@ -1600,19 +1660,20 @@ void PF_aim (void)
        VectorCopy (dir, bestdir);
        bestdist = sv_aim.value;
        bestent = NULL;
-       
+
        check = NEXT_EDICT(sv.edicts);
        for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
        {
-               if (check->v.takedamage != DAMAGE_AIM)
+               pr_xfunction->builtinsprofile++;
+               if (check->v->takedamage != DAMAGE_AIM)
                        continue;
                if (check == ent)
                        continue;
-               if (teamplay.integer && ent->v.team > 0 && ent->v.team == check->v.team)
+               if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
                        continue;       // don't aim at teammate
                for (j=0 ; j<3 ; j++)
-                       end[j] = check->v.origin[j]
-                       + 0.5*(check->v.mins[j] + check->v.maxs[j]);
+                       end[j] = check->v->origin[j]
+                       + 0.5*(check->v->mins[j] + check->v->maxs[j]);
                VectorSubtract (end, start, dir);
                VectorNormalize (dir);
                dist = DotProduct (dir, pr_global_struct->v_forward);
@@ -1625,15 +1686,15 @@ void PF_aim (void)
                        bestent = check;
                }
        }
-       
+
        if (bestent)
        {
-               VectorSubtract (bestent->v.origin, ent->v.origin, dir);
+               VectorSubtract (bestent->v->origin, ent->v->origin, dir);
                dist = DotProduct (dir, pr_global_struct->v_forward);
                VectorScale (pr_global_struct->v_forward, dist, end);
                end[2] = dir[2];
                VectorNormalize (end);
-               VectorCopy (end, G_VECTOR(OFS_RETURN)); 
+               VectorCopy (end, G_VECTOR(OFS_RETURN));
        }
        else
        {
@@ -1652,12 +1713,16 @@ void PF_changeyaw (void)
 {
        edict_t         *ent;
        float           ideal, current, move, speed;
-       
+
        ent = PROG_TO_EDICT(pr_global_struct->self);
-       current = ANGLEMOD(ent->v.angles[1]);
-       ideal = ent->v.ideal_yaw;
-       speed = ent->v.yaw_speed;
-       
+       if (ent == sv.edicts)
+               PF_WARNING("changeyaw: can not modify world entity\n");
+       if (ent->e->free)
+               PF_WARNING("changeyaw: can not modify free entity\n");
+       current = ANGLEMOD(ent->v->angles[1]);
+       ideal = ent->v->ideal_yaw;
+       speed = ent->v->yaw_speed;
+
        if (current == ideal)
                return;
        move = ideal - current;
@@ -1681,8 +1746,8 @@ void PF_changeyaw (void)
                if (move < -speed)
                        move = -speed;
        }
-       
-       ent->v.angles[1] = ANGLEMOD (current + move);
+
+       ent->v->angles[1] = ANGLEMOD (current + move);
 }
 
 /*
@@ -1695,24 +1760,28 @@ void PF_changepitch (void)
        edict_t         *ent;
        float           ideal, current, move, speed;
        eval_t          *val;
-       
+
        ent = G_EDICT(OFS_PARM0);
-       current = ANGLEMOD( ent->v.angles[0] );
+       if (ent == sv.edicts)
+               PF_WARNING("changepitch: can not modify world entity\n");
+       if (ent->e->free)
+               PF_WARNING("changepitch: can not modify free entity\n");
+       current = ANGLEMOD( ent->v->angles[0] );
        if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
                ideal = val->_float;
        else
        {
-               PR_RunError ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
+               PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
                return;
        }
        if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
                speed = val->_float;
        else
        {
-               PR_RunError ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
+               PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
                return;
        }
-       
+
        if (current == ideal)
                return;
        move = ideal - current;
@@ -1736,8 +1805,8 @@ void PF_changepitch (void)
                if (move < -speed)
                        move = -speed;
        }
-       
-       ent->v.angles[0] = ANGLEMOD (current + move);
+
+       ent->v->angles[0] = ANGLEMOD (current + move);
 }
 
 /*
@@ -1764,25 +1833,25 @@ sizebuf_t *WriteDest (void)
        {
        case MSG_BROADCAST:
                return &sv.datagram;
-       
+
        case MSG_ONE:
                ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
                entnum = NUM_FOR_EDICT(ent);
-               if (entnum < 1 || entnum > svs.maxclients)
-                       PR_RunError ("WriteDest: not a client");
+               if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
+                       Host_Error("WriteDest: tried to write to non-client\n");
                return &svs.clients[entnum-1].message;
-               
+
        case MSG_ALL:
                return &sv.reliable_datagram;
-       
+
        case MSG_INIT:
                return &sv.signon;
 
        default:
-               PR_RunError ("WriteDest: bad destination");
+               Host_Error("WriteDest: bad destination");
                break;
        }
-       
+
        return NULL;
 }
 
@@ -1808,12 +1877,15 @@ void PF_WriteLong (void)
 
 void PF_WriteAngle (void)
 {
-       MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
+       if (sv.protocol == PROTOCOL_DARKPLACES5)
+               MSG_WriteAngle16i (WriteDest(), G_FLOAT(OFS_PARM1));
+       else
+               MSG_WriteAngle8i (WriteDest(), G_FLOAT(OFS_PARM1));
 }
 
 void PF_WriteCoord (void)
 {
-       MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1));
+       MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1), sv.protocol);
 }
 
 void PF_WriteString (void)
@@ -1829,38 +1901,40 @@ void PF_WriteEntity (void)
 
 //=============================================================================
 
-int SV_ModelIndex (char *name);
-
 void PF_makestatic (void)
 {
-       edict_t *ent;
-       int             i, large;
-       
+       edict_t *ent;
+       int i, large;
+
        ent = G_EDICT(OFS_PARM0);
+       if (ent == sv.edicts)
+               PF_WARNING("makestatic: can not modify world entity\n");
+       if (ent->e->free)
+               PF_WARNING("makestatic: can not modify free entity\n");
 
        large = false;
-       if (ent->v.modelindex >= 256 || ent->v.frame >= 256)
+       if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
                large = true;
 
        if (large)
        {
                MSG_WriteByte (&sv.signon,svc_spawnstatic2);
-               MSG_WriteShort (&sv.signon, ent->v.modelindex);
-               MSG_WriteShort (&sv.signon, ent->v.frame);
+               MSG_WriteShort (&sv.signon, ent->v->modelindex);
+               MSG_WriteShort (&sv.signon, ent->v->frame);
        }
        else
        {
                MSG_WriteByte (&sv.signon,svc_spawnstatic);
-               MSG_WriteByte (&sv.signon, ent->v.modelindex);
-               MSG_WriteByte (&sv.signon, ent->v.frame);
+               MSG_WriteByte (&sv.signon, ent->v->modelindex);
+               MSG_WriteByte (&sv.signon, ent->v->frame);
        }
 
-       MSG_WriteByte (&sv.signon, ent->v.colormap);
-       MSG_WriteByte (&sv.signon, ent->v.skin);
+       MSG_WriteByte (&sv.signon, ent->v->colormap);
+       MSG_WriteByte (&sv.signon, ent->v->skin);
        for (i=0 ; i<3 ; i++)
        {
-               MSG_WriteDPCoord(&sv.signon, ent->v.origin[i]);
-               MSG_WriteAngle(&sv.signon, ent->v.angles[i]);
+               MSG_WriteCoord(&sv.signon, ent->v->origin[i], sv.protocol);
+               MSG_WriteAngle8i(&sv.signon, ent->v->angles[i]);
        }
 
 // throw the entity away now
@@ -1882,12 +1956,14 @@ void PF_setspawnparms (void)
 
        ent = G_EDICT(OFS_PARM0);
        i = NUM_FOR_EDICT(ent);
-       if (i < 1 || i > svs.maxclients)
-               PR_RunError ("Entity is not a client");
+       if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
+       {
+               Con_Print("tried to setspawnparms on a non-client\n");
+               return;
+       }
 
        // copy spawn parms out of the client_t
-       client = svs.clients + (i-1);
-
+       client = svs.clients + i-1;
        for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
                (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
 }
@@ -1905,7 +1981,7 @@ void PF_changelevel (void)
        if (svs.changelevel_issued)
                return;
        svs.changelevel_issued = true;
-       
+
        s = G_STRING(OFS_PARM0);
        Cbuf_AddText (va("changelevel %s\n",s));
 }
@@ -1944,10 +2020,9 @@ void PF_randomvec (void)
                temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
        }
        while (DotProduct(temp, temp) >= 1);
-       VectorCopy (temp, G_VECTOR(OFS_RETURN));        
+       VectorCopy (temp, G_VECTOR(OFS_RETURN));
 }
 
-void SV_LightPoint (vec3_t color, vec3_t p);
 /*
 =================
 PF_GetLight
@@ -1962,11 +2037,15 @@ getlight(vector)
 */
 void PF_GetLight (void)
 {
-       vec3_t          color;
-       vec_t*          p;
+       vec3_t ambientcolor, diffusecolor, diffusenormal;
+       vec_t *p;
        p = G_VECTOR(OFS_PARM0);
-       SV_LightPoint (color, p);
-       VectorCopy (color, G_VECTOR(OFS_RETURN));       
+       VectorClear(ambientcolor);
+       VectorClear(diffusecolor);
+       VectorClear(diffusenormal);
+       if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
+               sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
+       VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
 }
 
 #define MAX_QC_CVARS 128
@@ -1975,36 +2054,34 @@ int currentqc_cvar;
 
 void PF_registercvar (void)
 {
-       char    *name, *value;
-       cvar_t  *variable;
-       name = G_STRING(OFS_PARM1);
-       value = G_STRING(OFS_PARM2);
+       char *name, *value;
+       cvar_t *variable;
+       name = G_STRING(OFS_PARM0);
+       value = G_STRING(OFS_PARM1);
        G_FLOAT(OFS_RETURN) = 0;
 // first check to see if it has already been defined
        if (Cvar_FindVar (name))
                return;
-       
+
 // check for overlap with a command
        if (Cmd_Exists (name))
        {
-               Con_Printf ("PF_registercvar: %s is a command\n", name);
+               Con_Printf("PF_registercvar: %s is a command\n", name);
                return;
        }
 
        if (currentqc_cvar >= MAX_QC_CVARS)
-               PR_RunError ("PF_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
+               PF_ERROR("PF_registercvar: ran out of cvar slots\n");
 
 // copy the name and value
        variable = &qc_cvar[currentqc_cvar++];
-       variable->name = Z_Malloc (strlen(name)+1);     
+       variable->name = Z_Malloc (strlen(name)+1);
        strcpy (variable->name, name);
-       variable->string = Z_Malloc (strlen(value)+1);  
+       variable->string = Z_Malloc (strlen(value)+1);
        strcpy (variable->string, value);
        variable->value = atof (value);
-       
-// link the variable in
-       variable->next = cvar_vars;
-       cvar_vars = variable;
+
+       Cvar_RegisterVariable(variable);
        G_FLOAT(OFS_RETURN) = 1; // success
 }
 
@@ -2032,7 +2109,10 @@ void PF_min (void)
                G_FLOAT(OFS_RETURN) = f;
        }
        else
-               PR_RunError("min: must supply at least 2 floats\n");
+       {
+               G_FLOAT(OFS_RETURN) = 0;
+               PF_WARNING("min: must supply at least 2 floats\n");
+       }
 }
 
 /*
@@ -2059,7 +2139,10 @@ void PF_max (void)
                G_FLOAT(OFS_RETURN) = f;
        }
        else
-               PR_RunError("max: must supply at least 2 floats\n");
+       {
+               G_FLOAT(OFS_RETURN) = 0;
+               PF_WARNING("max: must supply at least 2 floats\n");
+       }
 }
 
 /*
@@ -2103,8 +2186,16 @@ void PF_copyentity (void)
 {
        edict_t *in, *out;
        in = G_EDICT(OFS_PARM0);
+       if (in == sv.edicts)
+               PF_WARNING("copyentity: can not read world entity\n");
+       if (in->e->free)
+               PF_WARNING("copyentity: can not read free entity\n");
        out = G_EDICT(OFS_PARM1);
-       memcpy(out, in, pr_edict_size);
+       if (out == sv.edicts)
+               PF_WARNING("copyentity: can not modify world entity\n");
+       if (out->e->free)
+               PF_WARNING("copyentity: can not modify free entity\n");
+       memcpy(out->v, in->v, progs->entityfields * 4);
 }
 
 /*
@@ -2118,22 +2209,26 @@ setcolor(clientent, value)
 */
 void PF_setcolor (void)
 {
-       client_t        *client;
-       int                     entnum, i;
-       
+       client_t *client;
+       int entnum, i;
+       eval_t *val;
+
        entnum = G_EDICTNUM(OFS_PARM0);
        i = G_FLOAT(OFS_PARM1);
-       
-       if (entnum < 1 || entnum > svs.maxclients)
+
+       if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
        {
-               Con_Print("tried to setcolor a non-client\n");
+               Con_Print("tried to setcolor a non-client\n");
                return;
        }
-               
-       client = &svs.clients[entnum-1];
+
+       client = svs.clients + entnum-1;
+       if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
+               val->_float = i;
        client->colors = i;
-       client->edict->v.team = (i & 15) + 1;
-               
+       client->old_colors = i;
+       client->edict->v->team = (i & 15) + 1;
+
        MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
        MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
        MSG_WriteByte (&sv.reliable_datagram, i);
@@ -2148,12 +2243,16 @@ effect(origin, modelname, startframe, framecount, framerate)
 */
 void PF_effect (void)
 {
+       int i;
        char *s;
        s = G_STRING(OFS_PARM1);
        if (!s || !s[0])
-               PR_RunError("effect: no model specified\n");
+               PF_WARNING("effect: no model specified\n");
 
-       SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
+       i = SV_ModelIndex(s);
+       if (i < 0)
+               PF_WARNING("effect: model not precached\n");
+       SV_StartEffect(G_VECTOR(OFS_PARM0), i, G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
 }
 
 void PF_te_blood (void)
@@ -2163,9 +2262,9 @@ void PF_te_blood (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_BLOOD);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
        // velocity
        MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
        MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
@@ -2181,15 +2280,15 @@ void PF_te_bloodshower (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
        // min
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
        // max
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
        // speed
-       MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
+       MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM2), sv.protocol);
        // count
        MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
 }
@@ -2199,9 +2298,9 @@ void PF_te_explosionrgb (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
        // color
        MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
        MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
@@ -2215,17 +2314,17 @@ void PF_te_particlecube (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
        // min
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
        // max
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
        // velocity
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
        // count
        MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
        // color
@@ -2233,7 +2332,7 @@ void PF_te_particlecube (void)
        // gravity true/false
        MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
        // randomvel
-       MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
+       MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM6), sv.protocol);
 }
 
 void PF_te_particlerain (void)
@@ -2243,17 +2342,17 @@ void PF_te_particlerain (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
        // min
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
        // max
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
        // velocity
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
        // count
        MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
        // color
@@ -2267,17 +2366,17 @@ void PF_te_particlesnow (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
        // min
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
        // max
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
        // velocity
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
        // count
        MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
        // color
@@ -2291,9 +2390,9 @@ void PF_te_spark (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_SPARK);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
        // velocity
        MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
        MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
@@ -2307,9 +2406,9 @@ void PF_te_gunshotquad (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
 }
 
 void PF_te_spikequad (void)
@@ -2317,9 +2416,9 @@ void PF_te_spikequad (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
 }
 
 void PF_te_superspikequad (void)
@@ -2327,9 +2426,9 @@ void PF_te_superspikequad (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
 }
 
 void PF_te_explosionquad (void)
@@ -2337,9 +2436,9 @@ void PF_te_explosionquad (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
 }
 
 void PF_te_smallflash (void)
@@ -2347,9 +2446,9 @@ void PF_te_smallflash (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
 }
 
 void PF_te_customflash (void)
@@ -2359,9 +2458,9 @@ void PF_te_customflash (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
        // radius
        MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
        // lifetime
@@ -2377,9 +2476,9 @@ void PF_te_gunshot (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
 }
 
 void PF_te_spike (void)
@@ -2387,9 +2486,9 @@ void PF_te_spike (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_SPIKE);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
 }
 
 void PF_te_superspike (void)
@@ -2397,9 +2496,9 @@ void PF_te_superspike (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
 }
 
 void PF_te_explosion (void)
@@ -2407,9 +2506,9 @@ void PF_te_explosion (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
 }
 
 void PF_te_tarexplosion (void)
@@ -2417,9 +2516,9 @@ void PF_te_tarexplosion (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
 }
 
 void PF_te_wizspike (void)
@@ -2427,9 +2526,9 @@ void PF_te_wizspike (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
 }
 
 void PF_te_knightspike (void)
@@ -2437,9 +2536,9 @@ void PF_te_knightspike (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
 }
 
 void PF_te_lavasplash (void)
@@ -2447,9 +2546,9 @@ void PF_te_lavasplash (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
 }
 
 void PF_te_teleport (void)
@@ -2457,9 +2556,9 @@ void PF_te_teleport (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_TELEPORT);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
 }
 
 void PF_te_explosion2 (void)
@@ -2467,11 +2566,12 @@ void PF_te_explosion2 (void)
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
        // origin
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
        // color
        MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
+       MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM2));
 }
 
 void PF_te_lightning1 (void)
@@ -2481,13 +2581,13 @@ void PF_te_lightning1 (void)
        // owner entity
        MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
        // start
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
        // end
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
 }
 
 void PF_te_lightning2 (void)
@@ -2497,13 +2597,13 @@ void PF_te_lightning2 (void)
        // owner entity
        MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
        // start
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
        // end
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
 }
 
 void PF_te_lightning3 (void)
@@ -2513,13 +2613,13 @@ void PF_te_lightning3 (void)
        // owner entity
        MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
        // start
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
        // end
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
 }
 
 void PF_te_beam (void)
@@ -2529,183 +2629,886 @@ void PF_te_beam (void)
        // owner entity
        MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
        // start
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
        // end
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
 }
 
 void PF_te_plasmaburn (void)
 {
        MSG_WriteByte(&sv.datagram, svc_temp_entity);
        MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
-       MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
+       MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
+}
+
+static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
+{
+       int i, j;
+       vec3_t v1, clipplanenormal, normal;
+       vec_t clipplanedist, clipdist;
+       VectorCopy(p, out);
+       if (surf->flags & SURF_PLANEBACK)
+               VectorNegate(surf->plane->normal, normal);
+       else
+               VectorCopy(surf->plane->normal, normal);
+       for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
+       {
+               VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
+               VectorNormalizeFast(v1);
+               CrossProduct(v1, normal, clipplanenormal);
+               clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
+               clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
+               if (clipdist > 0)
+               {
+                       clipdist = -clipdist;
+                       VectorMA(out, clipdist, clipplanenormal, out);
+               }
+       }
+}
+
+static msurface_t *getsurface(edict_t *ed, int surfnum)
+{
+       int modelindex;
+       model_t *model;
+       if (!ed || ed->e->free)
+               return NULL;
+       modelindex = ed->v->modelindex;
+       if (modelindex < 1 || modelindex >= MAX_MODELS)
+               return NULL;
+       model = sv.models[modelindex];
+       if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
+               return NULL;
+       return model->brushq1.surfaces + surfnum + model->firstmodelsurface;
+}
+
+
+//PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
+void PF_getsurfacenumpoints(void)
+{
+       msurface_t *surf;
+       // return 0 if no such surface
+       if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
+       {
+               G_FLOAT(OFS_RETURN) = 0;
+               return;
+       }
+
+       G_FLOAT(OFS_RETURN) = surf->poly_numverts;
+}
+//PF_getsurfacepoint,     // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
+void PF_getsurfacepoint(void)
+{
+       edict_t *ed;
+       msurface_t *surf;
+       int pointnum;
+       VectorClear(G_VECTOR(OFS_RETURN));
+       ed = G_EDICT(OFS_PARM0);
+       if (!ed || ed->e->free)
+               return;
+       if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
+               return;
+       pointnum = G_FLOAT(OFS_PARM2);
+       if (pointnum < 0 || pointnum >= surf->poly_numverts)
+               return;
+       // FIXME: implement rotation/scaling
+       VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
+}
+//PF_getsurfacenormal,    // #436 vector(entity e, float s) getsurfacenormal = #436;
+void PF_getsurfacenormal(void)
+{
+       msurface_t *surf;
+       VectorClear(G_VECTOR(OFS_RETURN));
+       if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
+               return;
+       // FIXME: implement rotation/scaling
+       if (surf->flags & SURF_PLANEBACK)
+               VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
+       else
+               VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
+}
+//PF_getsurfacetexture,   // #437 string(entity e, float s) getsurfacetexture = #437;
+void PF_getsurfacetexture(void)
+{
+       msurface_t *surf;
+       G_INT(OFS_RETURN) = 0;
+       if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
+               return;
+       G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
+}
+//PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
+void PF_getsurfacenearpoint(void)
+{
+       int surfnum, best, modelindex;
+       vec3_t clipped, p;
+       vec_t dist, bestdist;
+       edict_t *ed;
+       model_t *model;
+       msurface_t *surf;
+       vec_t *point;
+       G_FLOAT(OFS_RETURN) = -1;
+       ed = G_EDICT(OFS_PARM0);
+       point = G_VECTOR(OFS_PARM1);
+
+       if (!ed || ed->e->free)
+               return;
+       modelindex = ed->v->modelindex;
+       if (modelindex < 1 || modelindex >= MAX_MODELS)
+               return;
+       model = sv.models[modelindex];
+       if (!model->brushq1.numsurfaces)
+               return;
+
+       // FIXME: implement rotation/scaling
+       VectorSubtract(point, ed->v->origin, p);
+       best = -1;
+       bestdist = 1000000000;
+       for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
+       {
+               surf = model->brushq1.surfaces + surfnum + model->firstmodelsurface;
+               dist = PlaneDiff(p, surf->plane);
+               dist = dist * dist;
+               if (dist < bestdist)
+               {
+                       clippointtosurface(surf, p, clipped);
+                       VectorSubtract(clipped, p, clipped);
+                       dist += DotProduct(clipped, clipped);
+                       if (dist < bestdist)
+                       {
+                               best = surfnum;
+                               bestdist = dist;
+                       }
+               }
+       }
+       G_FLOAT(OFS_RETURN) = best;
+}
+//PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
+void PF_getsurfaceclippedpoint(void)
+{
+       edict_t *ed;
+       msurface_t *surf;
+       vec3_t p, out;
+       VectorClear(G_VECTOR(OFS_RETURN));
+       ed = G_EDICT(OFS_PARM0);
+       if (!ed || ed->e->free)
+               return;
+       if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
+               return;
+       // FIXME: implement rotation/scaling
+       VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
+       clippointtosurface(surf, p, out);
+       // FIXME: implement rotation/scaling
+       VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
 }
 
-void PF_Fixme (void)
+#define MAX_PRFILES 256
+
+qfile_t *pr_files[MAX_PRFILES];
+
+void PR_Files_Init(void)
 {
-       PR_RunError ("unimplemented builtin"); // LordHavoc: was misspelled (bulitin)
+       memset(pr_files, 0, sizeof(pr_files));
+}
+
+void PR_Files_CloseAll(void)
+{
+       int i;
+       for (i = 0;i < MAX_PRFILES;i++)
+       {
+               if (pr_files[i])
+                       FS_Close(pr_files[i]);
+               pr_files[i] = NULL;
+       }
+}
+
+//float(string s) stof = #81; // get numerical value from a string
+void PF_stof(void)
+{
+       char string[STRINGTEMP_LENGTH];
+       PF_VarString(0, string, sizeof(string));
+       G_FLOAT(OFS_RETURN) = atof(string);
+}
+
+//float(string filename, float mode) fopen = #110; // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE), returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
+void PF_fopen(void)
+{
+       int filenum, mode, i;
+       char *modestring, *filename;
+       for (filenum = 0;filenum < MAX_PRFILES;filenum++)
+               if (pr_files[filenum] == NULL)
+                       break;
+       if (filenum >= MAX_PRFILES)
+       {
+               Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
+               G_FLOAT(OFS_RETURN) = -2;
+               return;
+       }
+       mode = G_FLOAT(OFS_PARM1);
+       switch(mode)
+       {
+       case 0: // FILE_READ
+               modestring = "rb";
+               break;
+       case 1: // FILE_APPEND
+               modestring = "ab";
+               break;
+       case 2: // FILE_WRITE
+               modestring = "wb";
+               break;
+       default:
+               Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
+               G_FLOAT(OFS_RETURN) = -3;
+               return;
+       }
+       filename = G_STRING(OFS_PARM0);
+       // control characters do not cause issues with any platforms I know of, but they are usually annoying to deal with
+       // ../ is parent directory on many platforms
+       // // is parent directory on Amiga
+       // / at the beginning of a path is root on unix, and parent directory on Amiga
+       // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
+       // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
+       for (i = 0;filename[i];i++)
+       {
+               if (filename[i] < ' ' || (filename[i] == '/' && filename[i+1] == '/') || (filename[i] == '.' && filename[i+1] == '.') || filename[i] == ':' || filename[i] == '\\' || filename[0] == '/')
+               {
+                       Con_Printf("PF_fopen: dangerous/confusing/annoying/non-portable filename \"%s\" not allowed. (contains control characters or // or .. or : or \\ or begins with /)\n", filename);
+                       G_FLOAT(OFS_RETURN) = -4;
+                       return;
+               }
+       }
+       pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
+
+       if (pr_files[filenum] == NULL && modestring == "rb")
+               pr_files[filenum] = FS_Open(filename, modestring, false);
+
+       if (pr_files[filenum] == NULL)
+               G_FLOAT(OFS_RETURN) = -1;
+       else
+               G_FLOAT(OFS_RETURN) = filenum;
+}
+
+//void(float fhandle) fclose = #111; // closes a file
+void PF_fclose(void)
+{
+       int filenum = G_FLOAT(OFS_PARM0);
+       if (filenum < 0 || filenum >= MAX_PRFILES)
+       {
+               Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
+               return;
+       }
+       if (pr_files[filenum] == NULL)
+       {
+               Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
+               return;
+       }
+       FS_Close(pr_files[filenum]);
+       pr_files[filenum] = NULL;
+}
+
+//string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
+void PF_fgets(void)
+{
+       int c, end;
+       static char string[STRINGTEMP_LENGTH];
+       int filenum = G_FLOAT(OFS_PARM0);
+       if (filenum < 0 || filenum >= MAX_PRFILES)
+       {
+               Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
+               return;
+       }
+       if (pr_files[filenum] == NULL)
+       {
+               Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
+               return;
+       }
+       end = 0;
+       for (;;)
+       {
+               c = FS_Getc(pr_files[filenum]);
+               if (c == '\r' || c == '\n' || c < 0)
+                       break;
+               if (end < STRINGTEMP_LENGTH - 1)
+                       string[end++] = c;
+       }
+       string[end] = 0;
+       // remove \n following \r
+       if (c == '\r')
+               c = FS_Getc(pr_files[filenum]);
+       if (developer.integer)
+               Con_Printf("fgets: %s\n", string);
+       if (c >= 0 || end)
+               G_INT(OFS_RETURN) = PR_SetString(string);
+       else
+               G_INT(OFS_RETURN) = 0;
+}
+
+//void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
+void PF_fputs(void)
+{
+       int stringlength;
+       char string[STRINGTEMP_LENGTH];
+       int filenum = G_FLOAT(OFS_PARM0);
+       if (filenum < 0 || filenum >= MAX_PRFILES)
+       {
+               Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
+               return;
+       }
+       if (pr_files[filenum] == NULL)
+       {
+               Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
+               return;
+       }
+       PF_VarString(1, string, sizeof(string));
+       if ((stringlength = strlen(string)))
+               FS_Write(pr_files[filenum], string, stringlength);
+       if (developer.integer)
+               Con_Printf("fputs: %s\n", string);
+}
+
+//float(string s) strlen = #114; // returns how many characters are in a string
+void PF_strlen(void)
+{
+       char *s;
+       s = G_STRING(OFS_PARM0);
+       if (s)
+               G_FLOAT(OFS_RETURN) = strlen(s);
+       else
+               G_FLOAT(OFS_RETURN) = 0;
+}
+
+//string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
+void PF_strcat(void)
+{
+       char *s = PR_GetTempString();
+       PF_VarString(0, s, STRINGTEMP_LENGTH);
+       G_INT(OFS_RETURN) = PR_SetString(s);
+}
+
+//string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
+void PF_substring(void)
+{
+       int i, start, length;
+       char *s, *string = PR_GetTempString();
+       s = G_STRING(OFS_PARM0);
+       start = G_FLOAT(OFS_PARM1);
+       length = G_FLOAT(OFS_PARM2);
+       if (!s)
+               s = "";
+       for (i = 0;i < start && *s;i++, s++);
+       for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
+               string[i] = *s;
+       string[i] = 0;
+       G_INT(OFS_RETURN) = PR_SetString(string);
+}
+
+//vector(string s) stov = #117; // returns vector value from a string
+void PF_stov(void)
+{
+       char string[STRINGTEMP_LENGTH];
+       PF_VarString(0, string, sizeof(string));
+       Math_atov(string, G_VECTOR(OFS_RETURN));
+}
+
+//string(string s) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often)
+void PF_strzone(void)
+{
+       char *in, *out;
+       in = G_STRING(OFS_PARM0);
+       out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
+       strcpy(out, in);
+       G_INT(OFS_RETURN) = PR_SetString(out);
+}
+
+//void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!)
+void PF_strunzone(void)
+{
+       Mem_Free(G_STRING(OFS_PARM0));
+}
+
+//void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
+//this function originally written by KrimZon, made shorter by LordHavoc
+void PF_clientcommand (void)
+{
+       client_t *temp_client;
+       int i;
+
+       //find client for this entity
+       i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
+       if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
+       {
+               Con_Print("PF_clientcommand: entity is not a client\n");
+               return;
+       }
+
+       temp_client = host_client;
+       host_client = svs.clients + i;
+       Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
+       host_client = temp_client;
+}
+
+//float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
+//this function originally written by KrimZon, made shorter by LordHavoc
+//20040203: rewritten by LordHavoc (no longer uses allocations)
+int num_tokens = 0;
+char *tokens[256], tokenbuf[4096];
+void PF_tokenize (void)
+{
+       int pos;
+       const char *p;
+       p = G_STRING(OFS_PARM0);
+
+       num_tokens = 0;
+       pos = 0;
+       while(COM_ParseToken(&p, false))
+       {
+               if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
+                       break;
+               if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
+                       break;
+               tokens[num_tokens++] = tokenbuf + pos;
+               strcpy(tokenbuf + pos, com_token);
+               pos += strlen(com_token) + 1;
+       }
+
+       G_FLOAT(OFS_RETURN) = num_tokens;
+}
+
+//string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
+//this function originally written by KrimZon, made shorter by LordHavoc
+void PF_argv (void)
+{
+       int token_num = G_FLOAT(OFS_PARM0);
+       if (token_num >= 0 && token_num < num_tokens)
+               G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
+       else
+               G_INT(OFS_RETURN) = PR_SetString("");
+}
+
+//void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag)
+void PF_setattachment (void)
+{
+       edict_t *e = G_EDICT(OFS_PARM0);
+       edict_t *tagentity = G_EDICT(OFS_PARM1);
+       char *tagname = G_STRING(OFS_PARM2);
+       eval_t *v;
+       int i, modelindex;
+       model_t *model;
+
+       if (e == sv.edicts)
+               PF_WARNING("setattachment: can not modify world entity\n");
+       if (e->e->free)
+               PF_WARNING("setattachment: can not modify free entity\n");
+
+       if (tagentity == NULL)
+               tagentity = sv.edicts;
+
+       v = GETEDICTFIELDVALUE(e, eval_tag_entity);
+       if (v)
+               v->edict = EDICT_TO_PROG(tagentity);
+
+       v = GETEDICTFIELDVALUE(e, eval_tag_index);
+       if (v)
+               v->_float = 0;
+       if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
+       {
+               modelindex = (int)tagentity->v->modelindex;
+               if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
+               {
+                       if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
+                               for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
+                                       if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
+                                               v->_float = i + 1;
+                       // FIXME: use a model function to get tag info (need to handle skeletal)
+                       if (v->_float == 0 && model->alias.aliasnum_tags)
+                               for (i = 0;i < model->alias.aliasnum_tags;i++)
+                                       if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
+                                               v->_float = i + 1;
+                       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", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity), model->name);
+               }
+               else
+                       Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity));
+       }
+}
+
+
+/////////////////////////////////////////
+// DP_QC_FS_SEARCH extension
+
+// qc fs search handling
+#define MAX_SEARCHES 128
+
+fssearch_t *pr_fssearchlist[MAX_SEARCHES];
+
+void PR_Search_Init(void)
+{
+       memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
+}
+
+void PR_Search_Reset(void)
+{
+       int i;
+       // reset the fssearch list
+       for(i = 0; i < MAX_SEARCHES; i++)
+               if(pr_fssearchlist[i])
+                       FS_FreeSearch(pr_fssearchlist[i]);
+       memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
+}
+
+/*
+=========
+PF_search_begin
+
+float search_begin(string pattern, float caseinsensitive, float quiet)
+=========
+*/
+void PF_search_begin(void)
+{
+       int handle;
+       char *pattern;
+       int caseinsens, quiet;
+
+       pattern = G_STRING(OFS_PARM0);
+
+       PR_CheckEmptyString(pattern);
+
+       caseinsens = G_FLOAT(OFS_PARM1);
+       quiet = G_FLOAT(OFS_PARM2);
+       
+       for(handle = 0; handle < MAX_SEARCHES; handle++)
+               if(!pr_fssearchlist[handle])
+                       break;
+
+       if(handle >= MAX_SEARCHES)
+       {
+               Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
+               G_FLOAT(OFS_RETURN) = -2;
+               return;
+       }
+
+       if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
+               G_FLOAT(OFS_RETURN) = -1;
+       else
+               G_FLOAT(OFS_RETURN) = handle;
+}
+
+/*
+=========
+VM_search_end
+
+void   search_end(float handle)
+=========
+*/
+void PF_search_end(void)
+{
+       int handle;
+
+       handle = G_FLOAT(OFS_PARM0);
+       
+       if(handle < 0 || handle >= MAX_SEARCHES)
+       {
+               Con_Printf("PF_search_end: invalid handle %i\n", handle);
+               return;
+       }
+       if(pr_fssearchlist[handle] == NULL)
+       {
+               Con_Printf("PF_search_end: no such handle %i\n", handle);
+               return;
+       }
+
+       FS_FreeSearch(pr_fssearchlist[handle]);
+       pr_fssearchlist[handle] = NULL;
+}
+
+/*
+=========
+VM_search_getsize
+
+float  search_getsize(float handle)
+=========
+*/
+void PF_search_getsize(void)
+{
+       int handle;
+
+       handle = G_FLOAT(OFS_PARM0);
+
+       if(handle < 0 || handle >= MAX_SEARCHES)
+       {
+               Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
+               return;
+       }
+       if(pr_fssearchlist[handle] == NULL)
+       {
+               Con_Printf("PF_search_getsize: no such handle %i\n", handle);
+               return;
+       }
+       
+       G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
+}
+
+/*
+=========
+VM_search_getfilename
+
+string search_getfilename(float handle, float num)
+=========
+*/
+void PF_search_getfilename(void)
+{
+       int handle, filenum;
+       char *tmp;
+
+       handle = G_FLOAT(OFS_PARM0);
+       filenum = G_FLOAT(OFS_PARM1);
+
+       if(handle < 0 || handle >= MAX_SEARCHES)
+       {
+               Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
+               return;
+       }
+       if(pr_fssearchlist[handle] == NULL)
+       {
+               Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
+               return;
+       }
+       if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
+       {
+               Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
+               return;
+       }
+       
+       tmp = PR_GetTempString();
+       strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
+
+       G_INT(OFS_RETURN) = PR_SetString(tmp);
+}
+
+void PF_cvar_string (void)
+{
+       char *str;
+       cvar_t *var;
+       char *tmp;
+
+       str = G_STRING(OFS_PARM0);
+       var = Cvar_FindVar (str);
+
+       tmp = PR_GetTempString();
+       strcpy(tmp, var->string);
+
+       G_INT(OFS_RETURN) = PR_SetString(tmp);
 }
 
 
 
 builtin_t pr_builtin[] =
 {
-PF_Fixme,
-PF_makevectors,        // void(entity e)       makevectors             = #1;
-PF_setorigin,  // void(entity e, vector o) setorigin   = #2;
-PF_setmodel,   // void(entity e, string m) setmodel    = #3;
-PF_setsize,    // void(entity e, vector min, vector max) setsize = #4;
-PF_Fixme,      // void(entity e, vector min, vector max) setabssize = #5;
-PF_break,      // void() break                                         = #6;
-PF_random,     // float() random                                               = #7;
-PF_sound,      // void(entity e, float chan, string samp) sound = #8;
-PF_normalize,  // vector(vector v) normalize                   = #9;
-PF_error,      // void(string e) error                         = #10;
-PF_objerror,   // void(string e) objerror                              = #11;
-PF_vlen,       // float(vector v) vlen                         = #12;
-PF_vectoyaw,   // float(vector v) vectoyaw             = #13;
-PF_Spawn,      // entity() spawn                                               = #14;
-PF_Remove,     // void(entity e) remove                                = #15;
-PF_traceline,  // float(vector v1, vector v2, float tryents) traceline = #16;
-PF_checkclient,        // entity() clientlist                                  = #17;
-PF_Find,       // entity(entity start, .string fld, string match) find = #18;
-PF_precache_sound,     // void(string s) precache_sound                = #19;
-PF_precache_model,     // void(string s) precache_model                = #20;
-PF_stuffcmd,   // void(entity client, string s)stuffcmd = #21;
-PF_findradius, // entity(vector org, float rad) findradius = #22;
-PF_bprint,     // void(string s) bprint                                = #23;
-PF_sprint,     // void(entity client, string s) sprint = #24;
-PF_dprint,     // void(string s) dprint                                = #25;
-PF_ftos,       // void(string s) ftos                          = #26;
-PF_vtos,       // void(string s) vtos                          = #27;
-PF_coredump,
-PF_traceon,
-PF_traceoff,
-PF_eprint,     // void(entity e) debug print an entire entity
-PF_walkmove, // float(float yaw, float dist) walkmove
-PF_Fixme, // float(float yaw, float dist) walkmove
-PF_droptofloor,
-PF_lightstyle,
-PF_rint,
-PF_floor,
-PF_ceil,
-PF_Fixme,
-PF_checkbottom,
-PF_pointcontents,
-PF_Fixme,
-PF_fabs,
-PF_aim,
-PF_cvar,
-PF_localcmd,
-PF_nextent,
-PF_particle,
-PF_changeyaw,
-PF_Fixme,
-PF_vectoangles,
-
-PF_WriteByte,
-PF_WriteChar,
-PF_WriteShort,
-PF_WriteLong,
-PF_WriteCoord,
-PF_WriteAngle,
-PF_WriteString,
-PF_WriteEntity,
-
-PF_sin,
-PF_cos,
-PF_sqrt,
-PF_changepitch,
-PF_TraceToss,
-PF_etos,
-PF_Fixme,
-
-SV_MoveToGoal,
-PF_precache_file,
-PF_makestatic,
-
-PF_changelevel,
-PF_Fixme,
-
-PF_cvar_set,
-PF_centerprint,
-
-PF_ambientsound,
-
-PF_precache_model,
-PF_precache_sound,             // precache_sound2 is different only for qcc
-PF_precache_file,
-
-PF_setspawnparms,
-
-PF_Fixme,                              // #79 LordHavoc: dunno who owns 79-89, so these are just padding
-PF_Fixme,                              // #80
-PF_Fixme,                              // #81
-PF_Fixme,                              // #82
-PF_Fixme,                              // #83
-PF_Fixme,                              // #84
-PF_Fixme,                              // #85
-PF_Fixme,                              // #86
-PF_Fixme,                              // #87
-PF_Fixme,                              // #88
-PF_Fixme,                              // #89
-
-PF_tracebox,                   // #90 LordHavoc builtin range (9x)
-PF_randomvec,                  // #91
-PF_GetLight,                   // #92
-PF_registercvar,               // #93
-PF_min,                                        // #94
-PF_max,                                        // #95
-PF_bound,                              // #96
-PF_pow,                                        // #97
-PF_FindFloat,                  // #98
-PF_checkextension,             // #99
-#define a PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme,
-#define aa a a a a a a a a a a
-aa // #200
-aa // #300
-aa // #400
-PF_copyentity,                 // #400 LordHavoc: builtin range (4xx)
-PF_setcolor,                   // #401
-PF_findchain,                  // #402
-PF_findchainfloat,             // #403
-PF_effect,                             // #404
-PF_te_blood,                   // #405
-PF_te_bloodshower,             // #406
-PF_te_explosionrgb,            // #407
-PF_te_particlecube,            // #408
-PF_te_particlerain,            // #409
-PF_te_particlesnow,            // #410
-PF_te_spark,                   // #411
-PF_te_gunshotquad,             // #412
-PF_te_spikequad,               // #413
-PF_te_superspikequad,  // #414
-PF_te_explosionquad,   // #415
-PF_te_smallflash,              // #416
-PF_te_customflash,             // #417
-PF_te_gunshot,                 // #418
-PF_te_spike,                   // #419
-PF_te_superspike,              // #420
-PF_te_explosion,               // #421
-PF_te_tarexplosion,            // #422
-PF_te_wizspike,                        // #423
-PF_te_knightspike,             // #424
-PF_te_lavasplash,              // #425
-PF_te_teleport,                        // #426
-PF_te_explosion2,              // #427
-PF_te_lightning1,              // #428
-PF_te_lightning2,              // #429
-PF_te_lightning3,              // #430
-PF_te_beam,                            // #431
-PF_vectorvectors,              // #432
-PF_te_plasmaburn,              // #433
+NULL,                                          // #0
+PF_makevectors,                                // #1 void(entity e) makevectors
+PF_setorigin,                          // #2 void(entity e, vector o) setorigin
+PF_setmodel,                           // #3 void(entity e, string m) setmodel
+PF_setsize,                                    // #4 void(entity e, vector min, vector max) setsize
+NULL,                                          // #5 void(entity e, vector min, vector max) setabssize
+PF_break,                                      // #6 void() break
+PF_random,                                     // #7 float() random
+PF_sound,                                      // #8 void(entity e, float chan, string samp) sound
+PF_normalize,                          // #9 vector(vector v) normalize
+PF_error,                                      // #10 void(string e) error
+PF_objerror,                           // #11 void(string e) objerror
+PF_vlen,                                       // #12 float(vector v) vlen
+PF_vectoyaw,                           // #13 float(vector v) vectoyaw
+PF_Spawn,                                      // #14 entity() spawn
+PF_Remove,                                     // #15 void(entity e) remove
+PF_traceline,                          // #16 float(vector v1, vector v2, float tryents) traceline
+PF_checkclient,                                // #17 entity() clientlist
+PF_Find,                                       // #18 entity(entity start, .string fld, string match) find
+PF_precache_sound,                     // #19 void(string s) precache_sound
+PF_precache_model,                     // #20 void(string s) precache_model
+PF_stuffcmd,                           // #21 void(entity client, string s)stuffcmd
+PF_findradius,                         // #22 entity(vector org, float rad) findradius
+PF_bprint,                                     // #23 void(string s) bprint
+PF_sprint,                                     // #24 void(entity client, string s) sprint
+PF_dprint,                                     // #25 void(string s) dprint
+PF_ftos,                                       // #26 void(string s) ftos
+PF_vtos,                                       // #27 void(string s) vtos
+PF_coredump,                           // #28 void() coredump
+PF_traceon,                                    // #29 void() traceon
+PF_traceoff,                           // #30 void() traceoff
+PF_eprint,                                     // #31 void(entity e) eprint
+PF_walkmove,                           // #32 float(float yaw, float dist) walkmove
+NULL,                                          // #33
+PF_droptofloor,                                // #34 float() droptofloor
+PF_lightstyle,                         // #35 void(float style, string value) lightstyle
+PF_rint,                                       // #36 float(float v) rint
+PF_floor,                                      // #37 float(float v) floor
+PF_ceil,                                       // #38 float(float v) ceil
+NULL,                                          // #39
+PF_checkbottom,                                // #40 float(entity e) checkbottom
+PF_pointcontents               ,       // #41 float(vector v) pointcontents
+NULL,                                          // #42
+PF_fabs,                                       // #43 float(float f) fabs
+PF_aim,                                                // #44 vector(entity e, float speed) aim
+PF_cvar,                                       // #45 float(string s) cvar
+PF_localcmd,                           // #46 void(string s) localcmd
+PF_nextent,                                    // #47 entity(entity e) nextent
+PF_particle,                           // #48 void(vector o, vector d, float color, float count) particle
+PF_changeyaw,                          // #49 void() ChangeYaw
+NULL,                                          // #50
+PF_vectoangles,                                // #51 vector(vector v) vectoangles
+PF_WriteByte,                          // #52 void(float to, float f) WriteByte
+PF_WriteChar,                          // #53 void(float to, float f) WriteChar
+PF_WriteShort,                         // #54 void(float to, float f) WriteShort
+PF_WriteLong,                          // #55 void(float to, float f) WriteLong
+PF_WriteCoord,                         // #56 void(float to, float f) WriteCoord
+PF_WriteAngle,                         // #57 void(float to, float f) WriteAngle
+PF_WriteString,                                // #58 void(float to, string s) WriteString
+PF_WriteEntity,                                // #59 void(float to, entity e) WriteEntity
+PF_sin,                                                // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
+PF_cos,                                                // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
+PF_sqrt,                                       // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
+PF_changepitch,                                // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
+PF_TraceToss,                          // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
+PF_etos,                                       // #65 string(entity ent) etos (DP_QC_ETOS)
+NULL,                                          // #66
+SV_MoveToGoal,                         // #67 void(float step) movetogoal
+PF_precache_file,                      // #68 string(string s) precache_file
+PF_makestatic,                         // #69 void(entity e) makestatic
+PF_changelevel,                                // #70 void(string s) changelevel
+NULL,                                          // #71
+PF_cvar_set,                           // #72 void(string var, string val) cvar_set
+PF_centerprint,                                // #73 void(entity client, strings) centerprint
+PF_ambientsound,                       // #74 void(vector pos, string samp, float vol, float atten) ambientsound
+PF_precache_model,                     // #75 string(string s) precache_model2
+PF_precache_sound,                     // #76 string(string s) precache_sound2
+PF_precache_file,                      // #77 string(string s) precache_file2
+PF_setspawnparms,                      // #78 void(entity e) setspawnparms
+NULL,                                          // #79
+NULL,                                          // #80
+PF_stof,                                       // #81 float(string s) stof (FRIK_FILE)
+NULL,                                          // #82
+NULL,                                          // #83
+NULL,                                          // #84
+NULL,                                          // #85
+NULL,                                          // #86
+NULL,                                          // #87
+NULL,                                          // #88
+NULL,                                          // #89
+PF_tracebox,                           // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
+PF_randomvec,                          // #91 vector() randomvec (DP_QC_RANDOMVEC)
+PF_GetLight,                           // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
+PF_registercvar,                       // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
+PF_min,                                                // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
+PF_max,                                                // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
+PF_bound,                                      // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
+PF_pow,                                                // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
+PF_FindFloat,                          // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
+PF_checkextension,                     // #99 float(string s) checkextension (the basis of the extension system)
+NULL,                                          // #100
+NULL,                                          // #101
+NULL,                                          // #102
+NULL,                                          // #103
+NULL,                                          // #104
+NULL,                                          // #105
+NULL,                                          // #106
+NULL,                                          // #107
+NULL,                                          // #108
+NULL,                                          // #109
+PF_fopen,                                      // #110 float(string filename, float mode) fopen (FRIK_FILE)
+PF_fclose,                                     // #111 void(float fhandle) fclose (FRIK_FILE)
+PF_fgets,                                      // #112 string(float fhandle) fgets (FRIK_FILE)
+PF_fputs,                                      // #113 void(float fhandle, string s) fputs (FRIK_FILE)
+PF_strlen,                                     // #114 float(string s) strlen (FRIK_FILE)
+PF_strcat,                                     // #115 string(string s1, string s2) strcat (FRIK_FILE)
+PF_substring,                          // #116 string(string s, float start, float length) substring (FRIK_FILE)
+PF_stov,                                       // #117 vector(string) stov (FRIK_FILE)
+PF_strzone,                                    // #118 string(string s) strzone (FRIK_FILE)
+PF_strunzone,                          // #119 void(string s) strunzone (FRIK_FILE)
+#define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+a a a a a a a a                                // #120-199
+a a a a a a a a a a                    // #200-299
+a a a a a a a a a a                    // #300-399
+PF_copyentity,                         // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
+PF_setcolor,                           // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
+PF_findchain,                          // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
+PF_findchainfloat,                     // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
+PF_effect,                                     // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
+PF_te_blood,                           // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
+PF_te_bloodshower,                     // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
+PF_te_explosionrgb,                    // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
+PF_te_particlecube,                    // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
+PF_te_particlerain,                    // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
+PF_te_particlesnow,                    // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
+PF_te_spark,                           // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
+PF_te_gunshotquad,                     // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
+PF_te_spikequad,                       // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
+PF_te_superspikequad,          // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
+PF_te_explosionquad,           // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
+PF_te_smallflash,                      // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
+PF_te_customflash,                     // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
+PF_te_gunshot,                         // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
+PF_te_spike,                           // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
+PF_te_superspike,                      // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
+PF_te_explosion,                       // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
+PF_te_tarexplosion,                    // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
+PF_te_wizspike,                                // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
+PF_te_knightspike,                     // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
+PF_te_lavasplash,                      // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
+PF_te_teleport,                                // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
+PF_te_explosion2,                      // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
+PF_te_lightning1,                      // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
+PF_te_lightning2,                      // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
+PF_te_lightning3,                      // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
+PF_te_beam,                                    // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
+PF_vectorvectors,                      // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
+PF_te_plasmaburn,                      // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
+PF_getsurfacenumpoints,                // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
+PF_getsurfacepoint,                    // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
+PF_getsurfacenormal,           // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
+PF_getsurfacetexture,          // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
+PF_getsurfacenearpoint,                // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
+PF_getsurfaceclippedpoint,     // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
+PF_clientcommand,                      // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
+PF_tokenize,                           // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
+PF_argv,                                       // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
+PF_setattachment,                      // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
+PF_search_begin,                       // #444
+PF_search_end,                         // #445
+PF_search_getsize,                     // #446
+PF_search_getfilename,         // #447
+PF_cvar_string,                                // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
+PF_findflags,                          // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
+PF_findchainflags,                     // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
+NULL,                                          // #451
+NULL,                                          // #452
+NULL,                                          // #453
+NULL,                                          // #454
+NULL,                                          // #455
+NULL,                                          // #456
+NULL,                                          // #457
+NULL,                                          // #458
+NULL,                                          // #459
+a a a a                                                // #460-499 (LordHavoc)
 };
 
 builtin_t *pr_builtins = pr_builtin;
 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
+
+void PR_Cmd_Init(void)
+{
+       pr_strings_mempool = Mem_AllocPool("pr_stringszone", 0, NULL);
+       PR_Files_Init();
+       PR_Search_Init();
+}
+
+void PR_Cmd_Reset(void)
+{
+       Mem_EmptyPool(pr_strings_mempool);
+       PR_Search_Reset();
+       PR_Files_CloseAll();
+}
+