]> icculus.org git repositories - divverent/darkplaces.git/blob - pr_edict.c
fixed noclipping rendering nothing (there was no vis update)
[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                 snprintf (line, sizeof (line), "%s", PR_GetString(val->string));
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                 snprintf (line, sizeof (line), "%s", PR_GetString(f->s_name));
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_Printf ("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                         strncpy(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                         strncpy(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_Printf("%s", tempstring);
640                         tempstring[0] = 0;
641                 }
642         }
643         if (tempstring[0])
644                 Con_Printf("%s", 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_Printf (f, "{\n");
663
664         if (ed->e->free)
665         {
666                 FS_Printf (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_Printf (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 >= sv.num_edicts)
728         {
729                 Con_Printf("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_Printf (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_Printf (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_Printf("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                                 break;
951                         val->vector[i] = atof(s);
952                         while (*s > ' ')
953                                 s++;
954                         if (!*s)
955                                 break;
956                 }
957                 break;
958
959         case ev_entity:
960                 while (*s && *s <= ' ')
961                         s++;
962                 i = atoi(s);
963                 if (i < 0 || i >= MAX_EDICTS)
964                         Con_Printf("ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i)\n", i, MAX_EDICTS);
965                 while (i >= sv.max_edicts)
966                         SV_IncreaseEdicts();
967                 // if SV_IncreaseEdicts was called the base pointer needs to be updated
968                 if (ent)
969                         val = (eval_t *)((int *)ent->v + key->ofs);
970                 val->edict = EDICT_TO_PROG(EDICT_NUM(i));
971                 break;
972
973         case ev_field:
974                 def = ED_FindField(s);
975                 if (!def)
976                 {
977                         Con_DPrintf("ED_ParseEpair: Can't find field %s\n", s);
978                         return false;
979                 }
980                 val->_int = G_INT(def->ofs);
981                 break;
982
983         case ev_function:
984                 func = ED_FindFunction(s);
985                 if (!func)
986                 {
987                         Con_Printf ("ED_ParseEpair: Can't find function %s\n", s);
988                         return false;
989                 }
990                 val->function = func - pr_functions;
991                 break;
992
993         default:
994                 Con_Printf("ED_ParseEpair: Unknown key->type %i for key \"%s\"\n", key->type, PR_GetString(key->s_name));
995                 return false;
996         }
997         return true;
998 }
999
1000 /*
1001 ====================
1002 ED_ParseEdict
1003
1004 Parses an edict out of the given string, returning the new position
1005 ed should be a properly initialized empty edict.
1006 Used for initial level load and for savegames.
1007 ====================
1008 */
1009 const char *ED_ParseEdict (const char *data, edict_t *ent)
1010 {
1011         ddef_t *key;
1012         qboolean anglehack;
1013         qboolean init;
1014         char keyname[256];
1015         int n;
1016
1017         init = false;
1018
1019 // clear it
1020         if (ent != sv.edicts)   // hack
1021                 memset (ent->v, 0, progs->entityfields * 4);
1022
1023 // go through all the dictionary pairs
1024         while (1)
1025         {
1026         // parse key
1027                 if (!COM_ParseToken(&data, false))
1028                         Host_Error ("ED_ParseEntity: EOF without closing brace");
1029                 if (com_token[0] == '}')
1030                         break;
1031
1032                 // anglehack is to allow QuakeEd to write single scalar angles
1033                 // and allow them to be turned into vectors. (FIXME...)
1034                 anglehack = !strcmp (com_token, "angle");
1035                 if (anglehack)
1036                         strlcpy (com_token, "angles", sizeof (com_token));
1037
1038                 // FIXME: change light to _light to get rid of this hack
1039                 if (!strcmp(com_token, "light"))
1040                         strlcpy (com_token, "light_lev", sizeof (com_token));   // hack for single light def
1041
1042                 strlcpy (keyname, com_token, sizeof (keyname));
1043
1044                 // another hack to fix heynames with trailing spaces
1045                 n = strlen(keyname);
1046                 while (n && keyname[n-1] == ' ')
1047                 {
1048                         keyname[n-1] = 0;
1049                         n--;
1050                 }
1051
1052         // parse value
1053                 if (!COM_ParseToken(&data, false))
1054                         Host_Error ("ED_ParseEntity: EOF without closing brace");
1055
1056                 if (com_token[0] == '}')
1057                         Host_Error ("ED_ParseEntity: closing brace without data");
1058
1059                 init = true;
1060
1061 // keynames with a leading underscore are used for utility comments,
1062 // and are immediately discarded by quake
1063                 if (keyname[0] == '_')
1064                         continue;
1065
1066                 key = ED_FindField (keyname);
1067                 if (!key)
1068                 {
1069                         Con_DPrintf ("'%s' is not a field\n", keyname);
1070                         continue;
1071                 }
1072
1073                 if (anglehack)
1074                 {
1075                         char    temp[32];
1076                         strlcpy (temp, com_token, sizeof (temp));
1077                         snprintf (com_token, sizeof (com_token), "0 %s 0", temp);
1078                 }
1079
1080                 if (!ED_ParseEpair(ent, key, com_token))
1081                         Host_Error ("ED_ParseEdict: parse error");
1082         }
1083
1084         if (!init)
1085                 ent->e->free = true;
1086
1087         return data;
1088 }
1089
1090
1091 /*
1092 ================
1093 ED_LoadFromFile
1094
1095 The entities are directly placed in the array, rather than allocated with
1096 ED_Alloc, because otherwise an error loading the map would have entity
1097 number references out of order.
1098
1099 Creates a server's entity / program execution context by
1100 parsing textual entity definitions out of an ent file.
1101
1102 Used for both fresh maps and savegame loads.  A fresh map would also need
1103 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1104 ================
1105 */
1106 void ED_LoadFromFile (const char *data)
1107 {
1108         edict_t *ent;
1109         int parsed, inhibited, spawned, died;
1110         mfunction_t *func;
1111
1112         ent = NULL;
1113         parsed = 0;
1114         inhibited = 0;
1115         spawned = 0;
1116         died = 0;
1117         pr_global_struct->time = sv.time;
1118
1119 // parse ents
1120         while (1)
1121         {
1122 // parse the opening brace
1123                 if (!COM_ParseToken(&data, false))
1124                         break;
1125                 if (com_token[0] != '{')
1126                         Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1127
1128                 if (!ent)
1129                         ent = EDICT_NUM(0);
1130                 else
1131                         ent = ED_Alloc ();
1132                 data = ED_ParseEdict (data, ent);
1133                 parsed++;
1134
1135 // remove things from different skill levels or deathmatch
1136                 if (deathmatch.integer)
1137                 {
1138                         if (((int)ent->v->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1139                         {
1140                                 ED_Free (ent);
1141                                 inhibited++;
1142                                 continue;
1143                         }
1144                 }
1145                 else if ((current_skill == 0 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_EASY  ))
1146                           || (current_skill == 1 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_MEDIUM))
1147                           || (current_skill >= 2 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_HARD  )))
1148                 {
1149                         ED_Free (ent);
1150                         inhibited++;
1151                         continue;
1152                 }
1153
1154 //
1155 // immediately call spawn function
1156 //
1157                 if (!ent->v->classname)
1158                 {
1159                         Con_Printf ("No classname for:\n");
1160                         ED_Print (ent);
1161                         ED_Free (ent);
1162                         continue;
1163                 }
1164
1165         // look for the spawn function
1166                 func = ED_FindFunction (PR_GetString(ent->v->classname));
1167
1168                 if (!func)
1169                 {
1170                         if (developer.integer) // don't confuse non-developers with errors
1171                         {
1172                                 Con_Printf ("No spawn function for:\n");
1173                                 ED_Print (ent);
1174                         }
1175                         ED_Free (ent);
1176                         continue;
1177                 }
1178
1179                 pr_global_struct->self = EDICT_TO_PROG(ent);
1180                 PR_ExecuteProgram (func - pr_functions, "");
1181                 spawned++;
1182                 if (ent->e->free)
1183                         died++;
1184         }
1185
1186         Con_DPrintf ("%i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", parsed, inhibited, spawned, died, spawned - died);
1187 }
1188
1189
1190 typedef struct dpfield_s
1191 {
1192         int type;
1193         char *string;
1194 }
1195 dpfield_t;
1196
1197 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1198
1199 dpfield_t dpfields[] =
1200 {
1201         {ev_float, "gravity"},
1202         {ev_float, "button3"},
1203         {ev_float, "button4"},
1204         {ev_float, "button5"},
1205         {ev_float, "button6"},
1206         {ev_float, "button7"},
1207         {ev_float, "button8"},
1208         {ev_float, "glow_size"},
1209         {ev_float, "glow_trail"},
1210         {ev_float, "glow_color"},
1211         {ev_float, "items2"},
1212         {ev_float, "scale"},
1213         {ev_float, "alpha"},
1214         {ev_float, "renderamt"},
1215         {ev_float, "rendermode"},
1216         {ev_float, "fullbright"},
1217         {ev_float, "ammo_shells1"},
1218         {ev_float, "ammo_nails1"},
1219         {ev_float, "ammo_lava_nails"},
1220         {ev_float, "ammo_rockets1"},
1221         {ev_float, "ammo_multi_rockets"},
1222         {ev_float, "ammo_cells1"},
1223         {ev_float, "ammo_plasma"},
1224         {ev_float, "idealpitch"},
1225         {ev_float, "pitch_speed"},
1226         {ev_entity, "viewmodelforclient"},
1227         {ev_entity, "nodrawtoclient"},
1228         {ev_entity, "exteriormodeltoclient"},
1229         {ev_entity, "drawonlytoclient"},
1230         {ev_float, "ping"},
1231         {ev_vector, "movement"},
1232         {ev_float, "pmodel"},
1233         {ev_vector, "punchvector"},
1234         {ev_float, "clientcolors"},
1235         {ev_entity, "tag_entity"},
1236         {ev_float, "tag_index"},
1237         {ev_float, "light_lev"},
1238         {ev_float, "color"},
1239         {ev_float, "style"},
1240         {ev_float, "pflags"}
1241 };
1242
1243 /*
1244 ===============
1245 PR_LoadProgs
1246 ===============
1247 */
1248 extern void PR_Cmd_Reset (void);
1249 void PR_LoadProgs (void)
1250 {
1251         int i;
1252         dstatement_t *st;
1253         ddef_t *infielddefs;
1254         void *temp;
1255         dfunction_t *dfunctions;
1256
1257 // flush the non-C variable lookup cache
1258         for (i=0 ; i<GEFV_CACHESIZE ; i++)
1259                 gefvCache[i].field[0] = 0;
1260
1261         Mem_EmptyPool(progs_mempool);
1262         Mem_EmptyPool(edictstring_mempool);
1263
1264         temp = FS_LoadFile ("progs.dat", false);
1265         if (!temp)
1266                 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1267
1268         progs = (dprograms_t *)Mem_Alloc(progs_mempool, fs_filesize);
1269
1270         memcpy(progs, temp, fs_filesize);
1271         Mem_Free(temp);
1272
1273         Con_DPrintf ("Programs occupy %iK.\n", fs_filesize/1024);
1274
1275         pr_crc = CRC_Block((qbyte *)progs, fs_filesize);
1276
1277 // byte swap the header
1278         for (i = 0;i < (int) sizeof(*progs) / 4;i++)
1279                 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1280
1281         if (progs->version != PROG_VERSION)
1282                 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1283         if (progs->crc != PROGHEADER_CRC && progs->crc != 32401) // tenebrae crc also allowed
1284                 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1285
1286         //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1287         dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1288         pr_strings = (char *)progs + progs->ofs_strings;
1289         pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1290
1291         // we need to expand the fielddefs list to include all the engine fields,
1292         // so allocate a new place for it
1293         infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1294         pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1295
1296         pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1297
1298         // moved edict_size calculation down below field adding code
1299
1300         pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1301         pr_globals = (float *)pr_global_struct;
1302
1303 // byte swap the lumps
1304         for (i=0 ; i<progs->numstatements ; i++)
1305         {
1306                 pr_statements[i].op = LittleShort(pr_statements[i].op);
1307                 pr_statements[i].a = LittleShort(pr_statements[i].a);
1308                 pr_statements[i].b = LittleShort(pr_statements[i].b);
1309                 pr_statements[i].c = LittleShort(pr_statements[i].c);
1310         }
1311
1312         pr_functions = Mem_Alloc(progs_mempool, sizeof(mfunction_t) * progs->numfunctions);
1313         for (i = 0;i < progs->numfunctions;i++)
1314         {
1315                 pr_functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1316                 pr_functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1317                 pr_functions[i].s_name = LittleLong (dfunctions[i].s_name);
1318                 pr_functions[i].s_file = LittleLong (dfunctions[i].s_file);
1319                 pr_functions[i].numparms = LittleLong (dfunctions[i].numparms);
1320                 pr_functions[i].locals = LittleLong (dfunctions[i].locals);
1321                 memcpy(pr_functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1322         }
1323
1324         for (i=0 ; i<progs->numglobaldefs ; i++)
1325         {
1326                 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1327                 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1328                 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1329         }
1330
1331         // copy the progs fields to the new fields list
1332         for (i = 0;i < progs->numfielddefs;i++)
1333         {
1334                 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1335                 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1336                         Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1337                 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1338                 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1339         }
1340
1341         // append the darkplaces fields
1342         for (i = 0;i < (int) DPFIELDS;i++)
1343         {
1344                 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1345                 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1346                 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1347                 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1348                         progs->entityfields += 3;
1349                 else
1350                         progs->entityfields++;
1351                 progs->numfielddefs++;
1352         }
1353
1354         for (i=0 ; i<progs->numglobals ; i++)
1355                 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1356
1357         // moved edict_size calculation down here, below field adding code
1358         // LordHavoc: this no longer includes the edict_t header
1359         pr_edict_size = progs->entityfields * 4;
1360         pr_edictareasize = pr_edict_size * MAX_EDICTS;
1361
1362         // LordHavoc: bounds check anything static
1363         for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1364         {
1365                 switch (st->op)
1366                 {
1367                 case OP_IF:
1368                 case OP_IFNOT:
1369                         if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1370                                 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1371                         break;
1372                 case OP_GOTO:
1373                         if (st->a + i < 0 || st->a + i >= progs->numstatements)
1374                                 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1375                         break;
1376                 // global global global
1377                 case OP_ADD_F:
1378                 case OP_ADD_V:
1379                 case OP_SUB_F:
1380                 case OP_SUB_V:
1381                 case OP_MUL_F:
1382                 case OP_MUL_V:
1383                 case OP_MUL_FV:
1384                 case OP_MUL_VF:
1385                 case OP_DIV_F:
1386                 case OP_BITAND:
1387                 case OP_BITOR:
1388                 case OP_GE:
1389                 case OP_LE:
1390                 case OP_GT:
1391                 case OP_LT:
1392                 case OP_AND:
1393                 case OP_OR:
1394                 case OP_EQ_F:
1395                 case OP_EQ_V:
1396                 case OP_EQ_S:
1397                 case OP_EQ_E:
1398                 case OP_EQ_FNC:
1399                 case OP_NE_F:
1400                 case OP_NE_V:
1401                 case OP_NE_S:
1402                 case OP_NE_E:
1403                 case OP_NE_FNC:
1404                 case OP_ADDRESS:
1405                 case OP_LOAD_F:
1406                 case OP_LOAD_FLD:
1407                 case OP_LOAD_ENT:
1408                 case OP_LOAD_S:
1409                 case OP_LOAD_FNC:
1410                 case OP_LOAD_V:
1411                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1412                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1413                         break;
1414                 // global none global
1415                 case OP_NOT_F:
1416                 case OP_NOT_V:
1417                 case OP_NOT_S:
1418                 case OP_NOT_FNC:
1419                 case OP_NOT_ENT:
1420                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1421                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1422                         break;
1423                 // 2 globals
1424                 case OP_STOREP_F:
1425                 case OP_STOREP_ENT:
1426                 case OP_STOREP_FLD:
1427                 case OP_STOREP_S:
1428                 case OP_STOREP_FNC:
1429                 case OP_STORE_F:
1430                 case OP_STORE_ENT:
1431                 case OP_STORE_FLD:
1432                 case OP_STORE_S:
1433                 case OP_STORE_FNC:
1434                 case OP_STATE:
1435                 case OP_STOREP_V:
1436                 case OP_STORE_V:
1437                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1438                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1439                         break;
1440                 // 1 global
1441                 case OP_CALL0:
1442                 case OP_CALL1:
1443                 case OP_CALL2:
1444                 case OP_CALL3:
1445                 case OP_CALL4:
1446                 case OP_CALL5:
1447                 case OP_CALL6:
1448                 case OP_CALL7:
1449                 case OP_CALL8:
1450                 case OP_DONE:
1451                 case OP_RETURN:
1452                         if ((unsigned short) st->a >= progs->numglobals)
1453                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1454                         break;
1455                 default:
1456                         Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1457                         break;
1458                 }
1459         }
1460
1461         FindEdictFieldOffsets(); // LordHavoc: update field offset list
1462         PR_Execute_ProgsLoaded();
1463         PR_Cmd_Reset();
1464 }
1465
1466
1467 void PR_Fields_f (void)
1468 {
1469         int i, j, ednum, used, usedamount;
1470         int *counts;
1471         char tempstring[5000], tempstring2[260], *name;
1472         edict_t *ed;
1473         ddef_t *d;
1474         int *v;
1475         if (!sv.active)
1476         {
1477                 Con_Printf("no progs loaded\n");
1478                 return;
1479         }
1480         counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1481         for (ednum = 0;ednum < sv.max_edicts;ednum++)
1482         {
1483                 ed = EDICT_NUM(ednum);
1484                 if (ed->e->free)
1485                         continue;
1486                 for (i = 1;i < progs->numfielddefs;i++)
1487                 {
1488                         d = &pr_fielddefs[i];
1489                         name = PR_GetString(d->s_name);
1490                         if (name[strlen(name)-2] == '_')
1491                                 continue;       // skip _x, _y, _z vars
1492                         v = (int *)((char *)ed->v + d->ofs*4);
1493                         // if the value is still all 0, skip the field
1494                         for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1495                         {
1496                                 if (v[j])
1497                                 {
1498                                         counts[i]++;
1499                                         break;
1500                                 }
1501                         }
1502                 }
1503         }
1504         used = 0;
1505         usedamount = 0;
1506         tempstring[0] = 0;
1507         for (i = 0;i < progs->numfielddefs;i++)
1508         {
1509                 d = &pr_fielddefs[i];
1510                 name = PR_GetString(d->s_name);
1511                 if (name[strlen(name)-2] == '_')
1512                         continue;       // skip _x, _y, _z vars
1513                 switch(d->type & ~DEF_SAVEGLOBAL)
1514                 {
1515                 case ev_string:
1516                         strlcat (tempstring, "string   ", sizeof (tempstring));
1517                         break;
1518                 case ev_entity:
1519                         strlcat (tempstring, "entity   ", sizeof (tempstring));
1520                         break;
1521                 case ev_function:
1522                         strlcat (tempstring, "function ", sizeof (tempstring));
1523                         break;
1524                 case ev_field:
1525                         strlcat (tempstring, "field    ", sizeof (tempstring));
1526                         break;
1527                 case ev_void:
1528                         strlcat (tempstring, "void     ", sizeof (tempstring));
1529                         break;
1530                 case ev_float:
1531                         strlcat (tempstring, "float    ", sizeof (tempstring));
1532                         break;
1533                 case ev_vector:
1534                         strlcat (tempstring, "vector   ", sizeof (tempstring));
1535                         break;
1536                 case ev_pointer:
1537                         strlcat (tempstring, "pointer  ", sizeof (tempstring));
1538                         break;
1539                 default:
1540                         snprintf (tempstring2, sizeof (tempstring2), "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1541                         strlcat (tempstring, tempstring2, sizeof (tempstring));
1542                         break;
1543                 }
1544                 if (strlen(name) > 256)
1545                 {
1546                         strncpy(tempstring2, name, 256);
1547                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1548                         tempstring2[259] = 0;
1549                         name = tempstring2;
1550                 }
1551                 strcat (tempstring, name);
1552                 for (j = strlen(name);j < 25;j++)
1553                         strcat(tempstring, " ");
1554                 snprintf (tempstring2, sizeof (tempstring2), "%5d", counts[i]);
1555                 strlcat (tempstring, tempstring2, sizeof (tempstring));
1556                 strlcat (tempstring, "\n", sizeof (tempstring));
1557                 if (strlen(tempstring) >= 4096)
1558                 {
1559                         Con_Printf("%s", tempstring);
1560                         tempstring[0] = 0;
1561                 }
1562                 if (counts[i])
1563                 {
1564                         used++;
1565                         usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1566                 }
1567         }
1568         Mem_Free(counts);
1569         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);
1570 }
1571
1572 void PR_Globals_f (void)
1573 {
1574         int i;
1575         if (!sv.active)
1576         {
1577                 Con_Printf("no progs loaded\n");
1578                 return;
1579         }
1580         for (i = 0;i < progs->numglobaldefs;i++)
1581                 Con_Printf("%s\n", PR_GetString(pr_globaldefs[i].s_name));
1582         Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1583 }
1584
1585 /*
1586 ===============
1587 PR_Init
1588 ===============
1589 */
1590 extern void PR_Cmd_Init(void);
1591 void PR_Init (void)
1592 {
1593         Cmd_AddCommand ("edict", ED_PrintEdict_f);
1594         Cmd_AddCommand ("edicts", ED_PrintEdicts);
1595         Cmd_AddCommand ("edictcount", ED_Count);
1596         Cmd_AddCommand ("edictset", ED_EdictSet_f);
1597         Cmd_AddCommand ("profile", PR_Profile_f);
1598         Cmd_AddCommand ("pr_fields", PR_Fields_f);
1599         Cmd_AddCommand ("pr_globals", PR_Globals_f);
1600         Cvar_RegisterVariable (&pr_checkextension);
1601         Cvar_RegisterVariable (&nomonsters);
1602         Cvar_RegisterVariable (&gamecfg);
1603         Cvar_RegisterVariable (&scratch1);
1604         Cvar_RegisterVariable (&scratch2);
1605         Cvar_RegisterVariable (&scratch3);
1606         Cvar_RegisterVariable (&scratch4);
1607         Cvar_RegisterVariable (&savedgamecfg);
1608         Cvar_RegisterVariable (&saved1);
1609         Cvar_RegisterVariable (&saved2);
1610         Cvar_RegisterVariable (&saved3);
1611         Cvar_RegisterVariable (&saved4);
1612         // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1613         Cvar_RegisterVariable (&decors);
1614         // LordHavoc: Nehahra uses these to pass data around cutscene demos
1615         if (gamemode == GAME_NEHAHRA)
1616         {
1617                 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1618                 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1619                 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1620                 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1621                 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1622                 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1623                 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1624                 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1625                 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1626                 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1627         }
1628         Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1629         // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1630         Cvar_RegisterVariable (&pr_boundscheck);
1631         Cvar_RegisterVariable (&pr_traceqc);
1632
1633         progs_mempool = Mem_AllocPool("progs.dat");
1634         edictstring_mempool = Mem_AllocPool("edict strings");
1635
1636         PR_Cmd_Init();
1637 }
1638
1639 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1640 edict_t *EDICT_NUM_ERROR(int n, char *filename, int fileline)
1641 {
1642         Host_Error ("EDICT_NUM: bad number %i (called at %s:%i)", n, filename, fileline);
1643         return NULL;
1644 }
1645
1646 /*
1647 int NUM_FOR_EDICT_ERROR(edict_t *e)
1648 {
1649         Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1650         return 0;
1651 }
1652
1653 int NUM_FOR_EDICT(edict_t *e)
1654 {
1655         int n;
1656         n = e - sv.edicts;
1657         if ((unsigned int)n >= MAX_EDICTS)
1658                 Host_Error ("NUM_FOR_EDICT: bad pointer");
1659         return n;
1660 }
1661
1662 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1663 //{
1664 //      return e - sv.edicts;
1665 //}
1666
1667 //#define       EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1668 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1669 int EDICT_TO_PROG(edict_t *e)
1670 {
1671         int n;
1672         n = e - sv.edicts;
1673         if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1674                 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1675         return n;// EXPERIMENTAL
1676         //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1677 }
1678 edict_t *PROG_TO_EDICT(int n)
1679 {
1680         if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1681                 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1682         return sv.edicts + n; // EXPERIMENTAL
1683         //return sv.edicts + ((n) / (progs->entityfields * 4));
1684 }
1685 */
1686