]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - pr_cmds.c
no longer adopt colors from server updates (this means demos no longer change your...
[xonotic/darkplaces.git] / pr_cmds.c
index 1c3032d2bcd5bdd7af8c17c70672d24b78e626bc..6ee5c362a8e879cd7ce825d4bd9ac5f1a4f54c25 100644 (file)
--- a/pr_cmds.c
+++ b/pr_cmds.c
@@ -45,49 +45,54 @@ char *PF_VarString (int     first)
        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_QC_CHANGEPITCH \
-DP_QC_COPYENTITY \
-DP_QC_ETOS \
-DP_QC_FINDCHAIN \
-DP_QC_FINDCHAINFLOAT \
-DP_QC_FINDFLOAT \
-DP_QC_GETLIGHT \
-DP_QC_MINMAXBOUND \
-DP_QC_RANDOMVEC \
-DP_QC_SINCOSSQRTPOW \
-DP_QC_TRACEBOX \
-DP_QC_TRACETOSS \
-DP_QUAKE2_MODEL \
-DP_REGISTERCVAR \
-DP_SOLIDCORPSE \
-DP_SPRITE32 \
-DP_SV_DRAWONLYTOCLIENT \
-DP_SV_EFFECT \
-DP_SV_EXTERIORMODELTOCLIENT \
-DP_SV_NODRAWTOCLIENT \
-DP_SV_SETCOLOR \
-DP_TE_BLOOD \
-DP_TE_BLOODSHOWER \
-DP_TE_EXPLOSIONRGB \
-DP_TE_PARTICLECUBE \
-DP_TE_PARTICLERAIN \
-DP_TE_PARTICLESNOW \
-DP_TE_SPARK \
-NEH_CMD_PLAY2 \
-TW_SV_STEPCONTROL \
-";
+char *ENGINE_EXTENSIONS =
+"DP_ENT_ALPHA "
+"DP_ENT_CUSTOMCOLORMAP "
+"DP_ENT_EXTERIORMODELTOCLIENT "
+"DP_ENT_LOWPRECISION "
+"DP_ENT_GLOW "
+"DP_ENT_SCALE "
+"DP_ENT_VIEWMODEL "
+"DP_GFX_FOG "
+"DP_HALFLIFE_MAP "
+"DP_INPUTBUTTONS "
+"DP_MONSTERWALK "
+"DP_MOVETYPEFOLLOW "
+"DP_QC_CHANGEPITCH "
+"DP_QC_COPYENTITY "
+"DP_QC_ETOS "
+"DP_QC_FINDCHAIN "
+"DP_QC_FINDCHAINFLOAT "
+"DP_QC_FINDFLOAT "
+"DP_QC_GETLIGHT "
+"DP_QC_MINMAXBOUND "
+"DP_QC_RANDOMVEC "
+"DP_QC_SINCOSSQRTPOW "
+"DP_QC_TRACEBOX "
+"DP_QC_TRACETOSS "
+"DP_QC_VECTORVECTORS "
+"DP_QUAKE2_MODEL "
+"DP_REGISTERCVAR "
+"DP_SOLIDCORPSE "
+"DP_SPRITE32 "
+"DP_SV_DRAWONLYTOCLIENT "
+"DP_SV_EFFECT "
+"DP_SV_EXTERIORMODELTOCLIENT "
+"DP_SV_NODRAWTOCLIENT "
+"DP_SV_PLAYERPHYSICS "
+"DP_SV_SETCOLOR "
+"DP_SV_SLOWMO "
+"DP_TE_BLOOD "
+"DP_TE_BLOODSHOWER "
+"DP_TE_EXPLOSIONRGB "
+"DP_TE_PARTICLECUBE "
+"DP_TE_PARTICLERAIN "
+"DP_TE_PARTICLESNOW "
+"DP_TE_SPARK "
+"NEH_CMD_PLAY2 "
+"NEH_RESTOREGAME "
+"TW_SV_STEPCONTROL "
+;
 
 qboolean checkextension(char *name)
 {
@@ -138,9 +143,9 @@ 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);
+       Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), s);
        ed = PROG_TO_EDICT(pr_global_struct->self);
        ED_Print (ed);
 
@@ -161,9 +166,9 @@ 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);
+       Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), s);
        ed = PROG_TO_EDICT(pr_global_struct->self);
        ED_Print (ed);
        ED_Free (ed);
@@ -210,10 +215,10 @@ void PF_setorigin (void)
 {
        edict_t *e;
        float   *org;
-       
+
        e = G_EDICT(OFS_PARM0);
        org = G_VECTOR(OFS_PARM1);
-       VectorCopy (org, e->v.origin);
+       VectorCopy (org, e->v->origin);
        SV_LinkEdict (e, false);
 }
 
@@ -224,12 +229,12 @@ void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
        
        for (i=0 ; i<3 ; i++)
                if (min[i] > max[i])
-                       PR_RunError ("backwards mins/maxs");
+                       Host_Error ("backwards mins/maxs");
 
 // 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);
 }
@@ -248,7 +253,7 @@ void PF_setsize (void)
 {
        edict_t *e;
        float   *min, *max;
-       
+
        e = G_EDICT(OFS_PARM0);
        min = G_VECTOR(OFS_PARM1);
        max = G_VECTOR(OFS_PARM2);
@@ -279,13 +284,13 @@ void PF_setmodel (void)
                        break;
 
        if (!*check)
-               PR_RunError ("no precache: %s\n", m);
+               Host_Error ("no precache: %s\n", m);
 
 
-       e->v.model = m - pr_strings;
-       e->v.modelindex = i;
+       e->v->model = PR_SetString(*check);
+       e->v->modelindex = i;
 
-       mod = sv.models[ (int)e->v.modelindex];
+       mod = sv.models[ (int)e->v->modelindex];
 
        if (mod)
                SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
@@ -400,7 +405,7 @@ void PF_normalize (void)
                newvalue[2] = value1[2] * new;
        }
        
-       VectorCopy (newvalue, G_VECTOR(OFS_RETURN));    
+       VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
 }
 
 /*
@@ -512,7 +517,7 @@ void PF_random (void)
        float           num;
                
        num = (rand ()&0x7fff) / ((float)0x7fff);
-       
+
        G_FLOAT(OFS_RETURN) = num;
 }
 
@@ -641,7 +646,7 @@ break()
 */
 void PF_break (void)
 {
-       PR_RunError ("break statement");
+       Host_Error ("break statement");
 }
 
 /*
@@ -804,9 +809,9 @@ int PF_newcheckclient (int check)
 
                if (ent->free)
                        continue;
-               if (ent->v.health <= 0)
+               if (ent->v->health <= 0)
                        continue;
-               if ((int)ent->v.flags & FL_NOTARGET)
+               if ((int)ent->v->flags & FL_NOTARGET)
                        continue;
 
        // anything that is a client, or has a client as an enemy
@@ -814,7 +819,7 @@ int PF_newcheckclient (int check)
        }
 
 // get the PVS for the entity
-       VectorAdd (ent->v.origin, ent->v.view_ofs, org);
+       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 );
@@ -844,36 +849,39 @@ void PF_checkclient (void)
        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->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);
+       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)) ) )
+       if (leaf)
        {
-c_notvis++;
-               RETURN_EDICT(sv.edicts);
-               return;
+               l = (leaf - sv.worldmodel->leafs) - 1;
+               if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
+               {
+                       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);
 }
 
@@ -897,9 +905,9 @@ void PF_stuffcmd (void)
        
        entnum = G_EDICTNUM(OFS_PARM0);
        if (entnum < 1 || entnum > svs.maxclients)
-               PR_RunError ("Parm 0 not a client");
+               Host_Error ("Parm 0 not a client");
        str = G_STRING(OFS_PARM1);      
-       
+
        old = host_client;
        host_client = &svs.clients[entnum-1];
        Host_ClientCommands ("%s", str);
@@ -935,7 +943,7 @@ void PF_cvar (void)
        char    *str;
        
        str = G_STRING(OFS_PARM0);
-       
+
        G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str);
 }
 
@@ -975,7 +983,7 @@ void PF_findradius (void)
        int i;
 
        chain = (edict_t *)sv.edicts;
-       
+
        org = G_VECTOR(OFS_PARM0);
        radius = G_FLOAT(OFS_PARM1);
        radius2 = radius * radius;
@@ -985,18 +993,18 @@ void PF_findradius (void)
        {
                if (ent->free)
                        continue;
-               if (ent->v.solid == SOLID_NOT)
+               if (ent->v->solid == SOLID_NOT)
                        continue;
 
                // 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]);
+               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;
        }
 
@@ -1037,7 +1045,7 @@ void PF_ftos (void)
        s = PR_GetTempString();
        // LordHavoc: ftos improvement
        sprintf (s, "%g", v);
-       G_INT(OFS_RETURN) = s - pr_strings;
+       G_INT(OFS_RETURN) = PR_SetString(s);
 }
 
 void PF_fabs (void)
@@ -1052,7 +1060,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)
@@ -1060,7 +1068,7 @@ 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)
@@ -1076,9 +1084,9 @@ void PF_Remove (void)
 
        ed = G_EDICT(OFS_PARM0);
        if (ed == sv.edicts)
-               PR_RunError("remove: tried to remove world\n");
+               Host_Error("remove: tried to remove world\n");
        if (NUM_FOR_EDICT(ed) <= svs.maxclients)
-               PR_RunError("remove: tried to remove a client\n");
+               Host_Error("remove: tried to remove a client\n");
        ED_Free (ed);
 }
 
@@ -1121,7 +1129,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;
@@ -1129,7 +1137,7 @@ 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++)
        {
                ed = EDICT_NUM(e);
@@ -1149,7 +1157,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;
@@ -1163,7 +1171,7 @@ 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))
        {
@@ -1175,7 +1183,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;
        }
 
@@ -1186,7 +1194,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;
@@ -1195,7 +1203,7 @@ 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))
        {
@@ -1204,7 +1212,7 @@ void PF_findchainfloat (void)
                if (E_FLOAT(ent,f) != s)
                        continue;
 
-               ent->v.chain = EDICT_TO_PROG(chain);
+               ent->v->chain = EDICT_TO_PROG(chain);
                chain = ent;
        }
 
@@ -1214,7 +1222,7 @@ void PF_findchainfloat (void)
 void PR_CheckEmptyString (char *s)
 {
        if (s[0] <= ' ')
-               PR_RunError ("Bad string");
+               Host_Error ("Bad string");
 }
 
 void PF_precache_file (void)
@@ -1228,12 +1236,12 @@ void PF_precache_sound (void)
        int             i;
 
        if (sv.state != ss_loading)
-               PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
+               Host_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++)
        {
                if (!sv.sound_precache[i])
@@ -1244,16 +1252,16 @@ void PF_precache_sound (void)
                if (!strcmp(sv.sound_precache[i], s))
                        return;
        }
-       PR_RunError ("PF_precache_sound: overflow");
+       Host_Error ("PF_precache_sound: overflow");
 }
 
 void PF_precache_model (void)
 {
        char    *s;
        int             i;
-       
+
        if (sv.state != ss_loading)
-               PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
+               Host_Error ("PF_Precache_*: Precache can only be done in spawn functions");
 
        s = G_STRING(OFS_PARM0);
        if (sv.worldmodel->ishlbsp && ((!s) || (!s[0])))
@@ -1272,7 +1280,7 @@ void PF_precache_model (void)
                if (!strcmp(sv.model_precache[i], s))
                        return;
        }
-       PR_RunError ("PF_precache_model: overflow");
+       Host_Error ("PF_precache_model: overflow");
 }
 
 
@@ -1310,19 +1318,19 @@ void PF_walkmove (void)
        vec3_t  move;
        dfunction_t     *oldf;
        int     oldself;
-       
+
        ent = PROG_TO_EDICT(pr_global_struct->self);
        yaw = G_FLOAT(OFS_PARM0);
        dist = G_FLOAT(OFS_PARM1);
-       
-       if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
+
+       if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
        {
                G_FLOAT(OFS_RETURN) = 0;
                return;
        }
 
        yaw = yaw*M_PI*2 / 360;
-       
+
        move[0] = cos(yaw)*dist;
        move[1] = sin(yaw)*dist;
        move[2] = 0;
@@ -1330,10 +1338,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;
@@ -1354,19 +1362,19 @@ void PF_droptofloor (void)
 
        ent = PROG_TO_EDICT(pr_global_struct->self);
 
-       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);
+       trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
 
-       if (trace.fraction == 1 || trace.allsolid)
+       if (trace.fraction == 1)
                G_FLOAT(OFS_RETURN) = 0;
        else
        {
-               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->suspendedinairflag = true;
@@ -1442,7 +1450,7 @@ PF_pointcontents
 */
 void PF_pointcontents (void)
 {
-       G_FLOAT(OFS_RETURN) = Mod_PointInLeaf(G_VECTOR(OFS_PARM0), sv.worldmodel)->contents;
+       G_FLOAT(OFS_RETURN) = Mod_PointContents(G_VECTOR(OFS_PARM0), sv.worldmodel);
 }
 
 /*
@@ -1495,15 +1503,15 @@ void PF_aim (void)
        ent = G_EDICT(OFS_PARM0);
        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 && ((edict_t *)tr.ent)->v.takedamage == DAMAGE_AIM
-       && (!teamplay.integer || ent->v.team <=0 || ent->v.team != ((edict_t *)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;
@@ -1518,15 +1526,15 @@ void PF_aim (void)
        check = NEXT_EDICT(sv.edicts);
        for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
        {
-               if (check->v.takedamage != DAMAGE_AIM)
+               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);
@@ -1542,7 +1550,7 @@ void PF_aim (void)
 
        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];
@@ -1568,9 +1576,9 @@ void PF_changeyaw (void)
        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;
+       current = ANGLEMOD(ent->v->angles[1]);
+       ideal = ent->v->ideal_yaw;
+       speed = ent->v->yaw_speed;
 
        if (current == ideal)
                return;
@@ -1596,7 +1604,7 @@ void PF_changeyaw (void)
                        move = -speed;
        }
 
-       ent->v.angles[1] = ANGLEMOD (current + move);
+       ent->v->angles[1] = ANGLEMOD (current + move);
 }
 
 /*
@@ -1611,19 +1619,19 @@ void PF_changepitch (void)
        eval_t          *val;
 
        ent = G_EDICT(OFS_PARM0);
-       current = ANGLEMOD( ent->v.angles[0] );
+       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");
+               Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
                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");
+               Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
                return;
        }
 
@@ -1651,7 +1659,7 @@ void PF_changepitch (void)
                        move = -speed;
        }
 
-       ent->v.angles[0] = ANGLEMOD (current + move);
+       ent->v->angles[0] = ANGLEMOD (current + move);
 }
 
 /*
@@ -1683,7 +1691,7 @@ sizebuf_t *WriteDest (void)
                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");
+                       Host_Error ("WriteDest: not a client");
                return &svs.clients[entnum-1].message;
 
        case MSG_ALL:
@@ -1693,7 +1701,7 @@ sizebuf_t *WriteDest (void)
                return &sv.signon;
 
        default:
-               PR_RunError ("WriteDest: bad destination");
+               Host_Error ("WriteDest: bad destination");
                break;
        }
 
@@ -1743,38 +1751,36 @@ 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);
 
        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_WriteDPCoord(&sv.signon, ent->v->origin[i]);
+               MSG_WriteAngle(&sv.signon, ent->v->angles[i]);
        }
 
 // throw the entity away now
@@ -1797,7 +1803,7 @@ 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");
+               Host_Error ("Entity is not a client");
 
        // copy spawn parms out of the client_t
        client = svs.clients + (i-1);
@@ -1889,8 +1895,8 @@ int currentqc_cvar;
 
 void PF_registercvar (void)
 {
-       char    *name, *value;
-       cvar_t  *variable;
+       char *name, *value;
+       cvar_t *variable;
        name = G_STRING(OFS_PARM0);
        value = G_STRING(OFS_PARM1);
        G_FLOAT(OFS_RETURN) = 0;
@@ -1906,7 +1912,7 @@ void PF_registercvar (void)
        }
 
        if (currentqc_cvar >= MAX_QC_CVARS)
-               PR_RunError ("PF_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
+               Host_Error ("PF_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
 
 // copy the name and value
        variable = &qc_cvar[currentqc_cvar++];
@@ -1916,9 +1922,7 @@ void PF_registercvar (void)
        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
 }
 
@@ -1946,7 +1950,7 @@ void PF_min (void)
                G_FLOAT(OFS_RETURN) = f;
        }
        else
-               PR_RunError("min: must supply at least 2 floats\n");
+               Host_Error("min: must supply at least 2 floats\n");
 }
 
 /*
@@ -1973,7 +1977,7 @@ void PF_max (void)
                G_FLOAT(OFS_RETURN) = f;
        }
        else
-               PR_RunError("max: must supply at least 2 floats\n");
+               Host_Error("max: must supply at least 2 floats\n");
 }
 
 /*
@@ -2018,7 +2022,7 @@ void PF_copyentity (void)
        edict_t *in, *out;
        in = G_EDICT(OFS_PARM0);
        out = G_EDICT(OFS_PARM1);
-       memcpy(out, in, pr_edict_size);
+       memcpy(out->v, in->v, progs->entityfields * 4);
 }
 
 /*
@@ -2046,7 +2050,7 @@ void PF_setcolor (void)
 
        client = &svs.clients[entnum-1];
        client->colors = i;
-       client->edict->v.team = (i & 15) + 1;
+       client->edict->v->team = (i & 15) + 1;
 
        MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
        MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
@@ -2065,7 +2069,7 @@ void PF_effect (void)
        char *s;
        s = G_STRING(OFS_PARM1);
        if (!s || !s[0])
-               PR_RunError("effect: no model specified\n");
+               Host_Error("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));
 }
@@ -2461,9 +2465,170 @@ void PF_te_plasmaburn (void)
        MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
 }
 
+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->free)
+               return NULL;
+       modelindex = ed->v->modelindex;
+       if (modelindex < 1 || modelindex >= MAX_MODELS)
+               return NULL;
+       model = sv.models[modelindex];
+       if (model->type != mod_brush)
+               return NULL;
+       if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
+               return NULL;
+       return model->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->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->free)
+               return;
+       modelindex = ed->v->modelindex;
+       if (modelindex < 1 || modelindex >= MAX_MODELS)
+               return;
+       model = sv.models[modelindex];
+       if (model->type != mod_brush)
+               return;
+
+       // FIXME: implement rotation/scaling
+       VectorSubtract(point, ed->v->origin, p);
+       best = -1;
+       bestdist = 1000000000;
+       for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
+       {
+               surf = model->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->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)
 {
-       PR_RunError ("unimplemented builtin"); // LordHavoc: was misspelled (bulitin)
+       Host_Error ("unimplemented QC builtin"); // LordHavoc: was misspelled (bulitin)
 }
 
 
@@ -2619,6 +2784,12 @@ PF_te_lightning3,                // #430
 PF_te_beam,                            // #431
 PF_vectorvectors,              // #432
 PF_te_plasmaburn,              // #433
+PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
+PF_getsurfacepoint,     // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
+PF_getsurfacenormal,    // #436 vector(entity e, float s) getsurfacenormal = #436;
+PF_getsurfacetexture,   // #437 string(entity e, float s) getsurfacetexture = #437;
+PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
+PF_getsurfaceclippedpoint,// #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
 };
 
 builtin_t *pr_builtins = pr_builtin;