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