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