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