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