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