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