]> icculus.org git repositories - divverent/darkplaces.git/blob - pr_edict.c
fixed an unused variable warning
[divverent/darkplaces.git] / pr_edict.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // sv_edict.c -- entity dictionary
21
22 #include "quakedef.h"
23
24 dprograms_t             *progs;
25 mfunction_t             *pr_functions;
26 char                    *pr_strings;
27 ddef_t                  *pr_fielddefs;
28 ddef_t                  *pr_globaldefs;
29 dstatement_t    *pr_statements;
30 globalvars_t    *pr_global_struct;
31 float                   *pr_globals;                    // same as pr_global_struct
32 int                             pr_edict_size;                  // in bytes
33 int                             pr_edictareasize;               // LordHavoc: in bytes
34
35 unsigned short  pr_crc;
36
37 mempool_t               *progs_mempool;
38 mempool_t               *edictstring_mempool;
39
40 int             type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
41
42 ddef_t *ED_FieldAtOfs(int ofs);
43 qboolean ED_ParseEpair(edict_t *ent, ddef_t *key, const char *s);
44
45 cvar_t  pr_checkextension = {CVAR_READONLY, "pr_checkextension", "1"};
46 cvar_t  nomonsters = {0, "nomonsters", "0"};
47 cvar_t  gamecfg = {0, "gamecfg", "0"};
48 cvar_t  scratch1 = {0, "scratch1", "0"};
49 cvar_t  scratch2 = {0,"scratch2", "0"};
50 cvar_t  scratch3 = {0, "scratch3", "0"};
51 cvar_t  scratch4 = {0, "scratch4", "0"};
52 cvar_t  savedgamecfg = {CVAR_SAVE, "savedgamecfg", "0"};
53 cvar_t  saved1 = {CVAR_SAVE, "saved1", "0"};
54 cvar_t  saved2 = {CVAR_SAVE, "saved2", "0"};
55 cvar_t  saved3 = {CVAR_SAVE, "saved3", "0"};
56 cvar_t  saved4 = {CVAR_SAVE, "saved4", "0"};
57 cvar_t  decors = {0, "decors", "0"};
58 cvar_t  nehx00 = {0, "nehx00", "0"};cvar_t      nehx01 = {0, "nehx01", "0"};
59 cvar_t  nehx02 = {0, "nehx02", "0"};cvar_t      nehx03 = {0, "nehx03", "0"};
60 cvar_t  nehx04 = {0, "nehx04", "0"};cvar_t      nehx05 = {0, "nehx05", "0"};
61 cvar_t  nehx06 = {0, "nehx06", "0"};cvar_t      nehx07 = {0, "nehx07", "0"};
62 cvar_t  nehx08 = {0, "nehx08", "0"};cvar_t      nehx09 = {0, "nehx09", "0"};
63 cvar_t  nehx10 = {0, "nehx10", "0"};cvar_t      nehx11 = {0, "nehx11", "0"};
64 cvar_t  nehx12 = {0, "nehx12", "0"};cvar_t      nehx13 = {0, "nehx13", "0"};
65 cvar_t  nehx14 = {0, "nehx14", "0"};cvar_t      nehx15 = {0, "nehx15", "0"};
66 cvar_t  nehx16 = {0, "nehx16", "0"};cvar_t      nehx17 = {0, "nehx17", "0"};
67 cvar_t  nehx18 = {0, "nehx18", "0"};cvar_t      nehx19 = {0, "nehx19", "0"};
68 cvar_t  cutscene = {0, "cutscene", "1"};
69 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
70 cvar_t  pr_boundscheck = {0, "pr_boundscheck", "1"};
71 // LordHavoc: prints every opcode as it executes - warning: this is significant spew
72 cvar_t  pr_traceqc = {0, "pr_traceqc", "0"};
73
74 #define MAX_FIELD_LEN   64
75 #define GEFV_CACHESIZE  2
76
77 typedef struct {
78         ddef_t  *pcache;
79         char    field[MAX_FIELD_LEN];
80 } gefv_cache;
81
82 static gefv_cache       gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};
83
84 ddef_t *ED_FindField (const char *name);
85 mfunction_t *ED_FindFunction (const char *name);
86
87 // LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue...  these are defined as externs in progs.h
88 int eval_gravity;
89 int eval_button3;
90 int eval_button4;
91 int eval_button5;
92 int eval_button6;
93 int eval_button7;
94 int eval_button8;
95 int eval_glow_size;
96 int eval_glow_trail;
97 int eval_glow_color;
98 int eval_items2;
99 int eval_scale;
100 int eval_alpha;
101 int eval_renderamt; // HalfLife support
102 int eval_rendermode; // HalfLife support
103 int eval_fullbright;
104 int eval_ammo_shells1;
105 int eval_ammo_nails1;
106 int eval_ammo_lava_nails;
107 int eval_ammo_rockets1;
108 int eval_ammo_multi_rockets;
109 int eval_ammo_cells1;
110 int eval_ammo_plasma;
111 int eval_idealpitch;
112 int eval_pitch_speed;
113 int eval_viewmodelforclient;
114 int eval_nodrawtoclient;
115 int eval_exteriormodeltoclient;
116 int eval_drawonlytoclient;
117 int eval_ping;
118 int eval_movement;
119 int eval_pmodel;
120 int eval_punchvector;
121 int eval_viewzoom;
122 int eval_clientcolors;
123 int eval_tag_entity;
124 int eval_tag_index;
125 int eval_light_lev;
126 int eval_color;
127 int eval_style;
128 int eval_pflags;
129
130 mfunction_t *SV_PlayerPhysicsQC;
131 mfunction_t *EndFrameQC;
132 //KrimZon - SERVER COMMANDS IN QUAKEC
133 mfunction_t *SV_ParseClientCommandQC;
134
135 int FindFieldOffset(const char *field)
136 {
137         ddef_t *d;
138         d = ED_FindField(field);
139         if (!d)
140                 return 0;
141         return d->ofs*4;
142 }
143
144 void FindEdictFieldOffsets(void)
145 {
146         eval_gravity = FindFieldOffset("gravity");
147         eval_button3 = FindFieldOffset("button3");
148         eval_button4 = FindFieldOffset("button4");
149         eval_button5 = FindFieldOffset("button5");
150         eval_button6 = FindFieldOffset("button6");
151         eval_button7 = FindFieldOffset("button7");
152         eval_button8 = FindFieldOffset("button8");
153         eval_glow_size = FindFieldOffset("glow_size");
154         eval_glow_trail = FindFieldOffset("glow_trail");
155         eval_glow_color = FindFieldOffset("glow_color");
156         eval_items2 = FindFieldOffset("items2");
157         eval_scale = FindFieldOffset("scale");
158         eval_alpha = FindFieldOffset("alpha");
159         eval_renderamt = FindFieldOffset("renderamt"); // HalfLife support
160         eval_rendermode = FindFieldOffset("rendermode"); // HalfLife support
161         eval_fullbright = FindFieldOffset("fullbright");
162         eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
163         eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
164         eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
165         eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
166         eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
167         eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
168         eval_ammo_plasma = FindFieldOffset("ammo_plasma");
169         eval_idealpitch = FindFieldOffset("idealpitch");
170         eval_pitch_speed = FindFieldOffset("pitch_speed");
171         eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
172         eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
173         eval_exteriormodeltoclient = FindFieldOffset("exteriormodeltoclient");
174         eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
175         eval_ping = FindFieldOffset("ping");
176         eval_movement = FindFieldOffset("movement");
177         eval_pmodel = FindFieldOffset("pmodel");
178         eval_punchvector = FindFieldOffset("punchvector");
179         eval_viewzoom = FindFieldOffset("viewzoom");
180         eval_clientcolors = FindFieldOffset("clientcolors");
181         eval_tag_entity = FindFieldOffset("tag_entity");
182         eval_tag_index = FindFieldOffset("tag_index");
183         eval_light_lev = FindFieldOffset("light_lev");
184         eval_color = FindFieldOffset("color");
185         eval_style = FindFieldOffset("style");
186         eval_pflags = FindFieldOffset("pflags");
187
188         // LordHavoc: allowing QuakeC to override the player movement code
189         SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
190         // LordHavoc: support for endframe
191         EndFrameQC = ED_FindFunction ("EndFrame");
192         //KrimZon - SERVER COMMANDS IN QUAKEC
193         SV_ParseClientCommandQC = ED_FindFunction ("SV_ParseClientCommand");
194 }
195
196 /*
197 =================
198 ED_ClearEdict
199
200 Sets everything to NULL
201 =================
202 */
203 void ED_ClearEdict (edict_t *e)
204 {
205         int num;
206         memset (e->v, 0, progs->entityfields * 4);
207         e->e->free = false;
208         // LordHavoc: for consistency set these here
209         num = NUM_FOR_EDICT(e) - 1;
210         if (num >= 0 && num < svs.maxclients)
211         {
212                 e->v->colormap = num + 1;
213                 e->v->team = (svs.clients[num].colors & 15) + 1;
214                 e->v->netname = PR_SetString(svs.clients[num].name);
215         }
216 }
217
218 /*
219 =================
220 ED_Alloc
221
222 Either finds a free edict, or allocates a new one.
223 Try to avoid reusing an entity that was recently freed, because it
224 can cause the client to think the entity morphed into something else
225 instead of being removed and recreated, which can cause interpolated
226 angles and bad trails.
227 =================
228 */
229 edict_t *ED_Alloc (void)
230 {
231         int                     i;
232         edict_t         *e;
233
234         for (i = svs.maxclients + 1;i < sv.num_edicts;i++)
235         {
236                 e = EDICT_NUM(i);
237                 // the first couple seconds of server time can involve a lot of
238                 // freeing and allocating, so relax the replacement policy
239                 if (e->e->free && ( e->e->freetime < 2 || sv.time - e->e->freetime > 0.5 ) )
240                 {
241                         ED_ClearEdict (e);
242                         return e;
243                 }
244         }
245
246         if (i == MAX_EDICTS)
247                 Host_Error ("ED_Alloc: no free edicts");
248
249         sv.num_edicts++;
250         if (sv.num_edicts >= sv.max_edicts)
251                 SV_IncreaseEdicts();
252         e = EDICT_NUM(i);
253         ED_ClearEdict (e);
254
255         return e;
256 }
257
258 /*
259 =================
260 ED_Free
261
262 Marks the edict as free
263 FIXME: walk all entities and NULL out references to this entity
264 =================
265 */
266 void ED_Free (edict_t *ed)
267 {
268         SV_UnlinkEdict (ed);            // unlink from world bsp
269
270         ed->e->free = true;
271         ed->v->model = 0;
272         ed->v->takedamage = 0;
273         ed->v->modelindex = 0;
274         ed->v->colormap = 0;
275         ed->v->skin = 0;
276         ed->v->frame = 0;
277         VectorClear(ed->v->origin);
278         VectorClear(ed->v->angles);
279         ed->v->nextthink = -1;
280         ed->v->solid = 0;
281
282         ed->e->freetime = sv.time;
283 }
284
285 //===========================================================================
286
287 /*
288 ============
289 ED_GlobalAtOfs
290 ============
291 */
292 ddef_t *ED_GlobalAtOfs (int ofs)
293 {
294         ddef_t          *def;
295         int                     i;
296
297         for (i=0 ; i<progs->numglobaldefs ; i++)
298         {
299                 def = &pr_globaldefs[i];
300                 if (def->ofs == ofs)
301                         return def;
302         }
303         return NULL;
304 }
305
306 /*
307 ============
308 ED_FieldAtOfs
309 ============
310 */
311 ddef_t *ED_FieldAtOfs (int ofs)
312 {
313         ddef_t          *def;
314         int                     i;
315
316         for (i=0 ; i<progs->numfielddefs ; i++)
317         {
318                 def = &pr_fielddefs[i];
319                 if (def->ofs == ofs)
320                         return def;
321         }
322         return NULL;
323 }
324
325 /*
326 ============
327 ED_FindField
328 ============
329 */
330 ddef_t *ED_FindField (const char *name)
331 {
332         ddef_t *def;
333         int i;
334
335         for (i=0 ; i<progs->numfielddefs ; i++)
336         {
337                 def = &pr_fielddefs[i];
338                 if (!strcmp(PR_GetString(def->s_name), name))
339                         return def;
340         }
341         return NULL;
342 }
343
344 /*
345 ============
346 ED_FindGlobal
347 ============
348 */
349 ddef_t *ED_FindGlobal (const char *name)
350 {
351         ddef_t *def;
352         int i;
353
354         for (i=0 ; i<progs->numglobaldefs ; i++)
355         {
356                 def = &pr_globaldefs[i];
357                 if (!strcmp(PR_GetString(def->s_name), name))
358                         return def;
359         }
360         return NULL;
361 }
362
363
364 /*
365 ============
366 ED_FindFunction
367 ============
368 */
369 mfunction_t *ED_FindFunction (const char *name)
370 {
371         mfunction_t             *func;
372         int                             i;
373
374         for (i=0 ; i<progs->numfunctions ; i++)
375         {
376                 func = &pr_functions[i];
377                 if (!strcmp(PR_GetString(func->s_name), name))
378                         return func;
379         }
380         return NULL;
381 }
382
383
384 /*
385 ============
386 PR_ValueString
387
388 Returns a string describing *data in a type specific manner
389 =============
390 */
391 //int NoCrash_NUM_FOR_EDICT(edict_t *e);
392 char *PR_ValueString (etype_t type, eval_t *val)
393 {
394         static char line[1024]; // LordHavoc: enlarged a bit (was 256)
395         ddef_t *def;
396         mfunction_t *f;
397         int n;
398
399         type &= ~DEF_SAVEGLOBAL;
400
401         switch (type)
402         {
403         case ev_string:
404                 strlcpy (line, PR_GetString (val->string), sizeof (line));
405                 break;
406         case ev_entity:
407                 //n = NoCrash_NUM_FOR_EDICT(PROG_TO_EDICT(val->edict));
408                 n = val->edict;
409                 if (n < 0 || n >= MAX_EDICTS)
410                         snprintf (line, sizeof (line), "entity %i (invalid!)", n);
411                 else
412                         snprintf (line, sizeof (line), "entity %i", n);
413                 break;
414         case ev_function:
415                 f = pr_functions + val->function;
416                 snprintf (line, sizeof (line), "%s()", PR_GetString(f->s_name));
417                 break;
418         case ev_field:
419                 def = ED_FieldAtOfs ( val->_int );
420                 snprintf (line, sizeof (line), ".%s", PR_GetString(def->s_name));
421                 break;
422         case ev_void:
423                 snprintf (line, sizeof (line), "void");
424                 break;
425         case ev_float:
426                 // LordHavoc: changed from %5.1f to %10.4f
427                 snprintf (line, sizeof (line), "%10.4f", val->_float);
428                 break;
429         case ev_vector:
430                 // LordHavoc: changed from %5.1f to %10.4f
431                 snprintf (line, sizeof (line), "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
432                 break;
433         case ev_pointer:
434                 snprintf (line, sizeof (line), "pointer");
435                 break;
436         default:
437                 snprintf (line, sizeof (line), "bad type %i", type);
438                 break;
439         }
440
441         return line;
442 }
443
444 /*
445 ============
446 PR_UglyValueString
447
448 Returns a string describing *data in a type specific manner
449 Easier to parse than PR_ValueString
450 =============
451 */
452 char *PR_UglyValueString (etype_t type, eval_t *val)
453 {
454         static char line[4096];
455         int i;
456         char *s;
457         ddef_t *def;
458         mfunction_t *f;
459
460         type &= ~DEF_SAVEGLOBAL;
461
462         switch (type)
463         {
464         case ev_string:
465                 // Parse the string a bit to turn special characters
466                 // (like newline, specifically) into escape codes,
467                 // this fixes saving games from various mods
468                 s = PR_GetString (val->string);
469                 for (i = 0;i < (int)sizeof(line) - 2 && *s;)
470                 {
471                         if (*s == '\n')
472                         {
473                                 line[i++] = '\\';
474                                 line[i++] = 'n';
475                         }
476                         else if (*s == '\r')
477                         {
478                                 line[i++] = '\\';
479                                 line[i++] = 'r';
480                         }
481                         else
482                                 line[i++] = *s;
483                         s++;
484                 }
485                 line[i] = '\0';
486                 break;
487         case ev_entity:
488                 snprintf (line, sizeof (line), "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
489                 break;
490         case ev_function:
491                 f = pr_functions + val->function;
492                 strlcpy (line, PR_GetString (f->s_name), sizeof (line));
493                 break;
494         case ev_field:
495                 def = ED_FieldAtOfs ( val->_int );
496                 snprintf (line, sizeof (line), ".%s", PR_GetString(def->s_name));
497                 break;
498         case ev_void:
499                 snprintf (line, sizeof (line), "void");
500                 break;
501         case ev_float:
502                 snprintf (line, sizeof (line), "%f", val->_float);
503                 break;
504         case ev_vector:
505                 snprintf (line, sizeof (line), "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
506                 break;
507         default:
508                 snprintf (line, sizeof (line), "bad type %i", type);
509                 break;
510         }
511
512         return line;
513 }
514
515 /*
516 ============
517 PR_GlobalString
518
519 Returns a string with a description and the contents of a global,
520 padded to 20 field width
521 ============
522 */
523 char *PR_GlobalString (int ofs)
524 {
525         char    *s;
526         int             i;
527         ddef_t  *def;
528         void    *val;
529         static char     line[128];
530
531         val = (void *)&pr_globals[ofs];
532         def = ED_GlobalAtOfs(ofs);
533         if (!def)
534                 snprintf (line, sizeof (line), "%i(?)", ofs);
535         else
536         {
537                 s = PR_ValueString (def->type, val);
538                 snprintf (line, sizeof (line), "%i(%s)%s", ofs, PR_GetString(def->s_name), s);
539         }
540
541         i = strlen(line);
542         for ( ; i<20 ; i++)
543                 strlcat (line, " ", sizeof (line));
544         strlcat (line, " ", sizeof (line));
545
546         return line;
547 }
548
549 char *PR_GlobalStringNoContents (int ofs)
550 {
551         int             i;
552         ddef_t  *def;
553         static char     line[128];
554
555         def = ED_GlobalAtOfs(ofs);
556         if (!def)
557                 snprintf (line, sizeof (line), "%i(?)", ofs);
558         else
559                 snprintf (line, sizeof (line), "%i(%s)", ofs, PR_GetString(def->s_name));
560
561         i = strlen(line);
562         for ( ; i<20 ; i++)
563                 strlcat (line, " ", sizeof (line));
564         strlcat (line, " ", sizeof (line));
565
566         return line;
567 }
568
569
570 /*
571 =============
572 ED_Print
573
574 For debugging
575 =============
576 */
577 // LordHavoc: optimized this to print out much more quickly (tempstring)
578 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
579 void ED_Print(edict_t *ed)
580 {
581         int             l;
582         ddef_t  *d;
583         int             *v;
584         int             i, j;
585         char    *name;
586         int             type;
587         char    tempstring[8192], tempstring2[260]; // temporary string buffers
588
589         if (ed->e->free)
590         {
591                 Con_Print("FREE\n");
592                 return;
593         }
594
595         tempstring[0] = 0;
596         snprintf (tempstring, sizeof (tempstring), "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
597         for (i=1 ; i<progs->numfielddefs ; i++)
598         {
599                 d = &pr_fielddefs[i];
600                 name = PR_GetString(d->s_name);
601                 if (name[strlen(name)-2] == '_')
602                         continue;       // skip _x, _y, _z vars
603
604                 v = (int *)((char *)ed->v + d->ofs*4);
605
606         // if the value is still all 0, skip the field
607                 type = d->type & ~DEF_SAVEGLOBAL;
608
609                 for (j=0 ; j<type_size[type] ; j++)
610                         if (v[j])
611                                 break;
612                 if (j == type_size[type])
613                         continue;
614
615                 if (strlen(name) > 256)
616                 {
617                         memcpy (tempstring2, name, 256);
618                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
619                         tempstring2[259] = 0;
620                         name = tempstring2;
621                 }
622                 strlcat (tempstring, name, sizeof (tempstring));
623                 for (l = strlen(name);l < 14;l++)
624                         strcat(tempstring, " ");
625                 strcat(tempstring, " ");
626
627                 name = PR_ValueString(d->type, (eval_t *)v);
628                 if (strlen(name) > 256)
629                 {
630                         memcpy(tempstring2, name, 256);
631                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
632                         tempstring2[259] = 0;
633                         name = tempstring2;
634                 }
635                 strlcat (tempstring, name, sizeof (tempstring));
636                 strlcat (tempstring, "\n", sizeof (tempstring));
637                 if (strlen(tempstring) >= 4096)
638                 {
639                         Con_Print(tempstring);
640                         tempstring[0] = 0;
641                 }
642         }
643         if (tempstring[0])
644                 Con_Print(tempstring);
645 }
646
647 /*
648 =============
649 ED_Write
650
651 For savegames
652 =============
653 */
654 void ED_Write (qfile_t *f, edict_t *ed)
655 {
656         ddef_t  *d;
657         int             *v;
658         int             i, j;
659         char    *name;
660         int             type;
661
662         FS_Print(f, "{\n");
663
664         if (ed->e->free)
665         {
666                 FS_Print(f, "}\n");
667                 return;
668         }
669
670         for (i=1 ; i<progs->numfielddefs ; i++)
671         {
672                 d = &pr_fielddefs[i];
673                 name = PR_GetString(d->s_name);
674                 if (name[strlen(name)-2] == '_')
675                         continue;       // skip _x, _y, _z vars
676
677                 v = (int *)((char *)ed->v + d->ofs*4);
678
679         // if the value is still all 0, skip the field
680                 type = d->type & ~DEF_SAVEGLOBAL;
681                 for (j=0 ; j<type_size[type] ; j++)
682                         if (v[j])
683                                 break;
684                 if (j == type_size[type])
685                         continue;
686
687                 FS_Printf(f,"\"%s\" ",name);
688                 FS_Printf(f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
689         }
690
691         FS_Print(f, "}\n");
692 }
693
694 void ED_PrintNum (int ent)
695 {
696         ED_Print(EDICT_NUM(ent));
697 }
698
699 /*
700 =============
701 ED_PrintEdicts
702
703 For debugging, prints all the entities in the current server
704 =============
705 */
706 void ED_PrintEdicts (void)
707 {
708         int             i;
709
710         Con_Printf("%i entities\n", sv.num_edicts);
711         for (i=0 ; i<sv.num_edicts ; i++)
712                 ED_PrintNum (i);
713 }
714
715 /*
716 =============
717 ED_PrintEdict_f
718
719 For debugging, prints a single edict
720 =============
721 */
722 void ED_PrintEdict_f (void)
723 {
724         int             i;
725
726         i = atoi (Cmd_Argv(1));
727         if (i < 0 || i >= sv.num_edicts)
728         {
729                 Con_Print("Bad edict number\n");
730                 return;
731         }
732         ED_PrintNum (i);
733 }
734
735 /*
736 =============
737 ED_Count
738
739 For debugging
740 =============
741 */
742 void ED_Count (void)
743 {
744         int             i;
745         edict_t *ent;
746         int             active, models, solid, step;
747
748         active = models = solid = step = 0;
749         for (i=0 ; i<sv.num_edicts ; i++)
750         {
751                 ent = EDICT_NUM(i);
752                 if (ent->e->free)
753                         continue;
754                 active++;
755                 if (ent->v->solid)
756                         solid++;
757                 if (ent->v->model)
758                         models++;
759                 if (ent->v->movetype == MOVETYPE_STEP)
760                         step++;
761         }
762
763         Con_Printf("num_edicts:%3i\n", sv.num_edicts);
764         Con_Printf("active    :%3i\n", active);
765         Con_Printf("view      :%3i\n", models);
766         Con_Printf("touch     :%3i\n", solid);
767         Con_Printf("step      :%3i\n", step);
768
769 }
770
771 /*
772 ==============================================================================
773
774                                         ARCHIVING GLOBALS
775
776 FIXME: need to tag constants, doesn't really work
777 ==============================================================================
778 */
779
780 /*
781 =============
782 ED_WriteGlobals
783 =============
784 */
785 void ED_WriteGlobals (qfile_t *f)
786 {
787         ddef_t          *def;
788         int                     i;
789         char            *name;
790         int                     type;
791
792         FS_Print(f,"{\n");
793         for (i=0 ; i<progs->numglobaldefs ; i++)
794         {
795                 def = &pr_globaldefs[i];
796                 type = def->type;
797                 if ( !(def->type & DEF_SAVEGLOBAL) )
798                         continue;
799                 type &= ~DEF_SAVEGLOBAL;
800
801                 if (type != ev_string && type != ev_float && type != ev_entity)
802                         continue;
803
804                 name = PR_GetString(def->s_name);
805                 FS_Printf(f,"\"%s\" ", name);
806                 FS_Printf(f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
807         }
808         FS_Print(f,"}\n");
809 }
810
811 /*
812 =============
813 ED_EdictSet_f
814
815 Console command to set a field of a specified edict
816 =============
817 */
818 void ED_EdictSet_f(void)
819 {
820         edict_t *ed;
821         ddef_t *key;
822
823         if(Cmd_Argc() != 4)
824         {
825                 Con_Print("edictset <edict number> <field> <value>\n");
826                 return;
827         }
828         ed = EDICT_NUM(atoi(Cmd_Argv(1)));
829
830         if((key = ED_FindField(Cmd_Argv(2))) == 0)
831         {
832                 Con_Printf("Key %s not found !\n", Cmd_Argv(2));
833                 return;
834         }
835
836         ED_ParseEpair(ed, key, Cmd_Argv(3));
837 }
838
839 /*
840 =============
841 ED_ParseGlobals
842 =============
843 */
844 void ED_ParseGlobals (const char *data)
845 {
846         char keyname[1024]; // LordHavoc: good idea? bad idea?  was 64
847         ddef_t *key;
848
849         while (1)
850         {
851                 // parse key
852                 if (!COM_ParseToken(&data, false))
853                         Host_Error ("ED_ParseEntity: EOF without closing brace");
854                 if (com_token[0] == '}')
855                         break;
856
857                 strcpy (keyname, com_token);
858
859                 // parse value
860                 if (!COM_ParseToken(&data, false))
861                         Host_Error ("ED_ParseEntity: EOF without closing brace");
862
863                 if (com_token[0] == '}')
864                         Host_Error ("ED_ParseEntity: closing brace without data");
865
866                 key = ED_FindGlobal (keyname);
867                 if (!key)
868                 {
869                         Con_DPrintf("'%s' is not a global\n", keyname);
870                         continue;
871                 }
872
873                 if (!ED_ParseEpair(NULL, key, com_token))
874                         Host_Error ("ED_ParseGlobals: parse error");
875         }
876 }
877
878 //============================================================================
879
880
881 /*
882 =============
883 ED_NewString
884 =============
885 */
886 char *ED_NewString (const char *string)
887 {
888         char *new, *new_p;
889         int i,l;
890
891         l = strlen(string) + 1;
892         new = Mem_Alloc(edictstring_mempool, l);
893         new_p = new;
894
895         for (i=0 ; i< l ; i++)
896         {
897                 if (string[i] == '\\' && i < l-1)
898                 {
899                         i++;
900                         if (string[i] == 'n')
901                                 *new_p++ = '\n';
902                         else
903                                 *new_p++ = '\\';
904                 }
905                 else
906                         *new_p++ = string[i];
907         }
908
909         return new;
910 }
911
912
913 /*
914 =============
915 ED_ParseEval
916
917 Can parse either fields or globals
918 returns false if error
919 =============
920 */
921 qboolean ED_ParseEpair(edict_t *ent, ddef_t *key, const char *s)
922 {
923         int i;
924         ddef_t *def;
925         eval_t *val;
926         mfunction_t *func;
927
928         if (ent)
929                 val = (eval_t *)((int *)ent->v + key->ofs);
930         else
931                 val = (eval_t *)((int *)pr_globals + key->ofs);
932         switch (key->type & ~DEF_SAVEGLOBAL)
933         {
934         case ev_string:
935                 val->string = PR_SetString(ED_NewString(s));
936                 break;
937
938         case ev_float:
939                 while (*s && *s <= ' ')
940                         s++;
941                 val->_float = atof(s);
942                 break;
943
944         case ev_vector:
945                 for (i = 0;i < 3;i++)
946                 {
947                         while (*s && *s <= ' ')
948                                 s++;
949                         if (*s)
950                                 val->vector[i] = atof(s);
951                         else
952                                 val->vector[i] = 0;
953                         while (*s > ' ')
954                                 s++;
955                 }
956                 break;
957
958         case ev_entity:
959                 while (*s && *s <= ' ')
960                         s++;
961                 i = atoi(s);
962                 if (i < 0 || i >= MAX_EDICTS)
963                         Con_Printf("ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i)\n", i, MAX_EDICTS);
964                 while (i >= sv.max_edicts)
965                         SV_IncreaseEdicts();
966                 // if SV_IncreaseEdicts was called the base pointer needs to be updated
967                 if (ent)
968                         val = (eval_t *)((int *)ent->v + key->ofs);
969                 val->edict = EDICT_TO_PROG(EDICT_NUM(i));
970                 break;
971
972         case ev_field:
973                 def = ED_FindField(s);
974                 if (!def)
975                 {
976                         Con_DPrintf("ED_ParseEpair: Can't find field %s\n", s);
977                         return false;
978                 }
979                 val->_int = G_INT(def->ofs);
980                 break;
981
982         case ev_function:
983                 func = ED_FindFunction(s);
984                 if (!func)
985                 {
986                         Con_Printf("ED_ParseEpair: Can't find function %s\n", s);
987                         return false;
988                 }
989                 val->function = func - pr_functions;
990                 break;
991
992         default:
993                 Con_Printf("ED_ParseEpair: Unknown key->type %i for key \"%s\"\n", key->type, PR_GetString(key->s_name));
994                 return false;
995         }
996         return true;
997 }
998
999 /*
1000 ====================
1001 ED_ParseEdict
1002
1003 Parses an edict out of the given string, returning the new position
1004 ed should be a properly initialized empty edict.
1005 Used for initial level load and for savegames.
1006 ====================
1007 */
1008 const char *ED_ParseEdict (const char *data, edict_t *ent)
1009 {
1010         ddef_t *key;
1011         qboolean anglehack;
1012         qboolean init;
1013         char keyname[256];
1014         int n;
1015
1016         init = false;
1017
1018 // clear it
1019         if (ent != sv.edicts)   // hack
1020                 memset (ent->v, 0, progs->entityfields * 4);
1021
1022 // go through all the dictionary pairs
1023         while (1)
1024         {
1025         // parse key
1026                 if (!COM_ParseToken(&data, false))
1027                         Host_Error ("ED_ParseEntity: EOF without closing brace");
1028                 if (com_token[0] == '}')
1029                         break;
1030
1031                 // anglehack is to allow QuakeEd to write single scalar angles
1032                 // and allow them to be turned into vectors. (FIXME...)
1033                 anglehack = !strcmp (com_token, "angle");
1034                 if (anglehack)
1035                         strlcpy (com_token, "angles", sizeof (com_token));
1036
1037                 // FIXME: change light to _light to get rid of this hack
1038                 if (!strcmp(com_token, "light"))
1039                         strlcpy (com_token, "light_lev", sizeof (com_token));   // hack for single light def
1040
1041                 strlcpy (keyname, com_token, sizeof (keyname));
1042
1043                 // another hack to fix heynames with trailing spaces
1044                 n = strlen(keyname);
1045                 while (n && keyname[n-1] == ' ')
1046                 {
1047                         keyname[n-1] = 0;
1048                         n--;
1049                 }
1050
1051         // parse value
1052                 if (!COM_ParseToken(&data, false))
1053                         Host_Error ("ED_ParseEntity: EOF without closing brace");
1054
1055                 if (com_token[0] == '}')
1056                         Host_Error ("ED_ParseEntity: closing brace without data");
1057
1058                 init = true;
1059
1060 // keynames with a leading underscore are used for utility comments,
1061 // and are immediately discarded by quake
1062                 if (keyname[0] == '_')
1063                         continue;
1064
1065                 key = ED_FindField (keyname);
1066                 if (!key)
1067                 {
1068                         Con_DPrintf("'%s' is not a field\n", keyname);
1069                         continue;
1070                 }
1071
1072                 if (anglehack)
1073                 {
1074                         char    temp[32];
1075                         strlcpy (temp, com_token, sizeof (temp));
1076                         snprintf (com_token, sizeof (com_token), "0 %s 0", temp);
1077                 }
1078
1079                 if (!ED_ParseEpair(ent, key, com_token))
1080                         Host_Error ("ED_ParseEdict: parse error");
1081         }
1082
1083         if (!init)
1084                 ent->e->free = true;
1085
1086         return data;
1087 }
1088
1089
1090 /*
1091 ================
1092 ED_LoadFromFile
1093
1094 The entities are directly placed in the array, rather than allocated with
1095 ED_Alloc, because otherwise an error loading the map would have entity
1096 number references out of order.
1097
1098 Creates a server's entity / program execution context by
1099 parsing textual entity definitions out of an ent file.
1100
1101 Used for both fresh maps and savegame loads.  A fresh map would also need
1102 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1103 ================
1104 */
1105 void ED_LoadFromFile (const char *data)
1106 {
1107         edict_t *ent;
1108         int parsed, inhibited, spawned, died;
1109         mfunction_t *func;
1110
1111         ent = NULL;
1112         parsed = 0;
1113         inhibited = 0;
1114         spawned = 0;
1115         died = 0;
1116         pr_global_struct->time = sv.time;
1117
1118 // parse ents
1119         while (1)
1120         {
1121 // parse the opening brace
1122                 if (!COM_ParseToken(&data, false))
1123                         break;
1124                 if (com_token[0] != '{')
1125                         Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1126
1127                 if (!ent)
1128                         ent = EDICT_NUM(0);
1129                 else
1130                         ent = ED_Alloc ();
1131                 data = ED_ParseEdict (data, ent);
1132                 parsed++;
1133
1134 // remove things from different skill levels or deathmatch
1135                 if (deathmatch.integer)
1136                 {
1137                         if (((int)ent->v->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1138                         {
1139                                 ED_Free (ent);
1140                                 inhibited++;
1141                                 continue;
1142                         }
1143                 }
1144                 else if ((current_skill == 0 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_EASY  ))
1145                           || (current_skill == 1 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_MEDIUM))
1146                           || (current_skill >= 2 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_HARD  )))
1147                 {
1148                         ED_Free (ent);
1149                         inhibited++;
1150                         continue;
1151                 }
1152
1153 //
1154 // immediately call spawn function
1155 //
1156                 if (!ent->v->classname)
1157                 {
1158                         Con_Print("No classname for:\n");
1159                         ED_Print(ent);
1160                         ED_Free (ent);
1161                         continue;
1162                 }
1163
1164         // look for the spawn function
1165                 func = ED_FindFunction (PR_GetString(ent->v->classname));
1166
1167                 if (!func)
1168                 {
1169                         if (developer.integer) // don't confuse non-developers with errors
1170                         {
1171                                 Con_Print("No spawn function for:\n");
1172                                 ED_Print(ent);
1173                         }
1174                         ED_Free (ent);
1175                         continue;
1176                 }
1177
1178                 pr_global_struct->self = EDICT_TO_PROG(ent);
1179                 PR_ExecuteProgram (func - pr_functions, "QC function spawn is missing");
1180                 spawned++;
1181                 if (ent->e->free)
1182                         died++;
1183         }
1184
1185         Con_DPrintf("%i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", parsed, inhibited, spawned, died, spawned - died);
1186 }
1187
1188
1189 typedef struct dpfield_s
1190 {
1191         int type;
1192         char *string;
1193 }
1194 dpfield_t;
1195
1196 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1197
1198 dpfield_t dpfields[] =
1199 {
1200         {ev_float, "gravity"},
1201         {ev_float, "button3"},
1202         {ev_float, "button4"},
1203         {ev_float, "button5"},
1204         {ev_float, "button6"},
1205         {ev_float, "button7"},
1206         {ev_float, "button8"},
1207         {ev_float, "glow_size"},
1208         {ev_float, "glow_trail"},
1209         {ev_float, "glow_color"},
1210         {ev_float, "items2"},
1211         {ev_float, "scale"},
1212         {ev_float, "alpha"},
1213         {ev_float, "renderamt"},
1214         {ev_float, "rendermode"},
1215         {ev_float, "fullbright"},
1216         {ev_float, "ammo_shells1"},
1217         {ev_float, "ammo_nails1"},
1218         {ev_float, "ammo_lava_nails"},
1219         {ev_float, "ammo_rockets1"},
1220         {ev_float, "ammo_multi_rockets"},
1221         {ev_float, "ammo_cells1"},
1222         {ev_float, "ammo_plasma"},
1223         {ev_float, "idealpitch"},
1224         {ev_float, "pitch_speed"},
1225         {ev_entity, "viewmodelforclient"},
1226         {ev_entity, "nodrawtoclient"},
1227         {ev_entity, "exteriormodeltoclient"},
1228         {ev_entity, "drawonlytoclient"},
1229         {ev_float, "ping"},
1230         {ev_vector, "movement"},
1231         {ev_float, "pmodel"},
1232         {ev_vector, "punchvector"},
1233         {ev_float, "clientcolors"},
1234         {ev_entity, "tag_entity"},
1235         {ev_float, "tag_index"},
1236         {ev_float, "light_lev"},
1237         {ev_vector, "color"},
1238         {ev_float, "style"},
1239         {ev_float, "pflags"}
1240 };
1241
1242 /*
1243 ===============
1244 PR_LoadProgs
1245 ===============
1246 */
1247 extern void PR_Cmd_Reset (void);
1248 void PR_LoadProgs (void)
1249 {
1250         int i;
1251         dstatement_t *st;
1252         ddef_t *infielddefs;
1253         dfunction_t *dfunctions;
1254
1255 // flush the non-C variable lookup cache
1256         for (i=0 ; i<GEFV_CACHESIZE ; i++)
1257                 gefvCache[i].field[0] = 0;
1258
1259         Mem_EmptyPool(progs_mempool);
1260         Mem_EmptyPool(edictstring_mempool);
1261
1262         progs = (dprograms_t *)FS_LoadFile ("progs.dat", progs_mempool, false);
1263         if (!progs)
1264                 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1265
1266         Con_DPrintf("Programs occupy %iK.\n", fs_filesize/1024);
1267
1268         pr_crc = CRC_Block((qbyte *)progs, fs_filesize);
1269
1270 // byte swap the header
1271         for (i = 0;i < (int) sizeof(*progs) / 4;i++)
1272                 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1273
1274         if (progs->version != PROG_VERSION)
1275                 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1276         if (progs->crc != PROGHEADER_CRC && progs->crc != 32401) // tenebrae crc also allowed
1277                 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1278
1279         //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1280         dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1281         pr_strings = (char *)progs + progs->ofs_strings;
1282         pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1283
1284         // we need to expand the fielddefs list to include all the engine fields,
1285         // so allocate a new place for it
1286         infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1287         pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1288
1289         pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1290
1291         // moved edict_size calculation down below field adding code
1292
1293         pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1294         pr_globals = (float *)pr_global_struct;
1295
1296 // byte swap the lumps
1297         for (i=0 ; i<progs->numstatements ; i++)
1298         {
1299                 pr_statements[i].op = LittleShort(pr_statements[i].op);
1300                 pr_statements[i].a = LittleShort(pr_statements[i].a);
1301                 pr_statements[i].b = LittleShort(pr_statements[i].b);
1302                 pr_statements[i].c = LittleShort(pr_statements[i].c);
1303         }
1304
1305         pr_functions = Mem_Alloc(progs_mempool, sizeof(mfunction_t) * progs->numfunctions);
1306         for (i = 0;i < progs->numfunctions;i++)
1307         {
1308                 pr_functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1309                 pr_functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1310                 pr_functions[i].s_name = LittleLong (dfunctions[i].s_name);
1311                 pr_functions[i].s_file = LittleLong (dfunctions[i].s_file);
1312                 pr_functions[i].numparms = LittleLong (dfunctions[i].numparms);
1313                 pr_functions[i].locals = LittleLong (dfunctions[i].locals);
1314                 memcpy(pr_functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1315         }
1316
1317         for (i=0 ; i<progs->numglobaldefs ; i++)
1318         {
1319                 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1320                 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1321                 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1322         }
1323
1324         // copy the progs fields to the new fields list
1325         for (i = 0;i < progs->numfielddefs;i++)
1326         {
1327                 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1328                 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1329                         Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1330                 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1331                 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1332         }
1333
1334         // append the darkplaces fields
1335         for (i = 0;i < (int) DPFIELDS;i++)
1336         {
1337                 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1338                 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1339                 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1340                 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1341                         progs->entityfields += 3;
1342                 else
1343                         progs->entityfields++;
1344                 progs->numfielddefs++;
1345         }
1346
1347         for (i=0 ; i<progs->numglobals ; i++)
1348                 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1349
1350         // moved edict_size calculation down here, below field adding code
1351         // LordHavoc: this no longer includes the edict_t header
1352         pr_edict_size = progs->entityfields * 4;
1353         pr_edictareasize = pr_edict_size * MAX_EDICTS;
1354
1355         // LordHavoc: bounds check anything static
1356         for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1357         {
1358                 switch (st->op)
1359                 {
1360                 case OP_IF:
1361                 case OP_IFNOT:
1362                         if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1363                                 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1364                         break;
1365                 case OP_GOTO:
1366                         if (st->a + i < 0 || st->a + i >= progs->numstatements)
1367                                 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1368                         break;
1369                 // global global global
1370                 case OP_ADD_F:
1371                 case OP_ADD_V:
1372                 case OP_SUB_F:
1373                 case OP_SUB_V:
1374                 case OP_MUL_F:
1375                 case OP_MUL_V:
1376                 case OP_MUL_FV:
1377                 case OP_MUL_VF:
1378                 case OP_DIV_F:
1379                 case OP_BITAND:
1380                 case OP_BITOR:
1381                 case OP_GE:
1382                 case OP_LE:
1383                 case OP_GT:
1384                 case OP_LT:
1385                 case OP_AND:
1386                 case OP_OR:
1387                 case OP_EQ_F:
1388                 case OP_EQ_V:
1389                 case OP_EQ_S:
1390                 case OP_EQ_E:
1391                 case OP_EQ_FNC:
1392                 case OP_NE_F:
1393                 case OP_NE_V:
1394                 case OP_NE_S:
1395                 case OP_NE_E:
1396                 case OP_NE_FNC:
1397                 case OP_ADDRESS:
1398                 case OP_LOAD_F:
1399                 case OP_LOAD_FLD:
1400                 case OP_LOAD_ENT:
1401                 case OP_LOAD_S:
1402                 case OP_LOAD_FNC:
1403                 case OP_LOAD_V:
1404                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1405                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1406                         break;
1407                 // global none global
1408                 case OP_NOT_F:
1409                 case OP_NOT_V:
1410                 case OP_NOT_S:
1411                 case OP_NOT_FNC:
1412                 case OP_NOT_ENT:
1413                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1414                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1415                         break;
1416                 // 2 globals
1417                 case OP_STOREP_F:
1418                 case OP_STOREP_ENT:
1419                 case OP_STOREP_FLD:
1420                 case OP_STOREP_S:
1421                 case OP_STOREP_FNC:
1422                 case OP_STORE_F:
1423                 case OP_STORE_ENT:
1424                 case OP_STORE_FLD:
1425                 case OP_STORE_S:
1426                 case OP_STORE_FNC:
1427                 case OP_STATE:
1428                 case OP_STOREP_V:
1429                 case OP_STORE_V:
1430                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1431                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1432                         break;
1433                 // 1 global
1434                 case OP_CALL0:
1435                 case OP_CALL1:
1436                 case OP_CALL2:
1437                 case OP_CALL3:
1438                 case OP_CALL4:
1439                 case OP_CALL5:
1440                 case OP_CALL6:
1441                 case OP_CALL7:
1442                 case OP_CALL8:
1443                 case OP_DONE:
1444                 case OP_RETURN:
1445                         if ((unsigned short) st->a >= progs->numglobals)
1446                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1447                         break;
1448                 default:
1449                         Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1450                         break;
1451                 }
1452         }
1453
1454         FindEdictFieldOffsets(); // LordHavoc: update field offset list
1455         PR_Execute_ProgsLoaded();
1456         PR_Cmd_Reset();
1457 }
1458
1459
1460 void PR_Fields_f (void)
1461 {
1462         int i, j, ednum, used, usedamount;
1463         int *counts;
1464         char tempstring[5000], tempstring2[260], *name;
1465         edict_t *ed;
1466         ddef_t *d;
1467         int *v;
1468         if (!sv.active)
1469         {
1470                 Con_Print("no progs loaded\n");
1471                 return;
1472         }
1473         counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1474         for (ednum = 0;ednum < sv.max_edicts;ednum++)
1475         {
1476                 ed = EDICT_NUM(ednum);
1477                 if (ed->e->free)
1478                         continue;
1479                 for (i = 1;i < progs->numfielddefs;i++)
1480                 {
1481                         d = &pr_fielddefs[i];
1482                         name = PR_GetString(d->s_name);
1483                         if (name[strlen(name)-2] == '_')
1484                                 continue;       // skip _x, _y, _z vars
1485                         v = (int *)((char *)ed->v + d->ofs*4);
1486                         // if the value is still all 0, skip the field
1487                         for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1488                         {
1489                                 if (v[j])
1490                                 {
1491                                         counts[i]++;
1492                                         break;
1493                                 }
1494                         }
1495                 }
1496         }
1497         used = 0;
1498         usedamount = 0;
1499         tempstring[0] = 0;
1500         for (i = 0;i < progs->numfielddefs;i++)
1501         {
1502                 d = &pr_fielddefs[i];
1503                 name = PR_GetString(d->s_name);
1504                 if (name[strlen(name)-2] == '_')
1505                         continue;       // skip _x, _y, _z vars
1506                 switch(d->type & ~DEF_SAVEGLOBAL)
1507                 {
1508                 case ev_string:
1509                         strlcat (tempstring, "string   ", sizeof (tempstring));
1510                         break;
1511                 case ev_entity:
1512                         strlcat (tempstring, "entity   ", sizeof (tempstring));
1513                         break;
1514                 case ev_function:
1515                         strlcat (tempstring, "function ", sizeof (tempstring));
1516                         break;
1517                 case ev_field:
1518                         strlcat (tempstring, "field    ", sizeof (tempstring));
1519                         break;
1520                 case ev_void:
1521                         strlcat (tempstring, "void     ", sizeof (tempstring));
1522                         break;
1523                 case ev_float:
1524                         strlcat (tempstring, "float    ", sizeof (tempstring));
1525                         break;
1526                 case ev_vector:
1527                         strlcat (tempstring, "vector   ", sizeof (tempstring));
1528                         break;
1529                 case ev_pointer:
1530                         strlcat (tempstring, "pointer  ", sizeof (tempstring));
1531                         break;
1532                 default:
1533                         snprintf (tempstring2, sizeof (tempstring2), "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1534                         strlcat (tempstring, tempstring2, sizeof (tempstring));
1535                         break;
1536                 }
1537                 if (strlen(name) > 256)
1538                 {
1539                         memcpy(tempstring2, name, 256);
1540                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1541                         tempstring2[259] = 0;
1542                         name = tempstring2;
1543                 }
1544                 strcat (tempstring, name);
1545                 for (j = strlen(name);j < 25;j++)
1546                         strcat(tempstring, " ");
1547                 snprintf (tempstring2, sizeof (tempstring2), "%5d", counts[i]);
1548                 strlcat (tempstring, tempstring2, sizeof (tempstring));
1549                 strlcat (tempstring, "\n", sizeof (tempstring));
1550                 if (strlen(tempstring) >= 4096)
1551                 {
1552                         Con_Print(tempstring);
1553                         tempstring[0] = 0;
1554                 }
1555                 if (counts[i])
1556                 {
1557                         used++;
1558                         usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1559                 }
1560         }
1561         Mem_Free(counts);
1562         Con_Printf("%i entity fields (%i in use), totalling %i bytes per edict (%i in use), %i edicts allocated, %i bytes total spent on edict fields (%i needed)\n", progs->entityfields, used, progs->entityfields * 4, usedamount * 4, sv.max_edicts, progs->entityfields * 4 * sv.max_edicts, usedamount * 4 * sv.max_edicts);
1563 }
1564
1565 void PR_Globals_f (void)
1566 {
1567         int i;
1568         if (!sv.active)
1569         {
1570                 Con_Print("no progs loaded\n");
1571                 return;
1572         }
1573         for (i = 0;i < progs->numglobaldefs;i++)
1574                 Con_Printf("%s\n", PR_GetString(pr_globaldefs[i].s_name));
1575         Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1576 }
1577
1578 /*
1579 ===============
1580 PR_Init
1581 ===============
1582 */
1583 extern void PR_Cmd_Init(void);
1584 void PR_Init (void)
1585 {
1586         Cmd_AddCommand ("edict", ED_PrintEdict_f);
1587         Cmd_AddCommand ("edicts", ED_PrintEdicts);
1588         Cmd_AddCommand ("edictcount", ED_Count);
1589         Cmd_AddCommand ("edictset", ED_EdictSet_f);
1590         Cmd_AddCommand ("profile", PR_Profile_f);
1591         Cmd_AddCommand ("pr_fields", PR_Fields_f);
1592         Cmd_AddCommand ("pr_globals", PR_Globals_f);
1593         Cvar_RegisterVariable (&pr_checkextension);
1594         Cvar_RegisterVariable (&nomonsters);
1595         Cvar_RegisterVariable (&gamecfg);
1596         Cvar_RegisterVariable (&scratch1);
1597         Cvar_RegisterVariable (&scratch2);
1598         Cvar_RegisterVariable (&scratch3);
1599         Cvar_RegisterVariable (&scratch4);
1600         Cvar_RegisterVariable (&savedgamecfg);
1601         Cvar_RegisterVariable (&saved1);
1602         Cvar_RegisterVariable (&saved2);
1603         Cvar_RegisterVariable (&saved3);
1604         Cvar_RegisterVariable (&saved4);
1605         // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1606         Cvar_RegisterVariable (&decors);
1607         // LordHavoc: Nehahra uses these to pass data around cutscene demos
1608         if (gamemode == GAME_NEHAHRA)
1609         {
1610                 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1611                 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1612                 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1613                 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1614                 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1615                 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1616                 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1617                 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1618                 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1619                 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1620         }
1621         Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1622         // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1623         Cvar_RegisterVariable (&pr_boundscheck);
1624         Cvar_RegisterVariable (&pr_traceqc);
1625
1626         progs_mempool = Mem_AllocPool("progs.dat", 0, NULL);
1627         edictstring_mempool = Mem_AllocPool("edict strings", 0, NULL);
1628
1629         PR_Cmd_Init();
1630 }
1631
1632 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1633 edict_t *EDICT_NUM_ERROR(int n, char *filename, int fileline)
1634 {
1635         Host_Error ("EDICT_NUM: bad number %i (called at %s:%i)", n, filename, fileline);
1636         return NULL;
1637 }
1638
1639 /*
1640 int NUM_FOR_EDICT_ERROR(edict_t *e)
1641 {
1642         Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1643         return 0;
1644 }
1645
1646 int NUM_FOR_EDICT(edict_t *e)
1647 {
1648         int n;
1649         n = e - sv.edicts;
1650         if ((unsigned int)n >= MAX_EDICTS)
1651                 Host_Error ("NUM_FOR_EDICT: bad pointer");
1652         return n;
1653 }
1654
1655 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1656 //{
1657 //      return e - sv.edicts;
1658 //}
1659
1660 //#define       EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1661 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1662 int EDICT_TO_PROG(edict_t *e)
1663 {
1664         int n;
1665         n = e - sv.edicts;
1666         if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1667                 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1668         return n;// EXPERIMENTAL
1669         //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1670 }
1671 edict_t *PROG_TO_EDICT(int n)
1672 {
1673         if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1674                 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1675         return sv.edicts + n; // EXPERIMENTAL
1676         //return sv.edicts + ((n) / (progs->entityfields * 4));
1677 }
1678 */
1679