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