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