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