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