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