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