]> icculus.org git repositories - divverent/darkplaces.git/blob - pr_edict.c
reverted the massive svs.connectedclients change, now back to svs.clients and svs...
[divverent/darkplaces.git] / pr_edict.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // sv_edict.c -- entity dictionary
21
22 #include "quakedef.h"
23
24 dprograms_t             *progs;
25 mfunction_t             *pr_functions;
26 char                    *pr_strings;
27 ddef_t                  *pr_fielddefs;
28 ddef_t                  *pr_globaldefs;
29 dstatement_t    *pr_statements;
30 globalvars_t    *pr_global_struct;
31 float                   *pr_globals;                    // same as pr_global_struct
32 int                             pr_edict_size;                  // in bytes
33 int                             pr_edictareasize;               // LordHavoc: in bytes
34
35 unsigned short  pr_crc;
36
37 mempool_t               *progs_mempool;
38 mempool_t               *edictstring_mempool;
39
40 int             type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
41
42 ddef_t *ED_FieldAtOfs(int ofs);
43 qboolean ED_ParseEpair(edict_t *ent, 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 < svs.maxclients)
203         {
204                 e->v->colormap = num + 1;
205                 e->v->team = (svs.clients[num].colors & 15) + 1;
206                 e->v->netname = PR_SetString(svs.clients[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 = svs.maxclients + 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(NULL, 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(edict_t *ent, ddef_t *key, const char *s)
887 {
888         int i;
889         ddef_t *def;
890         eval_t *val;
891         mfunction_t *func;
892
893         if (ent)
894                 val = (eval_t *)((int *)ent->v + key->ofs);
895         else
896                 val = (eval_t *)((int *)pr_globals + key->ofs);
897         switch (key->type & ~DEF_SAVEGLOBAL)
898         {
899         case ev_string:
900                 val->string = PR_SetString(ED_NewString(s));
901                 break;
902
903         case ev_float:
904                 while (*s && *s <= ' ')
905                         s++;
906                 val->_float = atof(s);
907                 break;
908
909         case ev_vector:
910                 for (i = 0;i < 3;i++)
911                 {
912                         while (*s && *s <= ' ')
913                                 s++;
914                         if (!*s)
915                                 break;
916                         val->vector[i] = atof(s);
917                         while (*s > ' ')
918                                 s++;
919                         if (!*s)
920                                 break;
921                 }
922                 break;
923
924         case ev_entity:
925                 while (*s && *s <= ' ')
926                         s++;
927                 i = atoi(s);
928                 if (i < 0 || i >= MAX_EDICTS)
929                         Con_Printf("ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i)\n", i, MAX_EDICTS);
930                 while (i >= sv.max_edicts)
931                         SV_IncreaseEdicts();
932                 // if SV_IncreaseEdicts was called the base pointer needs to be updated
933                 if (ent)
934                         val = (eval_t *)((int *)ent->v + key->ofs);
935                 val->edict = EDICT_TO_PROG(EDICT_NUM(i));
936                 break;
937
938         case ev_field:
939                 def = ED_FindField(s);
940                 if (!def)
941                 {
942                         Con_DPrintf("ED_ParseEpair: Can't find field %s\n", s);
943                         return false;
944                 }
945                 val->_int = G_INT(def->ofs);
946                 break;
947
948         case ev_function:
949                 func = ED_FindFunction(s);
950                 if (!func)
951                 {
952                         Con_Printf ("ED_ParseEpair: Can't find function %s\n", s);
953                         return false;
954                 }
955                 val->function = func - pr_functions;
956                 break;
957
958         default:
959                 Con_Printf("ED_ParseEpair: Unknown key->type %i for key \"%s\"\n", key->type, PR_GetString(key->s_name));
960                 return false;
961         }
962         return true;
963 }
964
965 /*
966 ====================
967 ED_ParseEdict
968
969 Parses an edict out of the given string, returning the new position
970 ed should be a properly initialized empty edict.
971 Used for initial level load and for savegames.
972 ====================
973 */
974 const char *ED_ParseEdict (const char *data, edict_t *ent)
975 {
976         ddef_t *key;
977         qboolean anglehack;
978         qboolean init;
979         char keyname[256];
980         int n;
981
982         init = false;
983
984 // clear it
985         if (ent != sv.edicts)   // hack
986                 memset (ent->v, 0, progs->entityfields * 4);
987
988 // go through all the dictionary pairs
989         while (1)
990         {
991         // parse key
992                 if (!COM_ParseToken(&data, false))
993                         Host_Error ("ED_ParseEntity: EOF without closing brace");
994                 if (com_token[0] == '}')
995                         break;
996
997                 // anglehack is to allow QuakeEd to write single scalar angles
998                 // and allow them to be turned into vectors. (FIXME...)
999                 if (!strcmp(com_token, "angle"))
1000                 {
1001                         strcpy (com_token, "angles");
1002                         anglehack = true;
1003                 }
1004                 else
1005                         anglehack = false;
1006
1007                 // FIXME: change light to _light to get rid of this hack
1008                 if (!strcmp(com_token, "light"))
1009                         strcpy (com_token, "light_lev");        // hack for single light def
1010
1011                 strcpy (keyname, com_token);
1012
1013                 // another hack to fix heynames with trailing spaces
1014                 n = strlen(keyname);
1015                 while (n && keyname[n-1] == ' ')
1016                 {
1017                         keyname[n-1] = 0;
1018                         n--;
1019                 }
1020
1021         // parse value
1022                 if (!COM_ParseToken(&data, false))
1023                         Host_Error ("ED_ParseEntity: EOF without closing brace");
1024
1025                 if (com_token[0] == '}')
1026                         Host_Error ("ED_ParseEntity: closing brace without data");
1027
1028                 init = true;
1029
1030 // keynames with a leading underscore are used for utility comments,
1031 // and are immediately discarded by quake
1032                 if (keyname[0] == '_')
1033                         continue;
1034
1035                 key = ED_FindField (keyname);
1036                 if (!key)
1037                 {
1038                         Con_DPrintf ("'%s' is not a field\n", keyname);
1039                         continue;
1040                 }
1041
1042                 if (anglehack)
1043                 {
1044                         char    temp[32];
1045                         strcpy (temp, com_token);
1046                         sprintf (com_token, "0 %s 0", temp);
1047                 }
1048
1049                 if (!ED_ParseEpair(ent, key, com_token))
1050                         Host_Error ("ED_ParseEdict: parse error");
1051         }
1052
1053         if (!init)
1054                 ent->e->free = true;
1055
1056         return data;
1057 }
1058
1059
1060 /*
1061 ================
1062 ED_LoadFromFile
1063
1064 The entities are directly placed in the array, rather than allocated with
1065 ED_Alloc, because otherwise an error loading the map would have entity
1066 number references out of order.
1067
1068 Creates a server's entity / program execution context by
1069 parsing textual entity definitions out of an ent file.
1070
1071 Used for both fresh maps and savegame loads.  A fresh map would also need
1072 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1073 ================
1074 */
1075 void ED_LoadFromFile (const char *data)
1076 {
1077         edict_t *ent;
1078         int parsed, inhibited, spawned, died;
1079         mfunction_t *func;
1080
1081         ent = NULL;
1082         parsed = 0;
1083         inhibited = 0;
1084         spawned = 0;
1085         died = 0;
1086         pr_global_struct->time = sv.time;
1087
1088 // parse ents
1089         while (1)
1090         {
1091 // parse the opening brace
1092                 if (!COM_ParseToken(&data, false))
1093                         break;
1094                 if (com_token[0] != '{')
1095                         Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1096
1097                 if (!ent)
1098                         ent = EDICT_NUM(0);
1099                 else
1100                         ent = ED_Alloc ();
1101                 data = ED_ParseEdict (data, ent);
1102                 parsed++;
1103
1104 // remove things from different skill levels or deathmatch
1105                 if (deathmatch.integer)
1106                 {
1107                         if (((int)ent->v->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1108                         {
1109                                 ED_Free (ent);
1110                                 inhibited++;
1111                                 continue;
1112                         }
1113                 }
1114                 else if ((current_skill == 0 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_EASY  ))
1115                           || (current_skill == 1 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_MEDIUM))
1116                           || (current_skill >= 2 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_HARD  )))
1117                 {
1118                         ED_Free (ent);
1119                         inhibited++;
1120                         continue;
1121                 }
1122
1123 //
1124 // immediately call spawn function
1125 //
1126                 if (!ent->v->classname)
1127                 {
1128                         Con_Printf ("No classname for:\n");
1129                         ED_Print (ent);
1130                         ED_Free (ent);
1131                         continue;
1132                 }
1133
1134         // look for the spawn function
1135                 func = ED_FindFunction (PR_GetString(ent->v->classname));
1136
1137                 if (!func)
1138                 {
1139                         if (developer.integer) // don't confuse non-developers with errors
1140                         {
1141                                 Con_Printf ("No spawn function for:\n");
1142                                 ED_Print (ent);
1143                         }
1144                         ED_Free (ent);
1145                         continue;
1146                 }
1147
1148                 pr_global_struct->self = EDICT_TO_PROG(ent);
1149                 PR_ExecuteProgram (func - pr_functions, "");
1150                 spawned++;
1151                 if (ent->e->free)
1152                         died++;
1153         }
1154
1155         Con_DPrintf ("%i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", parsed, inhibited, spawned, died, spawned - died);
1156 }
1157
1158
1159 typedef struct dpfield_s
1160 {
1161         int type;
1162         char *string;
1163 }
1164 dpfield_t;
1165
1166 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1167
1168 dpfield_t dpfields[] =
1169 {
1170         {ev_float, "gravity"},
1171         {ev_float, "button3"},
1172         {ev_float, "button4"},
1173         {ev_float, "button5"},
1174         {ev_float, "button6"},
1175         {ev_float, "button7"},
1176         {ev_float, "button8"},
1177         {ev_float, "glow_size"},
1178         {ev_float, "glow_trail"},
1179         {ev_float, "glow_color"},
1180         {ev_float, "items2"},
1181         {ev_float, "scale"},
1182         {ev_float, "alpha"},
1183         {ev_float, "renderamt"},
1184         {ev_float, "rendermode"},
1185         {ev_float, "fullbright"},
1186         {ev_float, "ammo_shells1"},
1187         {ev_float, "ammo_nails1"},
1188         {ev_float, "ammo_lava_nails"},
1189         {ev_float, "ammo_rockets1"},
1190         {ev_float, "ammo_multi_rockets"},
1191         {ev_float, "ammo_cells1"},
1192         {ev_float, "ammo_plasma"},
1193         {ev_float, "idealpitch"},
1194         {ev_float, "pitch_speed"},
1195         {ev_entity, "viewmodelforclient"},
1196         {ev_entity, "nodrawtoclient"},
1197         {ev_entity, "exteriormodeltoclient"},
1198         {ev_entity, "drawonlytoclient"},
1199         {ev_float, "ping"},
1200         {ev_vector, "movement"},
1201         {ev_float, "pmodel"},
1202         {ev_vector, "punchvector"},
1203         {ev_float, "clientcolors"},
1204         {ev_entity, "tag_entity"},
1205         {ev_float, "tag_index"}
1206 };
1207
1208 /*
1209 ===============
1210 PR_LoadProgs
1211 ===============
1212 */
1213 extern void PR_Cmd_Reset (void);
1214 void PR_LoadProgs (void)
1215 {
1216         int i;
1217         dstatement_t *st;
1218         ddef_t *infielddefs;
1219         void *temp;
1220         dfunction_t *dfunctions;
1221
1222 // flush the non-C variable lookup cache
1223         for (i=0 ; i<GEFV_CACHESIZE ; i++)
1224                 gefvCache[i].field[0] = 0;
1225
1226         Mem_EmptyPool(progs_mempool);
1227         Mem_EmptyPool(edictstring_mempool);
1228
1229         temp = FS_LoadFile ("progs.dat", false);
1230         if (!temp)
1231                 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1232
1233         progs = (dprograms_t *)Mem_Alloc(progs_mempool, fs_filesize);
1234
1235         memcpy(progs, temp, fs_filesize);
1236         Mem_Free(temp);
1237
1238         Con_DPrintf ("Programs occupy %iK.\n", fs_filesize/1024);
1239
1240         pr_crc = CRC_Block((qbyte *)progs, fs_filesize);
1241
1242 // byte swap the header
1243         for (i = 0;i < (int) sizeof(*progs) / 4;i++)
1244                 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1245
1246         if (progs->version != PROG_VERSION)
1247                 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1248         if (progs->crc != PROGHEADER_CRC)
1249                 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1250
1251         //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1252         dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1253         pr_strings = (char *)progs + progs->ofs_strings;
1254         pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1255
1256         // we need to expand the fielddefs list to include all the engine fields,
1257         // so allocate a new place for it
1258         infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1259         pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1260
1261         pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1262
1263         // moved edict_size calculation down below field adding code
1264
1265         pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1266         pr_globals = (float *)pr_global_struct;
1267
1268 // byte swap the lumps
1269         for (i=0 ; i<progs->numstatements ; i++)
1270         {
1271                 pr_statements[i].op = LittleShort(pr_statements[i].op);
1272                 pr_statements[i].a = LittleShort(pr_statements[i].a);
1273                 pr_statements[i].b = LittleShort(pr_statements[i].b);
1274                 pr_statements[i].c = LittleShort(pr_statements[i].c);
1275         }
1276
1277         pr_functions = Mem_Alloc(progs_mempool, sizeof(mfunction_t) * progs->numfunctions);
1278         for (i = 0;i < progs->numfunctions;i++)
1279         {
1280                 pr_functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1281                 pr_functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1282                 pr_functions[i].s_name = LittleLong (dfunctions[i].s_name);
1283                 pr_functions[i].s_file = LittleLong (dfunctions[i].s_file);
1284                 pr_functions[i].numparms = LittleLong (dfunctions[i].numparms);
1285                 pr_functions[i].locals = LittleLong (dfunctions[i].locals);
1286                 memcpy(pr_functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1287         }
1288
1289         for (i=0 ; i<progs->numglobaldefs ; i++)
1290         {
1291                 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1292                 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1293                 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1294         }
1295
1296         // copy the progs fields to the new fields list
1297         for (i = 0;i < progs->numfielddefs;i++)
1298         {
1299                 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1300                 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1301                         Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1302                 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1303                 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1304         }
1305
1306         // append the darkplaces fields
1307         for (i = 0;i < (int) DPFIELDS;i++)
1308         {
1309                 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1310                 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1311                 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1312                 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1313                         progs->entityfields += 3;
1314                 else
1315                         progs->entityfields++;
1316                 progs->numfielddefs++;
1317         }
1318
1319         for (i=0 ; i<progs->numglobals ; i++)
1320                 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1321
1322         // moved edict_size calculation down here, below field adding code
1323         // LordHavoc: this no longer includes the edict_t header
1324         pr_edict_size = progs->entityfields * 4;
1325         pr_edictareasize = pr_edict_size * MAX_EDICTS;
1326
1327         // LordHavoc: bounds check anything static
1328         for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1329         {
1330                 switch (st->op)
1331                 {
1332                 case OP_IF:
1333                 case OP_IFNOT:
1334                         if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1335                                 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1336                         break;
1337                 case OP_GOTO:
1338                         if (st->a + i < 0 || st->a + i >= progs->numstatements)
1339                                 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1340                         break;
1341                 // global global global
1342                 case OP_ADD_F:
1343                 case OP_ADD_V:
1344                 case OP_SUB_F:
1345                 case OP_SUB_V:
1346                 case OP_MUL_F:
1347                 case OP_MUL_V:
1348                 case OP_MUL_FV:
1349                 case OP_MUL_VF:
1350                 case OP_DIV_F:
1351                 case OP_BITAND:
1352                 case OP_BITOR:
1353                 case OP_GE:
1354                 case OP_LE:
1355                 case OP_GT:
1356                 case OP_LT:
1357                 case OP_AND:
1358                 case OP_OR:
1359                 case OP_EQ_F:
1360                 case OP_EQ_V:
1361                 case OP_EQ_S:
1362                 case OP_EQ_E:
1363                 case OP_EQ_FNC:
1364                 case OP_NE_F:
1365                 case OP_NE_V:
1366                 case OP_NE_S:
1367                 case OP_NE_E:
1368                 case OP_NE_FNC:
1369                 case OP_ADDRESS:
1370                 case OP_LOAD_F:
1371                 case OP_LOAD_FLD:
1372                 case OP_LOAD_ENT:
1373                 case OP_LOAD_S:
1374                 case OP_LOAD_FNC:
1375                 case OP_LOAD_V:
1376                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1377                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1378                         break;
1379                 // global none global
1380                 case OP_NOT_F:
1381                 case OP_NOT_V:
1382                 case OP_NOT_S:
1383                 case OP_NOT_FNC:
1384                 case OP_NOT_ENT:
1385                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1386                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1387                         break;
1388                 // 2 globals
1389                 case OP_STOREP_F:
1390                 case OP_STOREP_ENT:
1391                 case OP_STOREP_FLD:
1392                 case OP_STOREP_S:
1393                 case OP_STOREP_FNC:
1394                 case OP_STORE_F:
1395                 case OP_STORE_ENT:
1396                 case OP_STORE_FLD:
1397                 case OP_STORE_S:
1398                 case OP_STORE_FNC:
1399                 case OP_STATE:
1400                 case OP_STOREP_V:
1401                 case OP_STORE_V:
1402                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1403                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1404                         break;
1405                 // 1 global
1406                 case OP_CALL0:
1407                 case OP_CALL1:
1408                 case OP_CALL2:
1409                 case OP_CALL3:
1410                 case OP_CALL4:
1411                 case OP_CALL5:
1412                 case OP_CALL6:
1413                 case OP_CALL7:
1414                 case OP_CALL8:
1415                 case OP_DONE:
1416                 case OP_RETURN:
1417                         if ((unsigned short) st->a >= progs->numglobals)
1418                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1419                         break;
1420                 default:
1421                         Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1422                         break;
1423                 }
1424         }
1425
1426         FindEdictFieldOffsets(); // LordHavoc: update field offset list
1427         PR_Execute_ProgsLoaded();
1428         PR_Cmd_Reset();
1429 }
1430
1431
1432 void PR_Fields_f (void)
1433 {
1434         int i, j, ednum, used, usedamount;
1435         int *counts;
1436         char tempstring[5000], tempstring2[260], *name;
1437         edict_t *ed;
1438         ddef_t *d;
1439         int *v;
1440         if (!sv.active)
1441         {
1442                 Con_Printf("no progs loaded\n");
1443                 return;
1444         }
1445         counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1446         for (ednum = 0;ednum < MAX_EDICTS;ednum++)
1447         {
1448                 ed = EDICT_NUM(ednum);
1449                 if (ed->e->free)
1450                         continue;
1451                 for (i = 1;i < progs->numfielddefs;i++)
1452                 {
1453                         d = &pr_fielddefs[i];
1454                         name = PR_GetString(d->s_name);
1455                         if (name[strlen(name)-2] == '_')
1456                                 continue;       // skip _x, _y, _z vars
1457                         v = (int *)((char *)ed->v + d->ofs*4);
1458                         // if the value is still all 0, skip the field
1459                         for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1460                         {
1461                                 if (v[j])
1462                                 {
1463                                         counts[i]++;
1464                                         break;
1465                                 }
1466                         }
1467                 }
1468         }
1469         used = 0;
1470         usedamount = 0;
1471         tempstring[0] = 0;
1472         for (i = 0;i < progs->numfielddefs;i++)
1473         {
1474                 d = &pr_fielddefs[i];
1475                 name = PR_GetString(d->s_name);
1476                 if (name[strlen(name)-2] == '_')
1477                         continue;       // skip _x, _y, _z vars
1478                 switch(d->type & ~DEF_SAVEGLOBAL)
1479                 {
1480                 case ev_string:
1481                         strcat(tempstring, "string   ");
1482                         break;
1483                 case ev_entity:
1484                         strcat(tempstring, "entity   ");
1485                         break;
1486                 case ev_function:
1487                         strcat(tempstring, "function ");
1488                         break;
1489                 case ev_field:
1490                         strcat(tempstring, "field    ");
1491                         break;
1492                 case ev_void:
1493                         strcat(tempstring, "void     ");
1494                         break;
1495                 case ev_float:
1496                         strcat(tempstring, "float    ");
1497                         break;
1498                 case ev_vector:
1499                         strcat(tempstring, "vector   ");
1500                         break;
1501                 case ev_pointer:
1502                         strcat(tempstring, "pointer  ");
1503                         break;
1504                 default:
1505                         sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1506                         strcat(tempstring, tempstring2);
1507                         break;
1508                 }
1509                 if (strlen(name) > 256)
1510                 {
1511                         strncpy(tempstring2, name, 256);
1512                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1513                         tempstring2[259] = 0;
1514                         name = tempstring2;
1515                 }
1516                 strcat(tempstring, name);
1517                 for (j = strlen(name);j < 25;j++)
1518                         strcat(tempstring, " ");
1519                 sprintf(tempstring2, "%5d", counts[i]);
1520                 strcat(tempstring, tempstring2);
1521                 strcat(tempstring, "\n");
1522                 if (strlen(tempstring) >= 4096)
1523                 {
1524                         Con_Printf("%s", tempstring);
1525                         tempstring[0] = 0;
1526                 }
1527                 if (counts[i])
1528                 {
1529                         used++;
1530                         usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1531                 }
1532         }
1533         Mem_Free(counts);
1534         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);
1535 }
1536
1537 void PR_Globals_f (void)
1538 {
1539         int i;
1540         if (!sv.active)
1541         {
1542                 Con_Printf("no progs loaded\n");
1543                 return;
1544         }
1545         for (i = 0;i < progs->numglobaldefs;i++)
1546                 Con_Printf("%s\n", PR_GetString(pr_globaldefs[i].s_name));
1547         Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1548 }
1549
1550 /*
1551 ===============
1552 PR_Init
1553 ===============
1554 */
1555 extern void PR_Cmd_Init(void);
1556 void PR_Init (void)
1557 {
1558         Cmd_AddCommand ("edict", ED_PrintEdict_f);
1559         Cmd_AddCommand ("edicts", ED_PrintEdicts);
1560         Cmd_AddCommand ("edictcount", ED_Count);
1561         Cmd_AddCommand ("profile", PR_Profile_f);
1562         Cmd_AddCommand ("pr_fields", PR_Fields_f);
1563         Cmd_AddCommand ("pr_globals", PR_Globals_f);
1564         Cvar_RegisterVariable (&pr_checkextension);
1565         Cvar_RegisterVariable (&nomonsters);
1566         Cvar_RegisterVariable (&gamecfg);
1567         Cvar_RegisterVariable (&scratch1);
1568         Cvar_RegisterVariable (&scratch2);
1569         Cvar_RegisterVariable (&scratch3);
1570         Cvar_RegisterVariable (&scratch4);
1571         Cvar_RegisterVariable (&savedgamecfg);
1572         Cvar_RegisterVariable (&saved1);
1573         Cvar_RegisterVariable (&saved2);
1574         Cvar_RegisterVariable (&saved3);
1575         Cvar_RegisterVariable (&saved4);
1576         // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1577         Cvar_RegisterVariable (&decors);
1578         // LordHavoc: Nehahra uses these to pass data around cutscene demos
1579         if (gamemode == GAME_NEHAHRA)
1580         {
1581                 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1582                 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1583                 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1584                 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1585                 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1586                 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1587                 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1588                 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1589                 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1590                 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1591         }
1592         Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1593         // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1594         Cvar_RegisterVariable (&pr_boundscheck);
1595         Cvar_RegisterVariable (&pr_traceqc);
1596
1597         progs_mempool = Mem_AllocPool("progs.dat");
1598         edictstring_mempool = Mem_AllocPool("edict strings");
1599
1600         PR_Cmd_Init();
1601 }
1602
1603 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1604 edict_t *EDICT_NUM_ERROR(int n, char *filename, int fileline)
1605 {
1606         Host_Error ("EDICT_NUM: bad number %i (called at %s:%i)", n, filename, fileline);
1607         return NULL;
1608 }
1609
1610 /*
1611 int NUM_FOR_EDICT_ERROR(edict_t *e)
1612 {
1613         Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1614         return 0;
1615 }
1616
1617 int NUM_FOR_EDICT(edict_t *e)
1618 {
1619         int n;
1620         n = e - sv.edicts;
1621         if ((unsigned int)n >= MAX_EDICTS)
1622                 Host_Error ("NUM_FOR_EDICT: bad pointer");
1623         return n;
1624 }
1625
1626 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1627 //{
1628 //      return e - sv.edicts;
1629 //}
1630
1631 //#define       EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1632 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1633 int EDICT_TO_PROG(edict_t *e)
1634 {
1635         int n;
1636         n = e - sv.edicts;
1637         if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1638                 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1639         return n;// EXPERIMENTAL
1640         //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1641 }
1642 edict_t *PROG_TO_EDICT(int n)
1643 {
1644         if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1645                 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1646         return sv.edicts + n; // EXPERIMENTAL
1647         //return sv.edicts + ((n) / (progs->entityfields * 4));
1648 }
1649 */
1650