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