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