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