2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
20 // sv_edict.c -- entity dictionary
25 dfunction_t *pr_functions;
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
35 unsigned short pr_crc;
37 int type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
39 ddef_t *ED_FieldAtOfs (int ofs);
40 qboolean ED_ParseEpair (void *base, ddef_t *key, char *s);
42 cvar_t nomonsters = {"nomonsters", "0"};
43 cvar_t gamecfg = {"gamecfg", "0"};
44 cvar_t scratch1 = {"scratch1", "0"};
45 cvar_t scratch2 = {"scratch2", "0"};
46 cvar_t scratch3 = {"scratch3", "0"};
47 cvar_t scratch4 = {"scratch4", "0"};
48 cvar_t savedgamecfg = {"savedgamecfg", "0", true};
49 cvar_t saved1 = {"saved1", "0", true};
50 cvar_t saved2 = {"saved2", "0", true};
51 cvar_t saved3 = {"saved3", "0", true};
52 cvar_t saved4 = {"saved4", "0", true};
53 cvar_t decors = {"decors", "0"};
54 cvar_t nehx00 = {"nehx00", "0"};cvar_t nehx01 = {"nehx01", "0"};
55 cvar_t nehx02 = {"nehx02", "0"};cvar_t nehx03 = {"nehx03", "0"};
56 cvar_t nehx04 = {"nehx04", "0"};cvar_t nehx05 = {"nehx05", "0"};
57 cvar_t nehx06 = {"nehx06", "0"};cvar_t nehx07 = {"nehx07", "0"};
58 cvar_t nehx08 = {"nehx08", "0"};cvar_t nehx09 = {"nehx09", "0"};
59 cvar_t nehx10 = {"nehx10", "0"};cvar_t nehx11 = {"nehx11", "0"};
60 cvar_t nehx12 = {"nehx12", "0"};cvar_t nehx13 = {"nehx13", "0"};
61 cvar_t nehx14 = {"nehx14", "0"};cvar_t nehx15 = {"nehx15", "0"};
62 cvar_t nehx16 = {"nehx16", "0"};cvar_t nehx17 = {"nehx17", "0"};
63 cvar_t nehx18 = {"nehx18", "0"};cvar_t nehx19 = {"nehx19", "0"};
64 cvar_t cutscene = {"cutscene", "1"};
65 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
66 cvar_t pr_boundscheck = {"pr_boundscheck", "1"};
68 #define MAX_FIELD_LEN 64
69 #define GEFV_CACHESIZE 2
73 char field[MAX_FIELD_LEN];
76 static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};
78 ddef_t *ED_FindField (char *name);
79 dfunction_t *ED_FindFunction (char *name);
81 // LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue... these are defined as externs in progs.h
95 int eval_renderamt; // HalfLife support
96 int eval_rendermode; // HalfLife support
98 int eval_ammo_shells1;
100 int eval_ammo_lava_nails;
101 int eval_ammo_rockets1;
102 int eval_ammo_multi_rockets;
103 int eval_ammo_cells1;
104 int eval_ammo_plasma;
106 int eval_pitch_speed;
107 int eval_viewmodelforclient;
108 int eval_nodrawtoclient;
109 int eval_drawonlytoclient;
115 dfunction_t *SV_PlayerPhysicsQC;
116 dfunction_t *EndFrameQC;
118 int FindFieldOffset(char *field)
121 d = ED_FindField(field);
127 void FindEdictFieldOffsets()
129 eval_gravity = FindFieldOffset("gravity");
130 eval_button3 = FindFieldOffset("button3");
131 eval_button4 = FindFieldOffset("button4");
132 eval_button5 = FindFieldOffset("button5");
133 eval_button6 = FindFieldOffset("button6");
134 eval_button7 = FindFieldOffset("button7");
135 eval_button8 = FindFieldOffset("button8");
136 eval_glow_size = FindFieldOffset("glow_size");
137 eval_glow_trail = FindFieldOffset("glow_trail");
138 eval_glow_color = FindFieldOffset("glow_color");
139 eval_items2 = FindFieldOffset("items2");
140 eval_scale = FindFieldOffset("scale");
141 eval_alpha = FindFieldOffset("alpha");
142 eval_renderamt = FindFieldOffset("renderamt"); // HalfLife support
143 eval_rendermode = FindFieldOffset("rendermode"); // HalfLife support
144 eval_fullbright = FindFieldOffset("fullbright");
145 eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
146 eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
147 eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
148 eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
149 eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
150 eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
151 eval_ammo_plasma = FindFieldOffset("ammo_plasma");
152 eval_idealpitch = FindFieldOffset("idealpitch");
153 eval_pitch_speed = FindFieldOffset("pitch_speed");
154 eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
155 eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
156 eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
157 eval_colormod = FindFieldOffset("colormod");
158 eval_ping = FindFieldOffset("ping");
159 eval_movement = FindFieldOffset("movement");
160 eval_pmodel = FindFieldOffset("pmodel");
162 // LordHavoc: allowing QuakeC to override the player movement code
163 SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
164 // LordHavoc: support for endframe
165 EndFrameQC = ED_FindFunction ("EndFrame");
172 Sets everything to NULL
175 void ED_ClearEdict (edict_t *e)
177 memset (&e->v, 0, progs->entityfields * 4);
185 Either finds a free edict, or allocates a new one.
186 Try to avoid reusing an entity that was recently freed, because it
187 can cause the client to think the entity morphed into something else
188 instead of being removed and recreated, which can cause interpolated
189 angles and bad trails.
192 edict_t *ED_Alloc (void)
197 for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
200 // the first couple seconds of server time can involve a lot of
201 // freeing and allocating, so relax the replacement policy
202 if (e->free && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) )
210 Sys_Error ("ED_Alloc: no free edicts");
223 Marks the edict as free
224 FIXME: walk all entities and NULL out references to this entity
227 void ED_Free (edict_t *ed)
229 SV_UnlinkEdict (ed); // unlink from world bsp
233 ed->v.takedamage = 0;
234 ed->v.modelindex = 0;
238 VectorCopy (vec3_origin, ed->v.origin);
239 VectorCopy (vec3_origin, ed->v.angles);
240 ed->v.nextthink = -1;
243 ed->freetime = sv.time;
246 //===========================================================================
253 ddef_t *ED_GlobalAtOfs (int ofs)
258 for (i=0 ; i<progs->numglobaldefs ; i++)
260 def = &pr_globaldefs[i];
272 ddef_t *ED_FieldAtOfs (int ofs)
277 for (i=0 ; i<progs->numfielddefs ; i++)
279 def = &pr_fielddefs[i];
291 ddef_t *ED_FindField (char *name)
296 for (i=0 ; i<progs->numfielddefs ; i++)
298 def = &pr_fielddefs[i];
299 if (!strcmp(pr_strings + def->s_name,name) )
311 ddef_t *ED_FindGlobal (char *name)
316 for (i=0 ; i<progs->numglobaldefs ; i++)
318 def = &pr_globaldefs[i];
319 if (!strcmp(pr_strings + def->s_name,name) )
331 dfunction_t *ED_FindFunction (char *name)
336 for (i=0 ; i<progs->numfunctions ; i++)
338 func = &pr_functions[i];
339 if (!strcmp(pr_strings + func->s_name,name) )
347 eval_t *GetEdictFieldValue(edict_t *ed, char *field)
353 for (i=0 ; i<GEFV_CACHESIZE ; i++)
355 if (!strcmp(field, gefvCache[i].field))
357 def = gefvCache[i].pcache;
362 def = ED_FindField (field);
364 if (strlen(field) < MAX_FIELD_LEN)
366 gefvCache[rep].pcache = def;
367 strcpy (gefvCache[rep].field, field);
375 return (eval_t *)((char *)&ed->v + def->ofs*4);
383 Returns a string describing *data in a type specific manner
386 char *PR_ValueString (etype_t type, eval_t *val)
388 static char line[256];
392 type &= ~DEF_SAVEGLOBAL;
397 sprintf (line, "%s", pr_strings + val->string);
400 sprintf (line, "entity %i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)) );
403 f = pr_functions + val->function;
404 sprintf (line, "%s()", pr_strings + f->s_name);
407 def = ED_FieldAtOfs ( val->_int );
408 sprintf (line, ".%s", pr_strings + def->s_name);
411 sprintf (line, "void");
414 sprintf (line, "%5.1f", val->_float);
417 sprintf (line, "'%5.1f %5.1f %5.1f'", val->vector[0], val->vector[1], val->vector[2]);
420 sprintf (line, "pointer");
423 sprintf (line, "bad type %i", type);
434 Returns a string describing *data in a type specific manner
435 Easier to parse than PR_ValueString
438 char *PR_UglyValueString (etype_t type, eval_t *val)
440 static char line[256];
444 type &= ~DEF_SAVEGLOBAL;
449 sprintf (line, "%s", pr_strings + val->string);
452 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
455 f = pr_functions + val->function;
456 sprintf (line, "%s", pr_strings + f->s_name);
459 def = ED_FieldAtOfs ( val->_int );
460 sprintf (line, "%s", pr_strings + def->s_name);
463 sprintf (line, "void");
466 sprintf (line, "%f", val->_float);
469 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
472 sprintf (line, "bad type %i", type);
483 Returns a string with a description and the contents of a global,
484 padded to 20 field width
487 char *PR_GlobalString (int ofs)
493 static char line[128];
495 val = (void *)&pr_globals[ofs];
496 def = ED_GlobalAtOfs(ofs);
498 sprintf (line,"%i(???)", ofs);
501 s = PR_ValueString (def->type, val);
502 sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s);
513 char *PR_GlobalStringNoContents (int ofs)
517 static char line[128];
519 def = ED_GlobalAtOfs(ofs);
521 sprintf (line,"%i(???)", ofs);
523 sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name);
541 // LordHavoc: optimized this to print out much more quickly
542 void ED_Print (edict_t *ed)
550 char tempstring[8192]; // temporary string buffer
554 Con_Printf ("FREE\n");
559 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
560 for (i=1 ; i<progs->numfielddefs ; i++)
562 d = &pr_fielddefs[i];
563 name = pr_strings + d->s_name;
564 if (name[strlen(name)-2] == '_')
565 continue; // skip _x, _y, _z vars
567 v = (int *)((char *)&ed->v + d->ofs*4);
569 // if the value is still all 0, skip the field
570 type = d->type & ~DEF_SAVEGLOBAL;
572 for (j=0 ; j<type_size[type] ; j++)
575 if (j == type_size[type])
578 strcat(tempstring, name);
581 strcat(tempstring, " ");
583 strcat(tempstring, PR_ValueString(d->type, (eval_t *)v));
584 strcat(tempstring, "\n");
586 Con_Printf(tempstring);
596 void ED_Write (FILE *f, edict_t *ed)
612 for (i=1 ; i<progs->numfielddefs ; i++)
614 d = &pr_fielddefs[i];
615 name = pr_strings + d->s_name;
616 if (name[strlen(name)-2] == '_')
617 continue; // skip _x, _y, _z vars
619 v = (int *)((char *)&ed->v + d->ofs*4);
621 // if the value is still all 0, skip the field
622 type = d->type & ~DEF_SAVEGLOBAL;
623 for (j=0 ; j<type_size[type] ; j++)
626 if (j == type_size[type])
629 fprintf (f,"\"%s\" ",name);
630 fprintf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
636 void ED_PrintNum (int ent)
638 ED_Print (EDICT_NUM(ent));
645 For debugging, prints all the entities in the current server
648 void ED_PrintEdicts (void)
652 Con_Printf ("%i entities\n", sv.num_edicts);
653 for (i=0 ; i<sv.num_edicts ; i++)
661 For debugging, prints a single edicy
664 void ED_PrintEdict_f (void)
668 i = atoi (Cmd_Argv(1));
669 if (i >= sv.num_edicts)
671 Con_Printf("Bad edict number\n");
688 int active, models, solid, step;
690 active = models = solid = step = 0;
691 for (i=0 ; i<sv.num_edicts ; i++)
701 if (ent->v.movetype == MOVETYPE_STEP)
705 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
706 Con_Printf ("active :%3i\n", active);
707 Con_Printf ("view :%3i\n", models);
708 Con_Printf ("touch :%3i\n", solid);
709 Con_Printf ("step :%3i\n", step);
714 ==============================================================================
718 FIXME: need to tag constants, doesn't really work
719 ==============================================================================
727 void ED_WriteGlobals (FILE *f)
735 for (i=0 ; i<progs->numglobaldefs ; i++)
737 def = &pr_globaldefs[i];
739 if ( !(def->type & DEF_SAVEGLOBAL) )
741 type &= ~DEF_SAVEGLOBAL;
743 if (type != ev_string
745 && type != ev_entity)
748 name = pr_strings + def->s_name;
749 fprintf (f,"\"%s\" ", name);
750 fprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
760 void ED_ParseGlobals (char *data)
768 data = COM_Parse (data);
769 if (com_token[0] == '}')
772 Host_Error ("ED_ParseEntity: EOF without closing brace");
774 strcpy (keyname, com_token);
777 data = COM_Parse (data);
779 Host_Error ("ED_ParseEntity: EOF without closing brace");
781 if (com_token[0] == '}')
782 Host_Error ("ED_ParseEntity: closing brace without data");
784 key = ED_FindGlobal (keyname);
787 Con_DPrintf ("'%s' is not a global\n", keyname);
791 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
792 Host_Error ("ED_ParseGlobals: parse error");
796 //============================================================================
804 char *ED_NewString (char *string)
809 l = strlen(string) + 1;
810 new = Hunk_Alloc (l);
813 for (i=0 ; i< l ; i++)
815 if (string[i] == '\\' && i < l-1)
818 if (string[i] == 'n')
824 *new_p++ = string[i];
835 Can parse either fields or globals
836 returns false if error
839 qboolean ED_ParseEpair (void *base, ddef_t *key, char *s)
848 d = (void *)((int *)base + key->ofs);
850 switch (key->type & ~DEF_SAVEGLOBAL)
853 *(string_t *)d = ED_NewString (s) - pr_strings;
857 *(float *)d = atof (s);
864 for (i=0 ; i<3 ; i++)
866 while (*v && *v != ' ')
869 ((float *)d)[i] = atof (w);
875 *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
879 def = ED_FindField (s);
882 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
883 if (strcmp(s, "sky") && strncmp(s, "fog_", 4) && strcmp(s, "skyboxsize"))
884 Con_DPrintf ("Can't find field %s\n", s);
887 *(int *)d = G_INT(def->ofs);
891 func = ED_FindFunction (s);
894 Con_DPrintf ("Can't find function %s\n", s);
897 *(func_t *)d = func - pr_functions;
910 Parses an edict out of the given string, returning the new position
911 ed should be a properly initialized empty edict.
912 Used for initial level load and for savegames.
915 char *ED_ParseEdict (char *data, edict_t *ent)
926 if (ent != sv.edicts) // hack
927 memset (&ent->v, 0, progs->entityfields * 4);
929 // go through all the dictionary pairs
933 data = COM_Parse (data);
934 if (com_token[0] == '}')
937 Host_Error ("ED_ParseEntity: EOF without closing brace");
939 // anglehack is to allow QuakeEd to write single scalar angles
940 // and allow them to be turned into vectors. (FIXME...)
941 if (!strcmp(com_token, "angle"))
943 strcpy (com_token, "angles");
949 // FIXME: change light to _light to get rid of this hack
950 if (!strcmp(com_token, "light"))
951 strcpy (com_token, "light_lev"); // hack for single light def
953 strcpy (keyname, com_token);
955 // another hack to fix heynames with trailing spaces
957 while (n && keyname[n-1] == ' ')
964 data = COM_Parse (data);
966 Host_Error ("ED_ParseEntity: EOF without closing brace");
968 if (com_token[0] == '}')
969 Host_Error ("ED_ParseEntity: closing brace without data");
973 // keynames with a leading underscore are used for utility comments,
974 // and are immediately discarded by quake
975 if (keyname[0] == '_')
978 key = ED_FindField (keyname);
981 Con_DPrintf ("'%s' is not a field\n", keyname);
988 strcpy (temp, com_token);
989 sprintf (com_token, "0 %s 0", temp);
992 if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
993 Host_Error ("ED_ParseEdict: parse error");
1007 The entities are directly placed in the array, rather than allocated with
1008 ED_Alloc, because otherwise an error loading the map would have entity
1009 number references out of order.
1011 Creates a server's entity / program execution context by
1012 parsing textual entity definitions out of an ent file.
1014 Used for both fresh maps and savegame loads. A fresh map would also need
1015 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1018 void ED_LoadFromFile (char *data)
1026 pr_global_struct->time = sv.time;
1031 // parse the opening brace
1032 data = COM_Parse (data);
1035 if (com_token[0] != '{')
1036 Sys_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1042 data = ED_ParseEdict (data, ent);
1044 // remove things from different skill levels or deathmatch
1045 if (deathmatch.value)
1047 if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1054 else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY ))
1055 || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
1056 || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD )))
1064 // immediately call spawn function
1066 if (!ent->v.classname)
1068 Con_Printf ("No classname for:\n");
1074 // look for the spawn function
1075 func = ED_FindFunction ( pr_strings + ent->v.classname );
1079 if (developer.value) // don't confuse non-developers with errors
1081 Con_Printf ("No spawn function for:\n");
1088 pr_global_struct->self = EDICT_TO_PROG(ent);
1089 PR_ExecuteProgram (func - pr_functions);
1092 Con_DPrintf ("%i entities inhibited\n", inhibit);
1101 void PR_LoadProgs (void)
1106 // flush the non-C variable lookup cache
1107 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1108 gefvCache[i].field[0] = 0;
1110 progs = (dprograms_t *)COM_LoadHunkFile ("progs.dat", false);
1112 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1113 Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024);
1115 pr_crc = CRC_Block((byte *)progs, com_filesize);
1117 // byte swap the header
1118 for (i=0 ; i<sizeof(*progs)/4 ; i++)
1119 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1121 if (progs->version != PROG_VERSION)
1122 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1123 if (progs->crc != PROGHEADER_CRC)
1124 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1126 pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
1127 pr_strings = (char *)progs + progs->ofs_strings;
1128 pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
1129 pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
1130 pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
1132 pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);
1133 pr_globals = (float *)pr_global_struct;
1135 pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
1137 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1139 // byte swap the lumps
1140 for (i=0 ; i<progs->numstatements ; i++)
1142 pr_statements[i].op = LittleShort(pr_statements[i].op);
1143 pr_statements[i].a = LittleShort(pr_statements[i].a);
1144 pr_statements[i].b = LittleShort(pr_statements[i].b);
1145 pr_statements[i].c = LittleShort(pr_statements[i].c);
1148 for (i=0 ; i<progs->numfunctions; i++)
1150 pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
1151 pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
1152 pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
1153 pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
1154 pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
1155 pr_functions[i].locals = LittleLong (pr_functions[i].locals);
1158 for (i=0 ; i<progs->numglobaldefs ; i++)
1160 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1161 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1162 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1165 for (i=0 ; i<progs->numfielddefs ; i++)
1167 pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
1168 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1169 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1170 pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs);
1171 pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
1174 for (i=0 ; i<progs->numglobals ; i++)
1175 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1177 // LordHavoc: bounds check anything static
1178 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1184 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1185 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1188 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1189 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1191 // global global global
1226 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1227 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1229 // global none global
1235 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1236 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1252 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1253 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1267 if ((unsigned short) st->a >= progs->numglobals)
1268 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1271 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1276 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1287 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1288 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1289 Cmd_AddCommand ("edictcount", ED_Count);
1290 Cmd_AddCommand ("profile", PR_Profile_f);
1291 Cvar_RegisterVariable (&nomonsters);
1292 Cvar_RegisterVariable (&gamecfg);
1293 Cvar_RegisterVariable (&scratch1);
1294 Cvar_RegisterVariable (&scratch2);
1295 Cvar_RegisterVariable (&scratch3);
1296 Cvar_RegisterVariable (&scratch4);
1297 Cvar_RegisterVariable (&savedgamecfg);
1298 Cvar_RegisterVariable (&saved1);
1299 Cvar_RegisterVariable (&saved2);
1300 Cvar_RegisterVariable (&saved3);
1301 Cvar_RegisterVariable (&saved4);
1302 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1303 Cvar_RegisterVariable (&decors);
1304 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1307 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1308 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1309 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1310 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1311 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1312 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1313 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1314 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1315 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1316 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1318 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1319 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1320 Cvar_RegisterVariable (&pr_boundscheck);
1323 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1324 edict_t *EDICT_NUM_ERROR(int n)
1326 Sys_Error ("EDICT_NUM: bad number %i", n);
1330 edict_t *EDICT_NUM(int n)
1332 if (n < 0 || n >= sv.max_edicts)
1333 Sys_Error ("EDICT_NUM: bad number %i", n);
1334 return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size);
1338 int NUM_FOR_EDICT(edict_t *e)
1342 b = (byte *)e - (byte *)sv.edicts;
1343 b = b / pr_edict_size;
1345 if (b < 0 || b >= sv.num_edicts)
1346 Sys_Error ("NUM_FOR_EDICT: bad pointer");