]> icculus.org git repositories - divverent/darkplaces.git/blob - pr_edict.c
changed surface->mesh to surface->groupmesh and added num_firsttriangle and num_first...
[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                         dpsnprintf (line, sizeof (line), "entity %i (invalid!)", n);
443                 else
444                         dpsnprintf (line, sizeof (line), "entity %i", n);
445                 break;
446         case ev_function:
447                 f = pr_functions + val->function;
448                 dpsnprintf (line, sizeof (line), "%s()", PR_GetString(f->s_name));
449                 break;
450         case ev_field:
451                 def = ED_FieldAtOfs ( val->_int );
452                 dpsnprintf (line, sizeof (line), ".%s", PR_GetString(def->s_name));
453                 break;
454         case ev_void:
455                 dpsnprintf (line, sizeof (line), "void");
456                 break;
457         case ev_float:
458                 // LordHavoc: changed from %5.1f to %10.4f
459                 dpsnprintf (line, sizeof (line), "%10.4f", val->_float);
460                 break;
461         case ev_vector:
462                 // LordHavoc: changed from %5.1f to %10.4f
463                 dpsnprintf (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                 dpsnprintf (line, sizeof (line), "pointer");
467                 break;
468         default:
469                 dpsnprintf (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                 dpsnprintf (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                 dpsnprintf (line, sizeof (line), ".%s", PR_GetString(def->s_name));
529                 break;
530         case ev_void:
531                 dpsnprintf (line, sizeof (line), "void");
532                 break;
533         case ev_float:
534                 dpsnprintf (line, sizeof (line), "%f", val->_float);
535                 break;
536         case ev_vector:
537                 dpsnprintf (line, sizeof (line), "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
538                 break;
539         default:
540                 dpsnprintf (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                 dpsnprintf (line, sizeof (line), "%i(?)", ofs);
567         else
568         {
569                 s = PR_ValueString (def->type, val);
570                 dpsnprintf (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                 dpsnprintf (line, sizeof (line), "%i(?)", ofs);
590         else
591                 dpsnprintf (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         dpsnprintf (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                         dpsnprintf (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 (gamemode != GAME_TRANSFUSION) //Transfusion does this in QC
1171                 {
1172                         if (deathmatch.integer)
1173                         {
1174                                 if (((int)ent->v->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1175                                 {
1176                                         ED_Free (ent);
1177                                         inhibited++;
1178                                         continue;
1179                                 }
1180                         }
1181                         else if ((current_skill <= 0 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_EASY  ))
1182                                 || (current_skill == 1 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_MEDIUM))
1183                                 || (current_skill >= 2 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_HARD  )))
1184                         {
1185                                 ED_Free (ent);
1186                                 inhibited++;
1187                                 continue;
1188                         }
1189                 }
1190 //
1191 // immediately call spawn function
1192 //
1193                 if (!ent->v->classname)
1194                 {
1195                         Con_Print("No classname for:\n");
1196                         ED_Print(ent);
1197                         ED_Free (ent);
1198                         continue;
1199                 }
1200
1201         // look for the spawn function
1202                 func = ED_FindFunction (PR_GetString(ent->v->classname));
1203
1204                 if (!func)
1205                 {
1206                         if (developer.integer) // don't confuse non-developers with errors
1207                         {
1208                                 Con_Print("No spawn function for:\n");
1209                                 ED_Print(ent);
1210                         }
1211                         ED_Free (ent);
1212                         continue;
1213                 }
1214
1215                 pr_global_struct->self = EDICT_TO_PROG(ent);
1216                 PR_ExecuteProgram (func - pr_functions, "QC function spawn is missing");
1217                 spawned++;
1218                 if (ent->e->free)
1219                         died++;
1220         }
1221
1222         Con_DPrintf("%i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", parsed, inhibited, spawned, died, spawned - died);
1223 }
1224
1225
1226 typedef struct dpfield_s
1227 {
1228         int type;
1229         char *string;
1230 }
1231 dpfield_t;
1232
1233 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1234
1235 dpfield_t dpfields[] =
1236 {
1237         {ev_entity, "cursor_trace_ent"},
1238         {ev_entity, "drawonlytoclient"},
1239         {ev_entity, "exteriormodeltoclient"},
1240         {ev_entity, "nodrawtoclient"},
1241         {ev_entity, "tag_entity"},
1242         {ev_entity, "viewmodelforclient"},
1243         {ev_float, "alpha"},
1244         {ev_float, "ammo_cells1"},
1245         {ev_float, "ammo_lava_nails"},
1246         {ev_float, "ammo_multi_rockets"},
1247         {ev_float, "ammo_nails1"},
1248         {ev_float, "ammo_plasma"},
1249         {ev_float, "ammo_rockets1"},
1250         {ev_float, "ammo_shells1"},
1251         {ev_float, "button3"},
1252         {ev_float, "button4"},
1253         {ev_float, "button5"},
1254         {ev_float, "button6"},
1255         {ev_float, "button7"},
1256         {ev_float, "button8"},
1257         {ev_float, "buttonchat"},
1258         {ev_float, "buttonuse"},
1259         {ev_float, "clientcolors"},
1260         {ev_float, "cursor_active"},
1261         {ev_float, "fullbright"},
1262         {ev_float, "glow_color"},
1263         {ev_float, "glow_size"},
1264         {ev_float, "glow_trail"},
1265         {ev_float, "gravity"},
1266         {ev_float, "idealpitch"},
1267         {ev_float, "items2"},
1268         {ev_float, "light_lev"},
1269         {ev_float, "pflags"},
1270         {ev_float, "ping"},
1271         {ev_float, "pitch_speed"},
1272         {ev_float, "pmodel"},
1273         {ev_float, "renderamt"}, // HalfLife support
1274         {ev_float, "rendermode"}, // HalfLife support
1275         {ev_float, "scale"},
1276         {ev_float, "style"},
1277         {ev_float, "tag_index"},
1278         {ev_float, "viewzoom"},
1279         {ev_vector, "color"},
1280         {ev_vector, "colormod"},
1281         {ev_vector, "cursor_screen"},
1282         {ev_vector, "cursor_trace_endpos"},
1283         {ev_vector, "cursor_trace_start"},
1284         {ev_vector, "movement"},
1285         {ev_vector, "punchvector"},
1286         {ev_string, "playermodel"},
1287         {ev_string, "playerskin"}
1288 };
1289
1290 /*
1291 ===============
1292 PR_LoadProgs
1293 ===============
1294 */
1295 extern void PR_Cmd_Reset (void);
1296 void PR_LoadProgs (const char *progsname)
1297 {
1298         int i;
1299         dstatement_t *st;
1300         ddef_t *infielddefs;
1301         dfunction_t *dfunctions;
1302
1303         if (!progsname || !*progsname)
1304                 Host_Error("PR_LoadProgs: passed empty progsname");
1305
1306 // flush the non-C variable lookup cache
1307         for (i=0 ; i<GEFV_CACHESIZE ; i++)
1308                 gefvCache[i].field[0] = 0;
1309
1310         Mem_EmptyPool(progs_mempool);
1311         Mem_EmptyPool(edictstring_mempool);
1312
1313         progs = (dprograms_t *)FS_LoadFile (progsname, progs_mempool, false);
1314         if (!progs)
1315                 Host_Error ("PR_LoadProgs: couldn't load %s", progsname);
1316
1317         Con_DPrintf("Programs occupy %iK.\n", fs_filesize/1024);
1318
1319         pr_crc = CRC_Block((qbyte *)progs, fs_filesize);
1320
1321 // byte swap the header
1322         for (i = 0;i < (int) sizeof(*progs) / 4;i++)
1323                 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1324
1325         if (progs->version != PROG_VERSION)
1326                 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1327         if (progs->crc != PROGHEADER_CRC && progs->crc != 32401) // tenebrae crc also allowed
1328                 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1329
1330         //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1331         dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1332         pr_strings = (char *)progs + progs->ofs_strings;
1333         pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1334
1335         // we need to expand the fielddefs list to include all the engine fields,
1336         // so allocate a new place for it
1337         infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1338         pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1339
1340         pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1341
1342         // moved edict_size calculation down below field adding code
1343
1344         pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1345         pr_globals = (float *)pr_global_struct;
1346
1347 // byte swap the lumps
1348         for (i=0 ; i<progs->numstatements ; i++)
1349         {
1350                 pr_statements[i].op = LittleShort(pr_statements[i].op);
1351                 pr_statements[i].a = LittleShort(pr_statements[i].a);
1352                 pr_statements[i].b = LittleShort(pr_statements[i].b);
1353                 pr_statements[i].c = LittleShort(pr_statements[i].c);
1354         }
1355
1356         pr_functions = Mem_Alloc(progs_mempool, sizeof(mfunction_t) * progs->numfunctions);
1357         for (i = 0;i < progs->numfunctions;i++)
1358         {
1359                 pr_functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1360                 pr_functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1361                 pr_functions[i].s_name = LittleLong (dfunctions[i].s_name);
1362                 pr_functions[i].s_file = LittleLong (dfunctions[i].s_file);
1363                 pr_functions[i].numparms = LittleLong (dfunctions[i].numparms);
1364                 pr_functions[i].locals = LittleLong (dfunctions[i].locals);
1365                 memcpy(pr_functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1366         }
1367
1368         for (i=0 ; i<progs->numglobaldefs ; i++)
1369         {
1370                 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1371                 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1372                 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1373         }
1374
1375         // copy the progs fields to the new fields list
1376         for (i = 0;i < progs->numfielddefs;i++)
1377         {
1378                 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1379                 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1380                         Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1381                 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1382                 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1383         }
1384
1385         // append the darkplaces fields
1386         for (i = 0;i < (int) DPFIELDS;i++)
1387         {
1388                 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1389                 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1390                 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1391                 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1392                         progs->entityfields += 3;
1393                 else
1394                         progs->entityfields++;
1395                 progs->numfielddefs++;
1396         }
1397
1398         for (i=0 ; i<progs->numglobals ; i++)
1399                 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1400
1401         // moved edict_size calculation down here, below field adding code
1402         // LordHavoc: this no longer includes the edict_t header
1403         pr_edict_size = progs->entityfields * 4;
1404         pr_edictareasize = pr_edict_size * MAX_EDICTS;
1405
1406         // LordHavoc: bounds check anything static
1407         for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1408         {
1409                 switch (st->op)
1410                 {
1411                 case OP_IF:
1412                 case OP_IFNOT:
1413                         if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1414                                 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1415                         break;
1416                 case OP_GOTO:
1417                         if (st->a + i < 0 || st->a + i >= progs->numstatements)
1418                                 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1419                         break;
1420                 // global global global
1421                 case OP_ADD_F:
1422                 case OP_ADD_V:
1423                 case OP_SUB_F:
1424                 case OP_SUB_V:
1425                 case OP_MUL_F:
1426                 case OP_MUL_V:
1427                 case OP_MUL_FV:
1428                 case OP_MUL_VF:
1429                 case OP_DIV_F:
1430                 case OP_BITAND:
1431                 case OP_BITOR:
1432                 case OP_GE:
1433                 case OP_LE:
1434                 case OP_GT:
1435                 case OP_LT:
1436                 case OP_AND:
1437                 case OP_OR:
1438                 case OP_EQ_F:
1439                 case OP_EQ_V:
1440                 case OP_EQ_S:
1441                 case OP_EQ_E:
1442                 case OP_EQ_FNC:
1443                 case OP_NE_F:
1444                 case OP_NE_V:
1445                 case OP_NE_S:
1446                 case OP_NE_E:
1447                 case OP_NE_FNC:
1448                 case OP_ADDRESS:
1449                 case OP_LOAD_F:
1450                 case OP_LOAD_FLD:
1451                 case OP_LOAD_ENT:
1452                 case OP_LOAD_S:
1453                 case OP_LOAD_FNC:
1454                 case OP_LOAD_V:
1455                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1456                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1457                         break;
1458                 // global none global
1459                 case OP_NOT_F:
1460                 case OP_NOT_V:
1461                 case OP_NOT_S:
1462                 case OP_NOT_FNC:
1463                 case OP_NOT_ENT:
1464                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1465                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1466                         break;
1467                 // 2 globals
1468                 case OP_STOREP_F:
1469                 case OP_STOREP_ENT:
1470                 case OP_STOREP_FLD:
1471                 case OP_STOREP_S:
1472                 case OP_STOREP_FNC:
1473                 case OP_STORE_F:
1474                 case OP_STORE_ENT:
1475                 case OP_STORE_FLD:
1476                 case OP_STORE_S:
1477                 case OP_STORE_FNC:
1478                 case OP_STATE:
1479                 case OP_STOREP_V:
1480                 case OP_STORE_V:
1481                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1482                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1483                         break;
1484                 // 1 global
1485                 case OP_CALL0:
1486                 case OP_CALL1:
1487                 case OP_CALL2:
1488                 case OP_CALL3:
1489                 case OP_CALL4:
1490                 case OP_CALL5:
1491                 case OP_CALL6:
1492                 case OP_CALL7:
1493                 case OP_CALL8:
1494                 case OP_DONE:
1495                 case OP_RETURN:
1496                         if ((unsigned short) st->a >= progs->numglobals)
1497                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1498                         break;
1499                 default:
1500                         Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1501                         break;
1502                 }
1503         }
1504
1505         FindEdictFieldOffsets(); // LordHavoc: update field offset list
1506         PR_Execute_ProgsLoaded();
1507         PR_Cmd_Reset();
1508 }
1509
1510
1511 void PR_Fields_f (void)
1512 {
1513         int i, j, ednum, used, usedamount;
1514         int *counts;
1515         char tempstring[5000], tempstring2[260], *name;
1516         edict_t *ed;
1517         ddef_t *d;
1518         int *v;
1519         if (!sv.active)
1520         {
1521                 Con_Print("no progs loaded\n");
1522                 return;
1523         }
1524         counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1525         for (ednum = 0;ednum < sv.max_edicts;ednum++)
1526         {
1527                 ed = EDICT_NUM(ednum);
1528                 if (ed->e->free)
1529                         continue;
1530                 for (i = 1;i < progs->numfielddefs;i++)
1531                 {
1532                         d = &pr_fielddefs[i];
1533                         name = PR_GetString(d->s_name);
1534                         if (name[strlen(name)-2] == '_')
1535                                 continue;       // skip _x, _y, _z vars
1536                         v = (int *)((char *)ed->v + d->ofs*4);
1537                         // if the value is still all 0, skip the field
1538                         for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1539                         {
1540                                 if (v[j])
1541                                 {
1542                                         counts[i]++;
1543                                         break;
1544                                 }
1545                         }
1546                 }
1547         }
1548         used = 0;
1549         usedamount = 0;
1550         tempstring[0] = 0;
1551         for (i = 0;i < progs->numfielddefs;i++)
1552         {
1553                 d = &pr_fielddefs[i];
1554                 name = PR_GetString(d->s_name);
1555                 if (name[strlen(name)-2] == '_')
1556                         continue;       // skip _x, _y, _z vars
1557                 switch(d->type & ~DEF_SAVEGLOBAL)
1558                 {
1559                 case ev_string:
1560                         strlcat (tempstring, "string   ", sizeof (tempstring));
1561                         break;
1562                 case ev_entity:
1563                         strlcat (tempstring, "entity   ", sizeof (tempstring));
1564                         break;
1565                 case ev_function:
1566                         strlcat (tempstring, "function ", sizeof (tempstring));
1567                         break;
1568                 case ev_field:
1569                         strlcat (tempstring, "field    ", sizeof (tempstring));
1570                         break;
1571                 case ev_void:
1572                         strlcat (tempstring, "void     ", sizeof (tempstring));
1573                         break;
1574                 case ev_float:
1575                         strlcat (tempstring, "float    ", sizeof (tempstring));
1576                         break;
1577                 case ev_vector:
1578                         strlcat (tempstring, "vector   ", sizeof (tempstring));
1579                         break;
1580                 case ev_pointer:
1581                         strlcat (tempstring, "pointer  ", sizeof (tempstring));
1582                         break;
1583                 default:
1584                         dpsnprintf (tempstring2, sizeof (tempstring2), "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1585                         strlcat (tempstring, tempstring2, sizeof (tempstring));
1586                         break;
1587                 }
1588                 if (strlen(name) > 256)
1589                 {
1590                         memcpy(tempstring2, name, 256);
1591                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1592                         tempstring2[259] = 0;
1593                         name = tempstring2;
1594                 }
1595                 strcat (tempstring, name);
1596                 for (j = strlen(name);j < 25;j++)
1597                         strcat(tempstring, " ");
1598                 dpsnprintf (tempstring2, sizeof (tempstring2), "%5d", counts[i]);
1599                 strlcat (tempstring, tempstring2, sizeof (tempstring));
1600                 strlcat (tempstring, "\n", sizeof (tempstring));
1601                 if (strlen(tempstring) >= 4096)
1602                 {
1603                         Con_Print(tempstring);
1604                         tempstring[0] = 0;
1605                 }
1606                 if (counts[i])
1607                 {
1608                         used++;
1609                         usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1610                 }
1611         }
1612         Mem_Free(counts);
1613         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);
1614 }
1615
1616 void PR_Globals_f (void)
1617 {
1618         int i;
1619         if (!sv.active)
1620         {
1621                 Con_Print("no progs loaded\n");
1622                 return;
1623         }
1624         for (i = 0;i < progs->numglobaldefs;i++)
1625                 Con_Printf("%s\n", PR_GetString(pr_globaldefs[i].s_name));
1626         Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1627 }
1628
1629 /*
1630 ===============
1631 PR_Init
1632 ===============
1633 */
1634 extern void PR_Cmd_Init(void);
1635 void PR_Init (void)
1636 {
1637         Cmd_AddCommand ("edict", ED_PrintEdict_f);
1638         Cmd_AddCommand ("edicts", ED_PrintEdicts);
1639         Cmd_AddCommand ("edictcount", ED_Count);
1640         Cmd_AddCommand ("edictset", ED_EdictSet_f);
1641         Cmd_AddCommand ("profile", PR_Profile_f);
1642         Cmd_AddCommand ("pr_fields", PR_Fields_f);
1643         Cmd_AddCommand ("pr_globals", PR_Globals_f);
1644         Cvar_RegisterVariable (&pr_checkextension);
1645         Cvar_RegisterVariable (&nomonsters);
1646         Cvar_RegisterVariable (&gamecfg);
1647         Cvar_RegisterVariable (&scratch1);
1648         Cvar_RegisterVariable (&scratch2);
1649         Cvar_RegisterVariable (&scratch3);
1650         Cvar_RegisterVariable (&scratch4);
1651         Cvar_RegisterVariable (&savedgamecfg);
1652         Cvar_RegisterVariable (&saved1);
1653         Cvar_RegisterVariable (&saved2);
1654         Cvar_RegisterVariable (&saved3);
1655         Cvar_RegisterVariable (&saved4);
1656         // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1657         Cvar_RegisterVariable (&decors);
1658         // LordHavoc: Nehahra uses these to pass data around cutscene demos
1659         if (gamemode == GAME_NEHAHRA)
1660         {
1661                 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1662                 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1663                 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1664                 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1665                 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1666                 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1667                 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1668                 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1669                 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1670                 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1671         }
1672         Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1673         // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1674         Cvar_RegisterVariable (&pr_boundscheck);
1675         Cvar_RegisterVariable (&pr_traceqc);
1676
1677         progs_mempool = Mem_AllocPool("progs.dat", 0, NULL);
1678         edictstring_mempool = Mem_AllocPool("edict strings", 0, NULL);
1679
1680         PR_Cmd_Init();
1681 }
1682
1683 /*
1684 ===============
1685 PR_Shutdown
1686 ===============
1687 */
1688 extern void PR_Cmd_Shutdown(void);
1689 void PR_Shutdown (void)
1690 {
1691         PR_Cmd_Shutdown();
1692
1693         Mem_FreePool(&edictstring_mempool);
1694         Mem_FreePool(&progs_mempool);
1695 }
1696
1697 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1698 edict_t *EDICT_NUM_ERROR(int n, char *filename, int fileline)
1699 {
1700         Host_Error ("EDICT_NUM: bad number %i (called at %s:%i)", n, filename, fileline);
1701         return NULL;
1702 }
1703
1704 /*
1705 int NUM_FOR_EDICT_ERROR(edict_t *e)
1706 {
1707         Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1708         return 0;
1709 }
1710
1711 int NUM_FOR_EDICT(edict_t *e)
1712 {
1713         int n;
1714         n = e - sv.edicts;
1715         if ((unsigned int)n >= MAX_EDICTS)
1716                 Host_Error ("NUM_FOR_EDICT: bad pointer");
1717         return n;
1718 }
1719
1720 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1721 //{
1722 //      return e - sv.edicts;
1723 //}
1724
1725 //#define       EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1726 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1727 int EDICT_TO_PROG(edict_t *e)
1728 {
1729         int n;
1730         n = e - sv.edicts;
1731         if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1732                 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1733         return n;// EXPERIMENTAL
1734         //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1735 }
1736 edict_t *PROG_TO_EDICT(int n)
1737 {
1738         if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1739                 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1740         return sv.edicts + n; // EXPERIMENTAL
1741         //return sv.edicts + ((n) / (progs->entityfields * 4));
1742 }
1743 */
1744