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