]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - pr_edict.c
whitespace
[xonotic/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, 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
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 (const char *name);
83 dfunction_t *ED_FindFunction (const 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(const 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 (const 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 (const 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 (const 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 (const 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                 if (!COM_ParseToken (&data))
794                         Host_Error ("ED_ParseEntity: EOF without closing brace");
795                 if (com_token[0] == '}')
796                         break;
797
798                 strcpy (keyname, com_token);
799
800                 // parse value
801                 if (!COM_ParseToken (&data))
802                         Host_Error ("ED_ParseEntity: EOF without closing brace");
803
804                 if (com_token[0] == '}')
805                         Host_Error ("ED_ParseEntity: closing brace without data");
806
807                 key = ED_FindGlobal (keyname);
808                 if (!key)
809                 {
810                         Con_DPrintf ("'%s' is not a global\n", keyname);
811                         continue;
812                 }
813
814                 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
815                         Host_Error ("ED_ParseGlobals: parse error");
816         }
817 }
818
819 //============================================================================
820
821
822 /*
823 =============
824 ED_NewString
825 =============
826 */
827 char *ED_NewString (const char *string)
828 {
829         char *new, *new_p;
830         int i,l;
831
832         l = strlen(string) + 1;
833         new = Mem_Alloc(edictstring_mempool, l);
834         new_p = new;
835
836         for (i=0 ; i< l ; i++)
837         {
838                 if (string[i] == '\\' && i < l-1)
839                 {
840                         i++;
841                         if (string[i] == 'n')
842                                 *new_p++ = '\n';
843                         else
844                                 *new_p++ = '\\';
845                 }
846                 else
847                         *new_p++ = string[i];
848         }
849
850         return new;
851 }
852
853
854 /*
855 =============
856 ED_ParseEval
857
858 Can parse either fields or globals
859 returns false if error
860 =============
861 */
862 qboolean        ED_ParseEpair (void *base, ddef_t *key, const char *s)
863 {
864         int             i;
865         char    string[128];
866         ddef_t  *def;
867         char    *v, *w;
868         void    *d;
869         dfunction_t     *func;
870
871         d = (void *)((int *)base + key->ofs);
872
873         switch (key->type & ~DEF_SAVEGLOBAL)
874         {
875         case ev_string:
876                 *(string_t *)d = ED_NewString (s) - pr_strings;
877                 break;
878                 
879         case ev_float:
880                 *(float *)d = atof (s);
881                 break;
882                 
883         case ev_vector:
884                 strcpy (string, s);
885                 v = string;
886                 w = string;
887                 for (i=0 ; i<3 ; i++)
888                 {
889                         while (*v && *v != ' ')
890                                 v++;
891                         *v = 0;
892                         ((float *)d)[i] = atof (w);
893                         w = v = v+1;
894                 }
895                 break;
896
897         case ev_entity:
898                 *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
899                 break;
900
901         case ev_field:
902                 def = ED_FindField (s);
903                 if (!def)
904                 {
905                         // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
906                         if (strcmp(s, "sky") && strcmp(s, "fog") && strncmp(s, "fog_", 4) && strcmp(s, "farclip"))
907                                 Con_DPrintf ("Can't find field %s\n", s);
908                         return false;
909                 }
910                 *(int *)d = G_INT(def->ofs);
911                 break;
912         
913         case ev_function:
914                 func = ED_FindFunction (s);
915                 if (!func)
916                 {
917                         Con_DPrintf ("Can't find function %s\n", s);
918                         return false;
919                 }
920                 *(func_t *)d = func - pr_functions;
921                 break;
922
923         default:
924                 break;
925         }
926         return true;
927 }
928
929 /*
930 ====================
931 ED_ParseEdict
932
933 Parses an edict out of the given string, returning the new position
934 ed should be a properly initialized empty edict.
935 Used for initial level load and for savegames.
936 ====================
937 */
938 const char *ED_ParseEdict (const char *data, edict_t *ent)
939 {
940         ddef_t *key;
941         qboolean anglehack;
942         qboolean init;
943         char keyname[256];
944         int n;
945
946         init = false;
947
948 // clear it
949         if (ent != sv.edicts)   // hack
950                 memset (&ent->v, 0, progs->entityfields * 4);
951
952 // go through all the dictionary pairs
953         while (1)
954         {
955         // parse key
956                 if (!COM_ParseToken (&data))
957                         Host_Error ("ED_ParseEntity: EOF without closing brace");
958                 if (com_token[0] == '}')
959                         break;
960
961                 // anglehack is to allow QuakeEd to write single scalar angles
962                 // and allow them to be turned into vectors. (FIXME...)
963                 if (!strcmp(com_token, "angle"))
964                 {
965                         strcpy (com_token, "angles");
966                         anglehack = true;
967                 }
968                 else
969                         anglehack = false;
970
971                 // FIXME: change light to _light to get rid of this hack
972                 if (!strcmp(com_token, "light"))
973                         strcpy (com_token, "light_lev");        // hack for single light def
974
975                 strcpy (keyname, com_token);
976
977                 // another hack to fix heynames with trailing spaces
978                 n = strlen(keyname);
979                 while (n && keyname[n-1] == ' ')
980                 {
981                         keyname[n-1] = 0;
982                         n--;
983                 }
984
985         // parse value
986                 if (!COM_ParseToken (&data))
987                         Host_Error ("ED_ParseEntity: EOF without closing brace");
988
989                 if (com_token[0] == '}')
990                         Host_Error ("ED_ParseEntity: closing brace without data");
991
992                 init = true;
993
994 // keynames with a leading underscore are used for utility comments,
995 // and are immediately discarded by quake
996                 if (keyname[0] == '_')
997                         continue;
998
999                 key = ED_FindField (keyname);
1000                 if (!key)
1001                 {
1002                         Con_DPrintf ("'%s' is not a field\n", keyname);
1003                         continue;
1004                 }
1005
1006                 if (anglehack)
1007                 {
1008                         char    temp[32];
1009                         strcpy (temp, com_token);
1010                         sprintf (com_token, "0 %s 0", temp);
1011                 }
1012
1013                 if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
1014                         Host_Error ("ED_ParseEdict: parse error");
1015         }
1016
1017         if (!init)
1018                 ent->free = true;
1019
1020         return data;
1021 }
1022
1023
1024 /*
1025 ================
1026 ED_LoadFromFile
1027
1028 The entities are directly placed in the array, rather than allocated with
1029 ED_Alloc, because otherwise an error loading the map would have entity
1030 number references out of order.
1031
1032 Creates a server's entity / program execution context by
1033 parsing textual entity definitions out of an ent file.
1034
1035 Used for both fresh maps and savegame loads.  A fresh map would also need
1036 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1037 ================
1038 */
1039 void ED_LoadFromFile (const char *data)
1040 {
1041         edict_t *ent;
1042         int inhibit;
1043         dfunction_t *func;
1044
1045         ent = NULL;
1046         inhibit = 0;
1047         pr_global_struct->time = sv.time;
1048         
1049 // parse ents
1050         while (1)
1051         {
1052 // parse the opening brace
1053                 if (!COM_ParseToken (&data))
1054                         break;
1055                 if (com_token[0] != '{')
1056                         Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1057
1058                 if (!ent)
1059                         ent = EDICT_NUM(0);
1060                 else
1061                         ent = ED_Alloc ();
1062                 data = ED_ParseEdict (data, ent);
1063
1064 // remove things from different skill levels or deathmatch
1065                 if (deathmatch.integer)
1066                 {
1067                         if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1068                         {
1069                                 ED_Free (ent);  
1070                                 inhibit++;
1071                                 continue;
1072                         }
1073                 }
1074                 else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY  ))
1075                           || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
1076                           || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD  )))
1077                 {
1078                         ED_Free (ent);  
1079                         inhibit++;
1080                         continue;
1081                 }
1082
1083 //
1084 // immediately call spawn function
1085 //
1086                 if (!ent->v.classname)
1087                 {
1088                         Con_Printf ("No classname for:\n");
1089                         ED_Print (ent);
1090                         ED_Free (ent);
1091                         continue;
1092                 }
1093
1094         // look for the spawn function
1095                 func = ED_FindFunction ( pr_strings + ent->v.classname );
1096
1097                 if (!func)
1098                 {
1099                         if (developer.integer) // don't confuse non-developers with errors
1100                         {
1101                                 Con_Printf ("No spawn function for:\n");
1102                                 ED_Print (ent);
1103                         }
1104                         ED_Free (ent);
1105                         continue;
1106                 }
1107
1108                 pr_global_struct->self = EDICT_TO_PROG(ent);
1109                 PR_ExecuteProgram (func - pr_functions, "");
1110         }
1111
1112         Con_DPrintf ("%i entities inhibited\n", inhibit);
1113 }
1114
1115
1116 typedef struct dpfield_s
1117 {
1118         int type;
1119         char *string;
1120 }
1121 dpfield_t;
1122
1123 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1124
1125 dpfield_t dpfields[] =
1126 {
1127         {ev_float, "gravity"},
1128         {ev_float, "button3"},
1129         {ev_float, "button4"},
1130         {ev_float, "button5"},
1131         {ev_float, "button6"},
1132         {ev_float, "button7"},
1133         {ev_float, "button8"},
1134         {ev_float, "glow_size"},
1135         {ev_float, "glow_trail"},
1136         {ev_float, "glow_color"},
1137         {ev_float, "items2"},
1138         {ev_float, "scale"},
1139         {ev_float, "alpha"},
1140         {ev_float, "renderamt"},
1141         {ev_float, "rendermode"},
1142         {ev_float, "fullbright"},
1143         {ev_float, "ammo_shells1"},
1144         {ev_float, "ammo_nails1"},
1145         {ev_float, "ammo_lava_nails"},
1146         {ev_float, "ammo_rockets1"},
1147         {ev_float, "ammo_multi_rockets"},
1148         {ev_float, "ammo_cells1"},
1149         {ev_float, "ammo_plasma"},
1150         {ev_float, "idealpitch"},
1151         {ev_float, "pitch_speed"},
1152         {ev_entity, "viewmodelforclient"},
1153         {ev_entity, "nodrawtoclient"},
1154         {ev_entity, "exteriormodeltoclient"},
1155         {ev_entity, "drawonlytoclient"},
1156         {ev_float, "ping"},
1157         {ev_vector, "movement"},
1158         {ev_float, "pmodel"},
1159         {ev_vector, "punchvector"}
1160 };
1161
1162 /*
1163 ===============
1164 PR_LoadProgs
1165 ===============
1166 */
1167 void PR_LoadProgs (void)
1168 {
1169         int i;
1170         dstatement_t *st;
1171         ddef_t *infielddefs;
1172         void *temp;
1173
1174 // flush the non-C variable lookup cache
1175         for (i=0 ; i<GEFV_CACHESIZE ; i++)
1176                 gefvCache[i].field[0] = 0;
1177
1178         Mem_EmptyPool(progs_mempool);
1179         Mem_EmptyPool(edictstring_mempool);
1180
1181         temp = COM_LoadFile ("progs.dat", false);
1182         if (!temp)
1183                 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1184
1185         progs = (dprograms_t *)Mem_Alloc(progs_mempool, com_filesize);
1186
1187         memcpy(progs, temp, com_filesize);
1188         Mem_Free(temp);
1189
1190         Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024);
1191
1192         pr_crc = CRC_Block((qbyte *)progs, com_filesize);
1193
1194 // byte swap the header
1195         for (i=0 ; i<sizeof(*progs)/4 ; i++)
1196                 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1197
1198         if (progs->version != PROG_VERSION)
1199                 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1200         if (progs->crc != PROGHEADER_CRC)
1201                 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1202
1203         pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1204         pr_strings = (char *)progs + progs->ofs_strings;
1205         pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1206
1207         // we need to expand the fielddefs list to include all the engine fields,
1208         // so allocate a new place for it
1209         infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1210         pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1211
1212         pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1213
1214         // moved edict_size calculation down below field adding code
1215
1216         pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1217         pr_globals = (float *)pr_global_struct;
1218
1219 // byte swap the lumps
1220         for (i=0 ; i<progs->numstatements ; i++)
1221         {
1222                 pr_statements[i].op = LittleShort(pr_statements[i].op);
1223                 pr_statements[i].a = LittleShort(pr_statements[i].a);
1224                 pr_statements[i].b = LittleShort(pr_statements[i].b);
1225                 pr_statements[i].c = LittleShort(pr_statements[i].c);
1226         }
1227
1228         for (i=0 ; i<progs->numfunctions; i++)
1229         {
1230                 pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
1231                 pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
1232                 pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
1233                 pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
1234                 pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
1235                 pr_functions[i].locals = LittleLong (pr_functions[i].locals);
1236         }
1237
1238         for (i=0 ; i<progs->numglobaldefs ; i++)
1239         {
1240                 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1241                 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1242                 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1243         }
1244
1245         // copy the progs fields to the new fields list
1246         for (i = 0;i < progs->numfielddefs;i++)
1247         {
1248                 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1249                 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1250                         Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1251                 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1252                 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1253         }
1254
1255         // append the darkplaces fields
1256         for (i = 0;i < DPFIELDS;i++)
1257         {
1258                 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1259                 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1260                 pr_fielddefs[progs->numfielddefs].s_name = dpfields[i].string - pr_strings;
1261                 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1262                         progs->entityfields += 3;
1263                 else
1264                         progs->entityfields++;
1265                 progs->numfielddefs++;
1266         }
1267
1268         for (i=0 ; i<progs->numglobals ; i++)
1269                 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1270
1271         // moved edict_size calculation down here, below field adding code
1272         pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
1273
1274         pr_edictareasize = pr_edict_size * MAX_EDICTS;
1275
1276         // LordHavoc: bounds check anything static
1277         for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1278         {
1279                 switch (st->op)
1280                 {
1281                 case OP_IF:
1282                 case OP_IFNOT:
1283                         if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1284                                 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1285                         break;
1286                 case OP_GOTO:
1287                         if (st->a + i < 0 || st->a + i >= progs->numstatements)
1288                                 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1289                         break;
1290                 // global global global
1291                 case OP_ADD_F:
1292                 case OP_ADD_V:
1293                 case OP_SUB_F:
1294                 case OP_SUB_V:
1295                 case OP_MUL_F:
1296                 case OP_MUL_V:
1297                 case OP_MUL_FV:
1298                 case OP_MUL_VF:
1299                 case OP_DIV_F:
1300                 case OP_BITAND:
1301                 case OP_BITOR:
1302                 case OP_GE:
1303                 case OP_LE:
1304                 case OP_GT:
1305                 case OP_LT:
1306                 case OP_AND:
1307                 case OP_OR:
1308                 case OP_EQ_F:
1309                 case OP_EQ_V:
1310                 case OP_EQ_S:
1311                 case OP_EQ_E:
1312                 case OP_EQ_FNC:
1313                 case OP_NE_F:
1314                 case OP_NE_V:
1315                 case OP_NE_S:
1316                 case OP_NE_E:
1317                 case OP_NE_FNC:
1318                 case OP_ADDRESS:
1319                 case OP_LOAD_F:
1320                 case OP_LOAD_FLD:
1321                 case OP_LOAD_ENT:
1322                 case OP_LOAD_S:
1323                 case OP_LOAD_FNC:
1324                 case OP_LOAD_V:
1325                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1326                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1327                         break;
1328                 // global none global
1329                 case OP_NOT_F:
1330                 case OP_NOT_V:
1331                 case OP_NOT_S:
1332                 case OP_NOT_FNC:
1333                 case OP_NOT_ENT:
1334                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1335                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1336                         break;
1337                 // 2 globals
1338                 case OP_STOREP_F:
1339                 case OP_STOREP_ENT:
1340                 case OP_STOREP_FLD:
1341                 case OP_STOREP_S:
1342                 case OP_STOREP_FNC:
1343                 case OP_STORE_F:
1344                 case OP_STORE_ENT:
1345                 case OP_STORE_FLD:
1346                 case OP_STORE_S:
1347                 case OP_STORE_FNC:
1348                 case OP_STATE:
1349                 case OP_STOREP_V:
1350                 case OP_STORE_V:
1351                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1352                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1353                         break;
1354                 // 1 global
1355                 case OP_CALL0:
1356                 case OP_CALL1:
1357                 case OP_CALL2:
1358                 case OP_CALL3:
1359                 case OP_CALL4:
1360                 case OP_CALL5:
1361                 case OP_CALL6:
1362                 case OP_CALL7:
1363                 case OP_CALL8:
1364                 case OP_DONE:
1365                 case OP_RETURN:
1366                         if ((unsigned short) st->a >= progs->numglobals)
1367                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1368                         break;
1369                 default:
1370                         Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1371                         break;
1372                 }
1373         }
1374
1375         FindEdictFieldOffsets(); // LordHavoc: update field offset list
1376         PR_Execute_ProgsLoaded();
1377 }
1378
1379
1380 void PR_Fields_f (void)
1381 {
1382         int i, j, ednum, used, usedamount;
1383         int *counts;
1384         char tempstring[5000], tempstring2[260], *name;
1385         edict_t *ed;
1386         ddef_t *d;
1387         int *v;
1388         if (!sv.active)
1389         {
1390                 Con_Printf("no progs loaded\n");
1391                 return;
1392         }
1393         counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1394         for (ednum = 0;ednum < MAX_EDICTS;ednum++)
1395         {
1396                 ed = EDICT_NUM(ednum);
1397                 if (ed->free)
1398                         continue;
1399                 for (i = 1;i < progs->numfielddefs;i++)
1400                 {
1401                         d = &pr_fielddefs[i];
1402                         name = pr_strings + d->s_name;
1403                         if (name[strlen(name)-2] == '_')
1404                                 continue;       // skip _x, _y, _z vars
1405                         v = (int *)((char *)&ed->v + d->ofs*4);
1406                         // if the value is still all 0, skip the field
1407                         for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1408                         {
1409                                 if (v[j])
1410                                 {
1411                                         counts[i]++;
1412                                         break;
1413                                 }
1414                         }
1415                 }
1416         }
1417         used = 0;
1418         usedamount = 0;
1419         tempstring[0] = 0;
1420         for (i = 0;i < progs->numfielddefs;i++)
1421         {
1422                 d = &pr_fielddefs[i];
1423                 name = pr_strings + d->s_name;
1424                 if (name[strlen(name)-2] == '_')
1425                         continue;       // skip _x, _y, _z vars
1426                 switch(d->type & ~DEF_SAVEGLOBAL)
1427                 {
1428                 case ev_string:
1429                         strcat(tempstring, "string   ");
1430                         break;
1431                 case ev_entity:
1432                         strcat(tempstring, "entity   ");
1433                         break;
1434                 case ev_function:
1435                         strcat(tempstring, "function ");
1436                         break;
1437                 case ev_field:
1438                         strcat(tempstring, "field    ");
1439                         break;
1440                 case ev_void:
1441                         strcat(tempstring, "void     ");
1442                         break;
1443                 case ev_float:
1444                         strcat(tempstring, "float    ");
1445                         break;
1446                 case ev_vector:
1447                         strcat(tempstring, "vector   ");
1448                         break;
1449                 case ev_pointer:
1450                         strcat(tempstring, "pointer  ");
1451                         break;
1452                 default:
1453                         sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1454                         strcat(tempstring, tempstring2);
1455                         break;
1456                 }
1457                 if (strlen(name) > 256)
1458                 {
1459                         strncpy(tempstring2, name, 256);
1460                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1461                         tempstring2[259] = 0;
1462                         name = tempstring2;
1463                 }
1464                 strcat(tempstring, name);
1465                 for (j = strlen(name);j < 25;j++)
1466                         strcat(tempstring, " ");
1467                 sprintf(tempstring2, "%5d", counts[i]);
1468                 strcat(tempstring, tempstring2);
1469                 strcat(tempstring, "\n");
1470                 if (strlen(tempstring) >= 4096)
1471                 {
1472                         Con_Printf("%s", tempstring);
1473                         tempstring[0] = 0;
1474                 }
1475                 if (counts[i])
1476                 {
1477                         used++;
1478                         usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1479                 }
1480         }
1481         Mem_Free(counts);
1482         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);
1483 }
1484
1485 void PR_Globals_f (void)
1486 {
1487         int i;
1488         if (!sv.active)
1489         {
1490                 Con_Printf("no progs loaded\n");
1491                 return;
1492         }
1493         for (i = 0;i < progs->numglobaldefs;i++)
1494                 Con_Printf("%s\n", (pr_strings + pr_globaldefs[i].s_name));
1495         Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1496 }
1497
1498 /*
1499 ===============
1500 PR_Init
1501 ===============
1502 */
1503 void PR_Init (void)
1504 {
1505         Cmd_AddCommand ("edict", ED_PrintEdict_f);
1506         Cmd_AddCommand ("edicts", ED_PrintEdicts);
1507         Cmd_AddCommand ("edictcount", ED_Count);
1508         Cmd_AddCommand ("profile", PR_Profile_f);
1509         Cmd_AddCommand ("pr_fields", PR_Fields_f);
1510         Cmd_AddCommand ("pr_globals", PR_Globals_f);
1511         Cvar_RegisterVariable (&pr_checkextension);
1512         Cvar_RegisterVariable (&nomonsters);
1513         Cvar_RegisterVariable (&gamecfg);
1514         Cvar_RegisterVariable (&scratch1);
1515         Cvar_RegisterVariable (&scratch2);
1516         Cvar_RegisterVariable (&scratch3);
1517         Cvar_RegisterVariable (&scratch4);
1518         Cvar_RegisterVariable (&savedgamecfg);
1519         Cvar_RegisterVariable (&saved1);
1520         Cvar_RegisterVariable (&saved2);
1521         Cvar_RegisterVariable (&saved3);
1522         Cvar_RegisterVariable (&saved4);
1523         // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1524         Cvar_RegisterVariable (&decors);
1525         // LordHavoc: Nehahra uses these to pass data around cutscene demos
1526         if (gamemode == GAME_NEHAHRA)
1527         {
1528                 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1529                 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1530                 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1531                 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1532                 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1533                 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1534                 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1535                 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1536                 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1537                 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1538         }
1539         Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1540         // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1541         Cvar_RegisterVariable (&pr_boundscheck);
1542
1543         progs_mempool = Mem_AllocPool("progs.dat");
1544         edictstring_mempool = Mem_AllocPool("edict strings");
1545 }
1546
1547 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1548 edict_t *EDICT_NUM_ERROR(int n)
1549 {
1550         Host_Error ("EDICT_NUM: bad number %i", n);
1551         return NULL;
1552 }
1553
1554 int NUM_FOR_EDICT(edict_t *e)
1555 {
1556         int             b;
1557
1558         b = (qbyte *)e - (qbyte *)sv.edicts;
1559         b = b / pr_edict_size;
1560
1561         if (b < 0 || b >= sv.num_edicts)
1562                 Host_Error ("NUM_FOR_EDICT: bad pointer");
1563         return b;
1564 }
1565
1566 int NoCrash_NUM_FOR_EDICT(edict_t *e)
1567 {
1568         int             b;
1569
1570         b = (qbyte *)e - (qbyte *)sv.edicts;
1571         b = b / pr_edict_size;
1572         return b;
1573 }
1574