]> icculus.org git repositories - divverent/darkplaces.git/blob - pr_edict.c
added collision.c, cl_collision.c. collision.h, cl_collision.h
[divverent/darkplaces.git] / pr_edict.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // sv_edict.c -- entity dictionary
21
22 #include "quakedef.h"
23
24 dprograms_t             *progs;
25 dfunction_t             *pr_functions;
26 char                    *pr_strings;
27 ddef_t                  *pr_fielddefs;
28 ddef_t                  *pr_globaldefs;
29 dstatement_t    *pr_statements;
30 globalvars_t    *pr_global_struct;
31 float                   *pr_globals;                    // same as pr_global_struct
32 int                             pr_edict_size;                  // in bytes
33 int                             pr_edictareasize;               // LordHavoc: in bytes
34
35 unsigned short  pr_crc;
36
37 mempool_t               *progs_mempool;
38 mempool_t               *edictstring_mempool;
39
40 int             type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
41
42 ddef_t *ED_FieldAtOfs (int ofs);
43 qboolean        ED_ParseEpair (void *base, ddef_t *key, char *s);
44
45 cvar_t  pr_checkextension = {0, "pr_checkextension", "1"};
46 cvar_t  nomonsters = {0, "nomonsters", "0"};
47 cvar_t  gamecfg = {0, "gamecfg", "0"};
48 cvar_t  scratch1 = {0, "scratch1", "0"};
49 cvar_t  scratch2 = {0,"scratch2", "0"};
50 cvar_t  scratch3 = {0, "scratch3", "0"};
51 cvar_t  scratch4 = {0, "scratch4", "0"};
52 cvar_t  savedgamecfg = {CVAR_SAVE, "savedgamecfg", "0"};
53 cvar_t  saved1 = {CVAR_SAVE, "saved1", "0"};
54 cvar_t  saved2 = {CVAR_SAVE, "saved2", "0"};
55 cvar_t  saved3 = {CVAR_SAVE, "saved3", "0"};
56 cvar_t  saved4 = {CVAR_SAVE, "saved4", "0"};
57 cvar_t  decors = {0, "decors", "0"};
58 cvar_t  nehx00 = {0, "nehx00", "0"};cvar_t      nehx01 = {0, "nehx01", "0"};
59 cvar_t  nehx02 = {0, "nehx02", "0"};cvar_t      nehx03 = {0, "nehx03", "0"};
60 cvar_t  nehx04 = {0, "nehx04", "0"};cvar_t      nehx05 = {0, "nehx05", "0"};
61 cvar_t  nehx06 = {0, "nehx06", "0"};cvar_t      nehx07 = {0, "nehx07", "0"};
62 cvar_t  nehx08 = {0, "nehx08", "0"};cvar_t      nehx09 = {0, "nehx09", "0"};
63 cvar_t  nehx10 = {0, "nehx10", "0"};cvar_t      nehx11 = {0, "nehx11", "0"};
64 cvar_t  nehx12 = {0, "nehx12", "0"};cvar_t      nehx13 = {0, "nehx13", "0"};
65 cvar_t  nehx14 = {0, "nehx14", "0"};cvar_t      nehx15 = {0, "nehx15", "0"};
66 cvar_t  nehx16 = {0, "nehx16", "0"};cvar_t      nehx17 = {0, "nehx17", "0"};
67 cvar_t  nehx18 = {0, "nehx18", "0"};cvar_t      nehx19 = {0, "nehx19", "0"};
68 cvar_t  cutscene = {0, "cutscene", "1"};
69 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
70 cvar_t  pr_boundscheck = {0, "pr_boundscheck", "1"};
71
72 #define MAX_FIELD_LEN   64
73 #define GEFV_CACHESIZE  2
74
75 typedef struct {
76         ddef_t  *pcache;
77         char    field[MAX_FIELD_LEN];
78 } gefv_cache;
79
80 static gefv_cache       gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};
81
82 ddef_t *ED_FindField (char *name);
83 dfunction_t *ED_FindFunction (char *name);
84
85 // LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue...  these are defined as externs in progs.h
86 int eval_gravity;
87 int eval_button3;
88 int eval_button4;
89 int eval_button5;
90 int eval_button6;
91 int eval_button7;
92 int eval_button8;
93 int eval_glow_size;
94 int eval_glow_trail;
95 int eval_glow_color;
96 int eval_items2;
97 int eval_scale;
98 int eval_alpha;
99 int eval_renderamt; // HalfLife support
100 int eval_rendermode; // HalfLife support
101 int eval_fullbright;
102 int eval_ammo_shells1;
103 int eval_ammo_nails1;
104 int eval_ammo_lava_nails;
105 int eval_ammo_rockets1;
106 int eval_ammo_multi_rockets;
107 int eval_ammo_cells1;
108 int eval_ammo_plasma;
109 int eval_idealpitch;
110 int eval_pitch_speed;
111 int eval_viewmodelforclient;
112 int eval_nodrawtoclient;
113 int eval_exteriormodeltoclient;
114 int eval_drawonlytoclient;
115 int eval_ping;
116 int eval_movement;
117 int eval_pmodel;
118 int eval_punchvector;
119 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[4096];
456         int i;
457         char *s;
458         ddef_t *def;
459         dfunction_t *f;
460
461         type &= ~DEF_SAVEGLOBAL;
462
463         switch (type)
464         {
465         case ev_string:
466                 sprintf (line, "%s", pr_strings + val->string);
467                 break;
468         case ev_entity:
469                 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
470                 break;
471         case ev_function:
472                 f = pr_functions + val->function;
473                 sprintf (line, "%s", pr_strings + f->s_name);
474                 break;
475         case ev_field:
476                 def = ED_FieldAtOfs ( val->_int );
477                 // LordHavoc: parse the string a bit to turn special characters
478                 // (like newline, specifically) into escape codes,
479                 // this fixes saving games from various mods
480                 //sprintf (line, "%s", pr_strings + def->s_name);
481                 s = pr_strings + def->s_name;
482                 for (i = 0;i < 4095 && *s;)
483                 {
484                         if (*s == '\n')
485                         {
486                                 line[i++] = '\\';
487                                 line[i++] = 'n';
488                         }
489                         else if (*s == '\r')
490                         {
491                                 line[i++] = '\\';
492                                 line[i++] = 'r';
493                         }
494                         else
495                                 line[i] = *s;
496                         s++;
497                 }
498                 line[i++] = 0;
499                 break;
500         case ev_void:
501                 sprintf (line, "void");
502                 break;
503         case ev_float:
504                 sprintf (line, "%f", val->_float);
505                 break;
506         case ev_vector:
507                 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
508                 break;
509         default:
510                 sprintf (line, "bad type %i", type);
511                 break;
512         }
513
514         return line;
515 }
516
517 /*
518 ============
519 PR_GlobalString
520
521 Returns a string with a description and the contents of a global,
522 padded to 20 field width
523 ============
524 */
525 char *PR_GlobalString (int ofs)
526 {
527         char    *s;
528         int             i;
529         ddef_t  *def;
530         void    *val;
531         static char     line[128];
532
533         val = (void *)&pr_globals[ofs];
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         {
539                 s = PR_ValueString (def->type, val);
540                 sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s);
541         }
542
543         i = strlen(line);
544         for ( ; i<20 ; i++)
545                 strcat (line," ");
546         strcat (line," ");
547
548         return line;
549 }
550
551 char *PR_GlobalStringNoContents (int ofs)
552 {
553         int             i;
554         ddef_t  *def;
555         static char     line[128];
556
557         def = ED_GlobalAtOfs(ofs);
558         if (!def)
559                 sprintf (line,"%i(\?\?\?)", ofs); // LordHavoc: escaping the ?s so it is not a trigraph
560         else
561                 sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name);
562
563         i = strlen(line);
564         for ( ; i<20 ; i++)
565                 strcat (line," ");
566         strcat (line," ");
567
568         return line;
569 }
570
571
572 /*
573 =============
574 ED_Print
575
576 For debugging
577 =============
578 */
579 // LordHavoc: optimized this to print out much more quickly (tempstring)
580 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
581 void ED_Print (edict_t *ed)
582 {
583         int             l;
584         ddef_t  *d;
585         int             *v;
586         int             i, j;
587         char    *name;
588         int             type;
589         char    tempstring[8192], tempstring2[260]; // temporary string buffers
590
591         if (ed->free)
592         {
593                 Con_Printf ("FREE\n");
594                 return;
595         }
596
597         tempstring[0] = 0;
598         sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
599         for (i=1 ; i<progs->numfielddefs ; i++)
600         {
601                 d = &pr_fielddefs[i];
602                 name = pr_strings + d->s_name;
603                 if (name[strlen(name)-2] == '_')
604                         continue;       // skip _x, _y, _z vars
605
606                 v = (int *)((char *)&ed->v + d->ofs*4);
607
608         // if the value is still all 0, skip the field
609                 type = d->type & ~DEF_SAVEGLOBAL;
610
611                 for (j=0 ; j<type_size[type] ; j++)
612                         if (v[j])
613                                 break;
614                 if (j == type_size[type])
615                         continue;
616
617                 if (strlen(name) > 256)
618                 {
619                         strncpy(tempstring2, name, 256);
620                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
621                         tempstring2[259] = 0;
622                         name = tempstring2;
623                 }
624                 strcat(tempstring, name);
625                 for (l = strlen(name);l < 14;l++)
626                         strcat(tempstring, " ");
627                 strcat(tempstring, " ");
628
629                 name = PR_ValueString(d->type, (eval_t *)v);
630                 if (strlen(name) > 256)
631                 {
632                         strncpy(tempstring2, name, 256);
633                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
634                         tempstring2[259] = 0;
635                         name = tempstring2;
636                 }
637                 strcat(tempstring, name);
638                 strcat(tempstring, "\n");
639                 if (strlen(tempstring) >= 4096)
640                 {
641                         Con_Printf("%s", tempstring);
642                         tempstring[0] = 0;
643                 }
644         }
645         if (tempstring[0])
646                 Con_Printf("%s", tempstring);
647 }
648
649 /*
650 =============
651 ED_Write
652
653 For savegames
654 =============
655 */
656 void ED_Write (QFile *f, edict_t *ed)
657 {
658         ddef_t  *d;
659         int             *v;
660         int             i, j;
661         char    *name;
662         int             type;
663
664         Qprintf (f, "{\n");
665
666         if (ed->free)
667         {
668                 Qprintf (f, "}\n");
669                 return;
670         }
671
672         for (i=1 ; i<progs->numfielddefs ; i++)
673         {
674                 d = &pr_fielddefs[i];
675                 name = pr_strings + d->s_name;
676                 if (name[strlen(name)-2] == '_')
677                         continue;       // skip _x, _y, _z vars
678
679                 v = (int *)((char *)&ed->v + d->ofs*4);
680
681         // if the value is still all 0, skip the field
682                 type = d->type & ~DEF_SAVEGLOBAL;
683                 for (j=0 ; j<type_size[type] ; j++)
684                         if (v[j])
685                                 break;
686                 if (j == type_size[type])
687                         continue;
688
689                 Qprintf (f,"\"%s\" ",name);
690                 Qprintf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
691         }
692
693         Qprintf (f, "}\n");
694 }
695
696 void ED_PrintNum (int ent)
697 {
698         ED_Print (EDICT_NUM(ent));
699 }
700
701 /*
702 =============
703 ED_PrintEdicts
704
705 For debugging, prints all the entities in the current server
706 =============
707 */
708 void ED_PrintEdicts (void)
709 {
710         int             i;
711
712         Con_Printf ("%i entities\n", sv.num_edicts);
713         for (i=0 ; i<sv.num_edicts ; i++)
714                 ED_PrintNum (i);
715 }
716
717 /*
718 =============
719 ED_PrintEdict_f
720
721 For debugging, prints a single edicy
722 =============
723 */
724 void ED_PrintEdict_f (void)
725 {
726         int             i;
727
728         i = atoi (Cmd_Argv(1));
729         if (i >= sv.num_edicts)
730         {
731                 Con_Printf("Bad edict number\n");
732                 return;
733         }
734         ED_PrintNum (i);
735 }
736
737 /*
738 =============
739 ED_Count
740
741 For debugging
742 =============
743 */
744 void ED_Count (void)
745 {
746         int             i;
747         edict_t *ent;
748         int             active, models, solid, step;
749
750         active = models = solid = step = 0;
751         for (i=0 ; i<sv.num_edicts ; i++)
752         {
753                 ent = EDICT_NUM(i);
754                 if (ent->free)
755                         continue;
756                 active++;
757                 if (ent->v.solid)
758                         solid++;
759                 if (ent->v.model)
760                         models++;
761                 if (ent->v.movetype == MOVETYPE_STEP)
762                         step++;
763         }
764
765         Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
766         Con_Printf ("active    :%3i\n", active);
767         Con_Printf ("view      :%3i\n", models);
768         Con_Printf ("touch     :%3i\n", solid);
769         Con_Printf ("step      :%3i\n", step);
770
771 }
772
773 /*
774 ==============================================================================
775
776                                         ARCHIVING GLOBALS
777
778 FIXME: need to tag constants, doesn't really work
779 ==============================================================================
780 */
781
782 /*
783 =============
784 ED_WriteGlobals
785 =============
786 */
787 void ED_WriteGlobals (QFile *f)
788 {
789         ddef_t          *def;
790         int                     i;
791         char            *name;
792         int                     type;
793
794         Qprintf (f,"{\n");
795         for (i=0 ; i<progs->numglobaldefs ; i++)
796         {
797                 def = &pr_globaldefs[i];
798                 type = def->type;
799                 if ( !(def->type & DEF_SAVEGLOBAL) )
800                         continue;
801                 type &= ~DEF_SAVEGLOBAL;
802
803                 if (type != ev_string && type != ev_float && type != ev_entity)
804                         continue;
805
806                 name = pr_strings + def->s_name;                
807                 Qprintf (f,"\"%s\" ", name);
808                 Qprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));              
809         }
810         Qprintf (f,"}\n");
811 }
812
813 /*
814 =============
815 ED_ParseGlobals
816 =============
817 */
818 void ED_ParseGlobals (char *data)
819 {
820         char    keyname[1024]; // LordHavoc: good idea? bad idea?  was 64
821         ddef_t  *key;
822
823         while (1)
824         {       
825         // parse key
826                 data = COM_Parse (data);
827                 if (com_token[0] == '}')
828                         break;
829                 if (!data)
830                         Host_Error ("ED_ParseEntity: EOF without closing brace");
831
832                 strcpy (keyname, com_token);
833
834         // parse value
835                 data = COM_Parse (data);
836                 if (!data)
837                         Host_Error ("ED_ParseEntity: EOF without closing brace");
838
839                 if (com_token[0] == '}')
840                         Host_Error ("ED_ParseEntity: closing brace without data");
841
842                 key = ED_FindGlobal (keyname);
843                 if (!key)
844                 {
845                         Con_DPrintf ("'%s' is not a global\n", keyname);
846                         continue;
847                 }
848
849                 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
850                         Host_Error ("ED_ParseGlobals: parse error");
851         }
852 }
853
854 //============================================================================
855
856
857 /*
858 =============
859 ED_NewString
860 =============
861 */
862 char *ED_NewString (char *string)
863 {
864         char    *new, *new_p;
865         int             i,l;
866
867         l = strlen(string) + 1;
868         new = Mem_Alloc(edictstring_mempool, l);
869         new_p = new;
870
871         for (i=0 ; i< l ; i++)
872         {
873                 if (string[i] == '\\' && i < l-1)
874                 {
875                         i++;
876                         if (string[i] == 'n')
877                                 *new_p++ = '\n';
878                         else
879                                 *new_p++ = '\\';
880                 }
881                 else
882                         *new_p++ = string[i];
883         }
884
885         return new;
886 }
887
888
889 /*
890 =============
891 ED_ParseEval
892
893 Can parse either fields or globals
894 returns false if error
895 =============
896 */
897 qboolean        ED_ParseEpair (void *base, ddef_t *key, char *s)
898 {
899         int             i;
900         char    string[128];
901         ddef_t  *def;
902         char    *v, *w;
903         void    *d;
904         dfunction_t     *func;
905
906         d = (void *)((int *)base + key->ofs);
907
908         switch (key->type & ~DEF_SAVEGLOBAL)
909         {
910         case ev_string:
911                 *(string_t *)d = ED_NewString (s) - pr_strings;
912                 break;
913                 
914         case ev_float:
915                 *(float *)d = atof (s);
916                 break;
917                 
918         case ev_vector:
919                 strcpy (string, s);
920                 v = string;
921                 w = string;
922                 for (i=0 ; i<3 ; i++)
923                 {
924                         while (*v && *v != ' ')
925                                 v++;
926                         *v = 0;
927                         ((float *)d)[i] = atof (w);
928                         w = v = v+1;
929                 }
930                 break;
931
932         case ev_entity:
933                 *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
934                 break;
935                 
936         case ev_field:
937                 def = ED_FindField (s);
938                 if (!def)
939                 {
940                         // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
941                         if (strcmp(s, "sky") && strcmp(s, "fog") && strncmp(s, "fog_", 4) && strcmp(s, "farclip"))
942                                 Con_DPrintf ("Can't find field %s\n", s);
943                         return false;
944                 }
945                 *(int *)d = G_INT(def->ofs);
946                 break;
947         
948         case ev_function:
949                 func = ED_FindFunction (s);
950                 if (!func)
951                 {
952                         Con_DPrintf ("Can't find function %s\n", s);
953                         return false;
954                 }
955                 *(func_t *)d = func - pr_functions;
956                 break;
957
958         default:
959                 break;
960         }
961         return true;
962 }
963
964 /*
965 ====================
966 ED_ParseEdict
967
968 Parses an edict out of the given string, returning the new position
969 ed should be a properly initialized empty edict.
970 Used for initial level load and for savegames.
971 ====================
972 */
973 char *ED_ParseEdict (char *data, edict_t *ent)
974 {
975         ddef_t          *key;
976         qboolean        anglehack;
977         qboolean        init;
978         char            keyname[256];
979         int                     n;
980
981         init = false;
982
983 // clear it
984         if (ent != sv.edicts)   // hack
985                 memset (&ent->v, 0, progs->entityfields * 4);
986
987 // go through all the dictionary pairs
988         while (1)
989         {
990         // parse key
991                 data = COM_Parse (data);
992                 if (com_token[0] == '}')
993                         break;
994                 if (!data)
995                         Host_Error ("ED_ParseEntity: EOF without closing brace");
996
997                 // anglehack is to allow QuakeEd to write single scalar angles
998                 // and allow them to be turned into vectors. (FIXME...)
999                 if (!strcmp(com_token, "angle"))
1000                 {
1001                         strcpy (com_token, "angles");
1002                         anglehack = true;
1003                 }
1004                 else
1005                         anglehack = false;
1006
1007                 // FIXME: change light to _light to get rid of this hack
1008                 if (!strcmp(com_token, "light"))
1009                         strcpy (com_token, "light_lev");        // hack for single light def
1010
1011                 strcpy (keyname, com_token);
1012
1013                 // another hack to fix heynames with trailing spaces
1014                 n = strlen(keyname);
1015                 while (n && keyname[n-1] == ' ')
1016                 {
1017                         keyname[n-1] = 0;
1018                         n--;
1019                 }
1020
1021         // parse value
1022                 data = COM_Parse (data);
1023                 if (!data)
1024                         Host_Error ("ED_ParseEntity: EOF without closing brace");
1025
1026                 if (com_token[0] == '}')
1027                         Host_Error ("ED_ParseEntity: closing brace without data");
1028
1029                 init = true;
1030
1031 // keynames with a leading underscore are used for utility comments,
1032 // and are immediately discarded by quake
1033                 if (keyname[0] == '_')
1034                         continue;
1035
1036                 key = ED_FindField (keyname);
1037                 if (!key)
1038                 {
1039                         Con_DPrintf ("'%s' is not a field\n", keyname);
1040                         continue;
1041                 }
1042
1043                 if (anglehack)
1044                 {
1045                         char    temp[32];
1046                         strcpy (temp, com_token);
1047                         sprintf (com_token, "0 %s 0", temp);
1048                 }
1049
1050                 if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
1051                         Host_Error ("ED_ParseEdict: parse error");
1052         }
1053
1054         if (!init)
1055                 ent->free = true;
1056
1057         return data;
1058 }
1059
1060
1061 /*
1062 ================
1063 ED_LoadFromFile
1064
1065 The entities are directly placed in the array, rather than allocated with
1066 ED_Alloc, because otherwise an error loading the map would have entity
1067 number references out of order.
1068
1069 Creates a server's entity / program execution context by
1070 parsing textual entity definitions out of an ent file.
1071
1072 Used for both fresh maps and savegame loads.  A fresh map would also need
1073 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1074 ================
1075 */
1076 void ED_LoadFromFile (char *data)
1077 {       
1078         edict_t         *ent;
1079         int                     inhibit;
1080         dfunction_t     *func;
1081
1082         ent = NULL;
1083         inhibit = 0;
1084         pr_global_struct->time = sv.time;
1085         
1086 // parse ents
1087         while (1)
1088         {
1089 // parse the opening brace      
1090                 data = COM_Parse (data);
1091                 if (!data)
1092                         break;
1093                 if (com_token[0] != '{')
1094                         Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1095
1096                 if (!ent)
1097                         ent = EDICT_NUM(0);
1098                 else
1099                         ent = ED_Alloc ();
1100                 data = ED_ParseEdict (data, ent);
1101
1102 // remove things from different skill levels or deathmatch
1103                 if (deathmatch.integer)
1104                 {
1105                         if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1106                         {
1107                                 ED_Free (ent);  
1108                                 inhibit++;
1109                                 continue;
1110                         }
1111                 }
1112                 else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY  ))
1113                           || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
1114                           || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD  )))
1115                 {
1116                         ED_Free (ent);  
1117                         inhibit++;
1118                         continue;
1119                 }
1120
1121 //
1122 // immediately call spawn function
1123 //
1124                 if (!ent->v.classname)
1125                 {
1126                         Con_Printf ("No classname for:\n");
1127                         ED_Print (ent);
1128                         ED_Free (ent);
1129                         continue;
1130                 }
1131
1132         // look for the spawn function
1133                 func = ED_FindFunction ( pr_strings + ent->v.classname );
1134
1135                 if (!func)
1136                 {
1137                         if (developer.integer) // don't confuse non-developers with errors
1138                         {
1139                                 Con_Printf ("No spawn function for:\n");
1140                                 ED_Print (ent);
1141                         }
1142                         ED_Free (ent);
1143                         continue;
1144                 }
1145
1146                 pr_global_struct->self = EDICT_TO_PROG(ent);
1147                 PR_ExecuteProgram (func - pr_functions, "");
1148         }
1149
1150         Con_DPrintf ("%i entities inhibited\n", inhibit);
1151 }
1152
1153
1154 typedef struct dpfield_s
1155 {
1156         int type;
1157         char *string;
1158 }
1159 dpfield_t;
1160
1161 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1162
1163 dpfield_t dpfields[] =
1164 {
1165         {ev_float, "gravity"},
1166         {ev_float, "button3"},
1167         {ev_float, "button4"},
1168         {ev_float, "button5"},
1169         {ev_float, "button6"},
1170         {ev_float, "button7"},
1171         {ev_float, "button8"},
1172         {ev_float, "glow_size"},
1173         {ev_float, "glow_trail"},
1174         {ev_float, "glow_color"},
1175         {ev_float, "items2"},
1176         {ev_float, "scale"},
1177         {ev_float, "alpha"},
1178         {ev_float, "renderamt"},
1179         {ev_float, "rendermode"},
1180         {ev_float, "fullbright"},
1181         {ev_float, "ammo_shells1"},
1182         {ev_float, "ammo_nails1"},
1183         {ev_float, "ammo_lava_nails"},
1184         {ev_float, "ammo_rockets1"},
1185         {ev_float, "ammo_multi_rockets"},
1186         {ev_float, "ammo_cells1"},
1187         {ev_float, "ammo_plasma"},
1188         {ev_float, "idealpitch"},
1189         {ev_float, "pitch_speed"},
1190         {ev_entity, "viewmodelforclient"},
1191         {ev_entity, "nodrawtoclient"},
1192         {ev_entity, "exteriormodeltoclient"},
1193         {ev_entity, "drawonlytoclient"},
1194         {ev_float, "ping"},
1195         {ev_vector, "movement"},
1196         {ev_float, "pmodel"},
1197         {ev_vector, "punchvector"}
1198 };
1199
1200 /*
1201 ===============
1202 PR_LoadProgs
1203 ===============
1204 */
1205 void PR_LoadProgs (void)
1206 {
1207         int i;
1208         dstatement_t *st;
1209         ddef_t *infielddefs;
1210         void *temp;
1211
1212 // flush the non-C variable lookup cache
1213         for (i=0 ; i<GEFV_CACHESIZE ; i++)
1214                 gefvCache[i].field[0] = 0;
1215
1216         Mem_EmptyPool(progs_mempool);
1217         Mem_EmptyPool(edictstring_mempool);
1218
1219         temp = COM_LoadFile ("progs.dat", false);
1220         if (!temp)
1221                 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1222
1223         progs = (dprograms_t *)Mem_Alloc(progs_mempool, com_filesize);
1224
1225         memcpy(progs, temp, com_filesize);
1226         Mem_Free(temp);
1227
1228         Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024);
1229
1230         pr_crc = CRC_Block((qbyte *)progs, com_filesize);
1231
1232 // byte swap the header
1233         for (i=0 ; i<sizeof(*progs)/4 ; i++)
1234                 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1235
1236         if (progs->version != PROG_VERSION)
1237                 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1238         if (progs->crc != PROGHEADER_CRC)
1239                 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1240
1241         pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1242         pr_strings = (char *)progs + progs->ofs_strings;
1243         pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1244
1245         // we need to expand the fielddefs list to include all the engine fields,
1246         // so allocate a new place for it
1247         infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1248         pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1249
1250         pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1251
1252         // moved edict_size calculation down below field adding code
1253
1254         pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1255         pr_globals = (float *)pr_global_struct;
1256
1257 // byte swap the lumps
1258         for (i=0 ; i<progs->numstatements ; i++)
1259         {
1260                 pr_statements[i].op = LittleShort(pr_statements[i].op);
1261                 pr_statements[i].a = LittleShort(pr_statements[i].a);
1262                 pr_statements[i].b = LittleShort(pr_statements[i].b);
1263                 pr_statements[i].c = LittleShort(pr_statements[i].c);
1264         }
1265
1266         for (i=0 ; i<progs->numfunctions; i++)
1267         {
1268                 pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
1269                 pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
1270                 pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
1271                 pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
1272                 pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
1273                 pr_functions[i].locals = LittleLong (pr_functions[i].locals);
1274         }
1275
1276         for (i=0 ; i<progs->numglobaldefs ; i++)
1277         {
1278                 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1279                 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1280                 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1281         }
1282
1283         // copy the progs fields to the new fields list
1284         for (i = 0;i < progs->numfielddefs;i++)
1285         {
1286                 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1287                 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1288                         Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1289                 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1290                 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1291         }
1292
1293         // append the darkplaces fields
1294         for (i = 0;i < DPFIELDS;i++)
1295         {
1296                 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1297                 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1298                 pr_fielddefs[progs->numfielddefs].s_name = dpfields[i].string - pr_strings;
1299                 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1300                         progs->entityfields += 3;
1301                 else
1302                         progs->entityfields++;
1303                 progs->numfielddefs++;
1304         }
1305
1306         for (i=0 ; i<progs->numglobals ; i++)
1307                 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1308
1309         // moved edict_size calculation down here, below field adding code
1310         pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
1311
1312         pr_edictareasize = pr_edict_size * MAX_EDICTS;
1313
1314         // LordHavoc: bounds check anything static
1315         for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1316         {
1317                 switch (st->op)
1318                 {
1319                 case OP_IF:
1320                 case OP_IFNOT:
1321                         if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1322                                 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1323                         break;
1324                 case OP_GOTO:
1325                         if (st->a + i < 0 || st->a + i >= progs->numstatements)
1326                                 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1327                         break;
1328                 // global global global
1329                 case OP_ADD_F:
1330                 case OP_ADD_V:
1331                 case OP_SUB_F:
1332                 case OP_SUB_V:
1333                 case OP_MUL_F:
1334                 case OP_MUL_V:
1335                 case OP_MUL_FV:
1336                 case OP_MUL_VF:
1337                 case OP_DIV_F:
1338                 case OP_BITAND:
1339                 case OP_BITOR:
1340                 case OP_GE:
1341                 case OP_LE:
1342                 case OP_GT:
1343                 case OP_LT:
1344                 case OP_AND:
1345                 case OP_OR:
1346                 case OP_EQ_F:
1347                 case OP_EQ_V:
1348                 case OP_EQ_S:
1349                 case OP_EQ_E:
1350                 case OP_EQ_FNC:
1351                 case OP_NE_F:
1352                 case OP_NE_V:
1353                 case OP_NE_S:
1354                 case OP_NE_E:
1355                 case OP_NE_FNC:
1356                 case OP_ADDRESS:
1357                 case OP_LOAD_F:
1358                 case OP_LOAD_FLD:
1359                 case OP_LOAD_ENT:
1360                 case OP_LOAD_S:
1361                 case OP_LOAD_FNC:
1362                 case OP_LOAD_V:
1363                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1364                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1365                         break;
1366                 // global none global
1367                 case OP_NOT_F:
1368                 case OP_NOT_V:
1369                 case OP_NOT_S:
1370                 case OP_NOT_FNC:
1371                 case OP_NOT_ENT:
1372                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1373                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1374                         break;
1375                 // 2 globals
1376                 case OP_STOREP_F:
1377                 case OP_STOREP_ENT:
1378                 case OP_STOREP_FLD:
1379                 case OP_STOREP_S:
1380                 case OP_STOREP_FNC:
1381                 case OP_STORE_F:
1382                 case OP_STORE_ENT:
1383                 case OP_STORE_FLD:
1384                 case OP_STORE_S:
1385                 case OP_STORE_FNC:
1386                 case OP_STATE:
1387                 case OP_STOREP_V:
1388                 case OP_STORE_V:
1389                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1390                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1391                         break;
1392                 // 1 global
1393                 case OP_CALL0:
1394                 case OP_CALL1:
1395                 case OP_CALL2:
1396                 case OP_CALL3:
1397                 case OP_CALL4:
1398                 case OP_CALL5:
1399                 case OP_CALL6:
1400                 case OP_CALL7:
1401                 case OP_CALL8:
1402                 case OP_DONE:
1403                 case OP_RETURN:
1404                         if ((unsigned short) st->a >= progs->numglobals)
1405                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1406                         break;
1407                 default:
1408                         Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1409                         break;
1410                 }
1411         }
1412
1413         FindEdictFieldOffsets(); // LordHavoc: update field offset list
1414 }
1415
1416
1417 void PR_Fields_f (void)
1418 {
1419         int i;
1420         if (!sv.active)
1421         {
1422                 Con_Printf("no progs loaded\n");
1423                 return;
1424         }
1425         for (i = 0;i < progs->numfielddefs;i++)
1426                 Con_Printf("%s\n", (pr_strings + pr_fielddefs[i].s_name));
1427         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);
1428 }
1429
1430 void PR_Globals_f (void)
1431 {
1432         int i;
1433         if (!sv.active)
1434         {
1435                 Con_Printf("no progs loaded\n");
1436                 return;
1437         }
1438         for (i = 0;i < progs->numglobaldefs;i++)
1439                 Con_Printf("%s\n", (pr_strings + pr_globaldefs[i].s_name));
1440         Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1441 }
1442
1443 /*
1444 ===============
1445 PR_Init
1446 ===============
1447 */
1448 void PR_Init (void)
1449 {
1450         Cmd_AddCommand ("edict", ED_PrintEdict_f);
1451         Cmd_AddCommand ("edicts", ED_PrintEdicts);
1452         Cmd_AddCommand ("edictcount", ED_Count);
1453         Cmd_AddCommand ("profile", PR_Profile_f);
1454         Cmd_AddCommand ("pr_fields", PR_Fields_f);
1455         Cmd_AddCommand ("pr_globals", PR_Globals_f);
1456         Cvar_RegisterVariable (&pr_checkextension);
1457         Cvar_RegisterVariable (&nomonsters);
1458         Cvar_RegisterVariable (&gamecfg);
1459         Cvar_RegisterVariable (&scratch1);
1460         Cvar_RegisterVariable (&scratch2);
1461         Cvar_RegisterVariable (&scratch3);
1462         Cvar_RegisterVariable (&scratch4);
1463         Cvar_RegisterVariable (&savedgamecfg);
1464         Cvar_RegisterVariable (&saved1);
1465         Cvar_RegisterVariable (&saved2);
1466         Cvar_RegisterVariable (&saved3);
1467         Cvar_RegisterVariable (&saved4);
1468         // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1469         Cvar_RegisterVariable (&decors);
1470         // LordHavoc: Nehahra uses these to pass data around cutscene demos
1471         if (gamemode == GAME_NEHAHRA)
1472         {
1473                 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1474                 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1475                 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1476                 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1477                 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1478                 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1479                 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1480                 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1481                 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1482                 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1483         }
1484         Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1485         // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1486         Cvar_RegisterVariable (&pr_boundscheck);
1487
1488         progs_mempool = Mem_AllocPool("progs.dat");
1489         edictstring_mempool = Mem_AllocPool("edict strings");
1490 }
1491
1492 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1493 edict_t *EDICT_NUM_ERROR(int n)
1494 {
1495         Host_Error ("EDICT_NUM: bad number %i", n);
1496         return NULL;
1497 }
1498 /*
1499 edict_t *EDICT_NUM(int n)
1500 {
1501         if (n < 0 || n >= sv.max_edicts)
1502                 Sys_Error ("EDICT_NUM: bad number %i", n);
1503         return (edict_t *)((qbyte *)sv.edicts+ (n)*pr_edict_size);
1504 }
1505 */
1506
1507 int NUM_FOR_EDICT(edict_t *e)
1508 {
1509         int             b;
1510
1511         b = (qbyte *)e - (qbyte *)sv.edicts;
1512         b = b / pr_edict_size;
1513
1514         if (b < 0 || b >= sv.num_edicts)
1515                 Host_Error ("NUM_FOR_EDICT: bad pointer");
1516         return b;
1517 }
1518
1519 int NoCrash_NUM_FOR_EDICT(edict_t *e)
1520 {
1521         int             b;
1522
1523         b = (qbyte *)e - (qbyte *)sv.edicts;
1524         b = b / pr_edict_size;
1525         return b;
1526 }