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