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