]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - pr_cmds.c
upgraded network protocol to DP5, now sends precise entity angles (except for EF_LOWP...
[xonotic/darkplaces.git] / pr_cmds.c
index 74872ab17a909a87031617684cc99b0e1a2d5a29..d2b39692b9ffe9ab25963654a9a91229b8df409e 100644 (file)
--- a/pr_cmds.c
+++ b/pr_cmds.c
@@ -39,7 +39,9 @@ static char *PR_GetTempString(void)
        return s;
 }
 
-#define        RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
+#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)
 
 
 /*
@@ -143,6 +145,7 @@ char *ENGINE_EXTENSIONS =
 "KRIMZON_SV_PARSECLIENTCOMMAND "
 "NEH_CMD_PLAY2 "
 "NEH_RESTOREGAME "
+"TENEBRAE_GFX_DLIGHTS "
 "TW_SV_STEPCONTROL "
 ;
 
@@ -201,7 +204,7 @@ void PF_error (void)
        ed = PROG_TO_EDICT(pr_global_struct->self);
        ED_Print (ed);
 
-       Host_Error ("Program error");
+       PF_ERROR("Program error");
 }
 
 /*
@@ -270,9 +273,9 @@ void PF_setorigin (void)
 
        e = G_EDICT(OFS_PARM0);
        if (e == sv.edicts)
-               Host_Error("setorigin: can not modify world entity\n");
+               PF_WARNING("setorigin: can not modify world entity\n");
        if (e->e->free)
-               Host_Error("setorigin: can not modify free entity\n");
+               PF_WARNING("setorigin: can not modify free entity\n");
        org = G_VECTOR(OFS_PARM1);
        VectorCopy (org, e->v->origin);
        SV_LinkEdict (e, false);
@@ -285,7 +288,7 @@ void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
 
        for (i=0 ; i<3 ; i++)
                if (min[i] > max[i])
-                       Host_Error ("backwards mins/maxs");
+                       PF_ERROR("SetMinMaxSize: backwards mins/maxs\n");
 
 // set derived values
        VectorCopy (min, e->v->mins);
@@ -312,9 +315,9 @@ void PF_setsize (void)
 
        e = G_EDICT(OFS_PARM0);
        if (e == sv.edicts)
-               Host_Error("setsize: can not modify world entity\n");
+               PF_WARNING("setsize: can not modify world entity\n");
        if (e->e->free)
-               Host_Error("setsize: can not modify free entity\n");
+               PF_WARNING("setsize: can not modify free entity\n");
        min = G_VECTOR(OFS_PARM1);
        max = G_VECTOR(OFS_PARM2);
        SetMinMaxSize (e, min, max, false);
@@ -337,9 +340,9 @@ void PF_setmodel (void)
 
        e = G_EDICT(OFS_PARM0);
        if (e == sv.edicts)
-               Host_Error("setmodel: can not modify world entity\n");
+               PF_WARNING("setmodel: can not modify world entity\n");
        if (e->e->free)
-               Host_Error("setmodel: can not modify free entity\n");
+               PF_WARNING("setmodel: can not modify free entity\n");
        m = G_STRING(OFS_PARM1);
 
 // check to see if model was properly precached
@@ -348,7 +351,7 @@ void PF_setmodel (void)
                        break;
 
        if (!*check)
-               Host_Error ("no precache: %s\n", m);
+               PF_WARNING("setmodel: no precache\n");
 
 
        e->v->model = PR_SetString(*check);
@@ -691,13 +694,13 @@ void PF_sound (void)
        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);
 }
@@ -711,7 +714,7 @@ break()
 */
 void PF_break (void)
 {
-       Host_Error ("break statement");
+       PF_ERROR("break: break statement\n");
 }
 
 /*
@@ -729,17 +732,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, 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;
@@ -773,7 +776,7 @@ void PF_tracebox (void)
 {
        float   *v1, *v2, *m1, *m2;
        trace_t trace;
-       int             nomonsters;
+       int             move;
        edict_t *ent;
 
        pr_xfunction->builtinsprofile += 30;
@@ -782,10 +785,10 @@ void PF_tracebox (void)
        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;
@@ -812,7 +815,7 @@ void PF_TraceToss (void)
 
        ent = G_EDICT(OFS_PARM0);
        if (ent == sv.edicts)
-               Host_Error("tracetoss: can not use world entity\n");
+               PF_WARNING("tracetoss: can not use world entity\n");
        ignore = G_EDICT(OFS_PARM1);
 
        trace = SV_Trace_Toss (ent, ignore);
@@ -1127,12 +1130,12 @@ void PF_Remove (void)
 
        ed = G_EDICT(OFS_PARM0);
        if (ed == sv.edicts)
-               Host_Error("remove: tried to remove world\n");
+               PF_WARNING("remove: tried to remove world\n");
        if (NUM_FOR_EDICT(ed) <= svs.maxclients)
-               Host_Error("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)
-               Con_Printf("remove: tried to remove an entity that was already removed\n");
+               PF_WARNING("remove: tried to remove an entity that was already removed\n");
        ED_Free (ed);
 }
 
@@ -1272,7 +1275,7 @@ void PF_findchainfloat (void)
 void PR_CheckEmptyString (char *s)
 {
        if (s[0] <= ' ')
-               Host_Error ("Bad string");
+               PF_ERROR("Bad string");
 }
 
 void PF_precache_file (void)
@@ -1286,7 +1289,7 @@ void PF_precache_sound (void)
        int             i;
 
        if (sv.state != ss_loading)
-               Host_Error ("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);
@@ -1302,7 +1305,7 @@ void PF_precache_sound (void)
                if (!strcmp(sv.sound_precache[i], s))
                        return;
        }
-       Host_Error ("PF_precache_sound: overflow");
+       PF_ERROR("PF_precache_sound: overflow");
 }
 
 void PF_precache_model (void)
@@ -1311,7 +1314,7 @@ void PF_precache_model (void)
        int             i;
 
        if (sv.state != ss_loading)
-               Host_Error ("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->brush.ishlbsp && ((!s) || (!s[0])))
@@ -1330,7 +1333,7 @@ void PF_precache_model (void)
                if (!strcmp(sv.model_precache[i], s))
                        return;
        }
-       Host_Error ("PF_precache_model: overflow");
+       PF_ERROR("PF_precache_model: overflow");
 }
 
 
@@ -1369,19 +1372,19 @@ void PF_walkmove (void)
        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)
-               Host_Error("walkmove: can not modify world entity\n");
+               PF_WARNING("walkmove: can not modify world entity\n");
        if (ent->e->free)
-               Host_Error("walkmove: can not modify free entity\n");
+               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;
                return;
-       }
 
        yaw = yaw*M_PI*2 / 360;
 
@@ -1414,20 +1417,21 @@ void PF_droptofloor (void)
        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)
-               Host_Error("droptofloor: can not modify world entity\n");
+               PF_WARNING("droptofloor: can not modify world entity\n");
        if (ent->e->free)
-               Host_Error("droptofloor: can not modify free entity\n");
+               PF_WARNING("droptofloor: can not modify free entity\n");
 
        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)
-               G_FLOAT(OFS_RETURN) = 0;
-       else
+       if (trace.fraction != 1)
        {
                VectorCopy (trace.endpos, ent->v->origin);
                SV_LinkEdict (ent, false);
@@ -1561,11 +1565,14 @@ void PF_aim (void)
        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)
-               Host_Error("aim: can not use world entity\n");
+               PF_WARNING("aim: can not use world entity\n");
        if (ent->e->free)
-               Host_Error("aim: can not use free entity\n");
+               PF_WARNING("aim: can not use free entity\n");
        speed = G_FLOAT(OFS_PARM1);
 
        VectorCopy (ent->v->origin, start);
@@ -1643,9 +1650,9 @@ void PF_changeyaw (void)
 
        ent = PROG_TO_EDICT(pr_global_struct->self);
        if (ent == sv.edicts)
-               Host_Error("changeyaw: can not modify world entity\n");
+               PF_WARNING("changeyaw: can not modify world entity\n");
        if (ent->e->free)
-               Host_Error("changeyaw: can not modify free entity\n");
+               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;
@@ -1690,22 +1697,22 @@ void PF_changepitch (void)
 
        ent = G_EDICT(OFS_PARM0);
        if (ent == sv.edicts)
-               Host_Error("changepitch: can not modify world entity\n");
+               PF_WARNING("changepitch: can not modify world entity\n");
        if (ent->e->free)
-               Host_Error("changepitch: can not modify free entity\n");
+               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
        {
-               Host_Error ("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
        {
-               Host_Error ("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;
        }
 
@@ -1775,7 +1782,7 @@ sizebuf_t *WriteDest (void)
                return &sv.signon;
 
        default:
-               Host_Error ("WriteDest: bad destination");
+               Host_Error("WriteDest: bad destination");
                break;
        }
 
@@ -1832,9 +1839,9 @@ void PF_makestatic (void)
 
        ent = G_EDICT(OFS_PARM0);
        if (ent == sv.edicts)
-               Host_Error("makestatic: can not modify world entity\n");
+               PF_WARNING("makestatic: can not modify world entity\n");
        if (ent->e->free)
-               Host_Error("makestatic: can not modify free entity\n");
+               PF_WARNING("makestatic: can not modify free entity\n");
 
        large = false;
        if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
@@ -1995,7 +2002,7 @@ void PF_registercvar (void)
        }
 
        if (currentqc_cvar >= MAX_QC_CVARS)
-               Host_Error ("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++];
@@ -2033,7 +2040,10 @@ void PF_min (void)
                G_FLOAT(OFS_RETURN) = f;
        }
        else
-               Host_Error("min: must supply at least 2 floats\n");
+       {
+               G_FLOAT(OFS_RETURN) = 0;
+               PF_WARNING("min: must supply at least 2 floats\n");
+       }
 }
 
 /*
@@ -2060,7 +2070,10 @@ void PF_max (void)
                G_FLOAT(OFS_RETURN) = f;
        }
        else
-               Host_Error("max: must supply at least 2 floats\n");
+       {
+               G_FLOAT(OFS_RETURN) = 0;
+               PF_WARNING("max: must supply at least 2 floats\n");
+       }
 }
 
 /*
@@ -2105,14 +2118,14 @@ void PF_copyentity (void)
        edict_t *in, *out;
        in = G_EDICT(OFS_PARM0);
        if (in == sv.edicts)
-               Host_Error("copyentity: can not read world entity\n");
+               PF_WARNING("copyentity: can not read world entity\n");
        if (in->e->free)
-               Host_Error("copyentity: can not read free entity\n");
+               PF_WARNING("copyentity: can not read free entity\n");
        out = G_EDICT(OFS_PARM1);
        if (out == sv.edicts)
-               Host_Error("copyentity: can not modify world entity\n");
+               PF_WARNING("copyentity: can not modify world entity\n");
        if (out->e->free)
-               Host_Error("copyentity: can not modify free entity\n");
+               PF_WARNING("copyentity: can not modify free entity\n");
        memcpy(out->v, in->v, progs->entityfields * 4);
 }
 
@@ -2164,7 +2177,7 @@ void PF_effect (void)
        char *s;
        s = G_STRING(OFS_PARM1);
        if (!s || !s[0])
-               Host_Error("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));
 }
@@ -2957,30 +2970,26 @@ void PF_clientcommand (void)
 
 //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
-char **tokens = NULL;
-int    max_tokens, num_tokens = 0;
+//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;
-       char *str;
-       str = G_STRING(OFS_PARM0);
+       p = G_STRING(OFS_PARM0);
 
-       if (tokens != NULL)
+       num_tokens = 0;
+       pos = 0;
+       while(COM_ParseToken(&p, false))
        {
-               int i;
-               for (i=0;i<num_tokens;i++)
-                       Z_Free(tokens[i]);
-               Z_Free(tokens);
-               num_tokens = 0;
-       }
-
-       tokens = Z_Malloc(strlen(str) * sizeof(char *));
-       max_tokens = strlen(str);
-
-       for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
-       {
-               tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
-               strcpy(tokens[num_tokens], com_token);
+               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;
@@ -3008,9 +3017,9 @@ void PF_setattachment (void)
        model_t *model;
 
        if (e == sv.edicts)
-               Host_Error("setattachment: can not modify world entity\n");
+               PF_WARNING("setattachment: can not modify world entity\n");
        if (e->e->free)
-               Host_Error("setattachment: can not modify free entity\n");
+               PF_WARNING("setattachment: can not modify free entity\n");
 
        if (tagentity == NULL)
                tagentity = sv.edicts;