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
96 int eval_ammo_shells1;
98 int eval_ammo_lava_nails;
99 int eval_ammo_rockets1;
100 int eval_ammo_multi_rockets;
101 int eval_ammo_cells1;
102 int eval_ammo_plasma;
104 int eval_pitch_speed;
105 int eval_viewmodelforclient;
106 int eval_nodrawtoclient;
107 int eval_drawonlytoclient;
112 dfunction_t *SV_PlayerPhysicsQC;
113 dfunction_t *EndFrameQC;
115 int FindFieldOffset(char *field)
118 d = ED_FindField(field);
124 void FindEdictFieldOffsets()
126 eval_gravity = FindFieldOffset("gravity");
127 eval_button3 = FindFieldOffset("button3");
128 eval_button4 = FindFieldOffset("button4");
129 eval_button5 = FindFieldOffset("button5");
130 eval_button6 = FindFieldOffset("button6");
131 eval_button7 = FindFieldOffset("button7");
132 eval_button8 = FindFieldOffset("button8");
133 eval_glow_size = FindFieldOffset("glow_size");
134 eval_glow_trail = FindFieldOffset("glow_trail");
135 eval_glow_color = FindFieldOffset("glow_color");
136 eval_items2 = FindFieldOffset("items2");
137 eval_scale = FindFieldOffset("scale");
138 eval_alpha = FindFieldOffset("alpha");
139 eval_fullbright = FindFieldOffset("fullbright");
140 eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
141 eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
142 eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
143 eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
144 eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
145 eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
146 eval_ammo_plasma = FindFieldOffset("ammo_plasma");
147 eval_idealpitch = FindFieldOffset("idealpitch");
148 eval_pitch_speed = FindFieldOffset("pitch_speed");
149 eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
150 eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
151 eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
152 eval_colormod = FindFieldOffset("colormod");
153 eval_ping = FindFieldOffset("ping");
154 eval_movement = FindFieldOffset("movement");
156 // LordHavoc: allowing QuakeC to override the player movement code
157 SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
158 // LordHavoc: support for endframe
159 EndFrameQC = ED_FindFunction ("EndFrame");
166 Sets everything to NULL
169 void ED_ClearEdict (edict_t *e)
171 memset (&e->v, 0, progs->entityfields * 4);
179 Either finds a free edict, or allocates a new one.
180 Try to avoid reusing an entity that was recently freed, because it
181 can cause the client to think the entity morphed into something else
182 instead of being removed and recreated, which can cause interpolated
183 angles and bad trails.
186 edict_t *ED_Alloc (void)
191 for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
194 // the first couple seconds of server time can involve a lot of
195 // freeing and allocating, so relax the replacement policy
196 if (e->free && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) )
204 Sys_Error ("ED_Alloc: no free edicts");
217 Marks the edict as free
218 FIXME: walk all entities and NULL out references to this entity
221 void ED_Free (edict_t *ed)
223 SV_UnlinkEdict (ed); // unlink from world bsp
227 ed->v.takedamage = 0;
228 ed->v.modelindex = 0;
232 VectorCopy (vec3_origin, ed->v.origin);
233 VectorCopy (vec3_origin, ed->v.angles);
234 ed->v.nextthink = -1;
237 ed->freetime = sv.time;
240 //===========================================================================
247 ddef_t *ED_GlobalAtOfs (int ofs)
252 for (i=0 ; i<progs->numglobaldefs ; i++)
254 def = &pr_globaldefs[i];
266 ddef_t *ED_FieldAtOfs (int ofs)
271 for (i=0 ; i<progs->numfielddefs ; i++)
273 def = &pr_fielddefs[i];
285 ddef_t *ED_FindField (char *name)
290 for (i=0 ; i<progs->numfielddefs ; i++)
292 def = &pr_fielddefs[i];
293 if (!strcmp(pr_strings + def->s_name,name) )
305 ddef_t *ED_FindGlobal (char *name)
310 for (i=0 ; i<progs->numglobaldefs ; i++)
312 def = &pr_globaldefs[i];
313 if (!strcmp(pr_strings + def->s_name,name) )
325 dfunction_t *ED_FindFunction (char *name)
330 for (i=0 ; i<progs->numfunctions ; i++)
332 func = &pr_functions[i];
333 if (!strcmp(pr_strings + func->s_name,name) )
341 eval_t *GetEdictFieldValue(edict_t *ed, char *field)
347 for (i=0 ; i<GEFV_CACHESIZE ; i++)
349 if (!strcmp(field, gefvCache[i].field))
351 def = gefvCache[i].pcache;
356 def = ED_FindField (field);
358 if (strlen(field) < MAX_FIELD_LEN)
360 gefvCache[rep].pcache = def;
361 strcpy (gefvCache[rep].field, field);
369 return (eval_t *)((char *)&ed->v + def->ofs*4);
377 Returns a string describing *data in a type specific manner
380 char *PR_ValueString (etype_t type, eval_t *val)
382 static char line[256];
386 type &= ~DEF_SAVEGLOBAL;
391 sprintf (line, "%s", pr_strings + val->string);
394 sprintf (line, "entity %i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)) );
397 f = pr_functions + val->function;
398 sprintf (line, "%s()", pr_strings + f->s_name);
401 def = ED_FieldAtOfs ( val->_int );
402 sprintf (line, ".%s", pr_strings + def->s_name);
405 sprintf (line, "void");
408 sprintf (line, "%5.1f", val->_float);
411 sprintf (line, "'%5.1f %5.1f %5.1f'", val->vector[0], val->vector[1], val->vector[2]);
414 sprintf (line, "pointer");
417 sprintf (line, "bad type %i", type);
428 Returns a string describing *data in a type specific manner
429 Easier to parse than PR_ValueString
432 char *PR_UglyValueString (etype_t type, eval_t *val)
434 static char line[256];
438 type &= ~DEF_SAVEGLOBAL;
443 sprintf (line, "%s", pr_strings + val->string);
446 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
449 f = pr_functions + val->function;
450 sprintf (line, "%s", pr_strings + f->s_name);
453 def = ED_FieldAtOfs ( val->_int );
454 sprintf (line, "%s", pr_strings + def->s_name);
457 sprintf (line, "void");
460 sprintf (line, "%f", val->_float);
463 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
466 sprintf (line, "bad type %i", type);
477 Returns a string with a description and the contents of a global,
478 padded to 20 field width
481 char *PR_GlobalString (int ofs)
487 static char line[128];
489 val = (void *)&pr_globals[ofs];
490 def = ED_GlobalAtOfs(ofs);
492 sprintf (line,"%i(???)", ofs);
495 s = PR_ValueString (def->type, val);
496 sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s);
507 char *PR_GlobalStringNoContents (int ofs)
511 static char line[128];
513 def = ED_GlobalAtOfs(ofs);
515 sprintf (line,"%i(???)", ofs);
517 sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name);
535 // LordHavoc: optimized this to print out much more quickly
536 void ED_Print (edict_t *ed)
544 char tempstring[8192]; // temporary string buffer
548 Con_Printf ("FREE\n");
553 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
554 for (i=1 ; i<progs->numfielddefs ; i++)
556 d = &pr_fielddefs[i];
557 name = pr_strings + d->s_name;
558 if (name[strlen(name)-2] == '_')
559 continue; // skip _x, _y, _z vars
561 v = (int *)((char *)&ed->v + d->ofs*4);
563 // if the value is still all 0, skip the field
564 type = d->type & ~DEF_SAVEGLOBAL;
566 for (j=0 ; j<type_size[type] ; j++)
569 if (j == type_size[type])
572 strcat(tempstring, name);
575 strcat(tempstring, " ");
577 strcat(tempstring, PR_ValueString(d->type, (eval_t *)v));
578 strcat(tempstring, "\n");
580 Con_Printf(tempstring);
590 void ED_Write (FILE *f, edict_t *ed)
606 for (i=1 ; i<progs->numfielddefs ; i++)
608 d = &pr_fielddefs[i];
609 name = pr_strings + d->s_name;
610 if (name[strlen(name)-2] == '_')
611 continue; // skip _x, _y, _z vars
613 v = (int *)((char *)&ed->v + d->ofs*4);
615 // if the value is still all 0, skip the field
616 type = d->type & ~DEF_SAVEGLOBAL;
617 for (j=0 ; j<type_size[type] ; j++)
620 if (j == type_size[type])
623 fprintf (f,"\"%s\" ",name);
624 fprintf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
630 void ED_PrintNum (int ent)
632 ED_Print (EDICT_NUM(ent));
639 For debugging, prints all the entities in the current server
642 void ED_PrintEdicts (void)
646 Con_Printf ("%i entities\n", sv.num_edicts);
647 for (i=0 ; i<sv.num_edicts ; i++)
655 For debugging, prints a single edicy
658 void ED_PrintEdict_f (void)
662 i = atoi (Cmd_Argv(1));
663 if (i >= sv.num_edicts)
665 Con_Printf("Bad edict number\n");
682 int active, models, solid, step;
684 active = models = solid = step = 0;
685 for (i=0 ; i<sv.num_edicts ; i++)
695 if (ent->v.movetype == MOVETYPE_STEP)
699 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
700 Con_Printf ("active :%3i\n", active);
701 Con_Printf ("view :%3i\n", models);
702 Con_Printf ("touch :%3i\n", solid);
703 Con_Printf ("step :%3i\n", step);
708 ==============================================================================
712 FIXME: need to tag constants, doesn't really work
713 ==============================================================================
721 void ED_WriteGlobals (FILE *f)
729 for (i=0 ; i<progs->numglobaldefs ; i++)
731 def = &pr_globaldefs[i];
733 if ( !(def->type & DEF_SAVEGLOBAL) )
735 type &= ~DEF_SAVEGLOBAL;
737 if (type != ev_string
739 && type != ev_entity)
742 name = pr_strings + def->s_name;
743 fprintf (f,"\"%s\" ", name);
744 fprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
754 void ED_ParseGlobals (char *data)
762 data = COM_Parse (data);
763 if (com_token[0] == '}')
766 Host_Error ("ED_ParseEntity: EOF without closing brace");
768 strcpy (keyname, com_token);
771 data = COM_Parse (data);
773 Host_Error ("ED_ParseEntity: EOF without closing brace");
775 if (com_token[0] == '}')
776 Host_Error ("ED_ParseEntity: closing brace without data");
778 key = ED_FindGlobal (keyname);
781 Con_DPrintf ("'%s' is not a global\n", keyname);
785 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
786 Host_Error ("ED_ParseGlobals: parse error");
790 //============================================================================
798 char *ED_NewString (char *string)
803 l = strlen(string) + 1;
804 new = Hunk_Alloc (l);
807 for (i=0 ; i< l ; i++)
809 if (string[i] == '\\' && i < l-1)
812 if (string[i] == 'n')
818 *new_p++ = string[i];
829 Can parse either fields or globals
830 returns false if error
833 qboolean ED_ParseEpair (void *base, ddef_t *key, char *s)
842 d = (void *)((int *)base + key->ofs);
844 switch (key->type & ~DEF_SAVEGLOBAL)
847 *(string_t *)d = ED_NewString (s) - pr_strings;
851 *(float *)d = atof (s);
858 for (i=0 ; i<3 ; i++)
860 while (*v && *v != ' ')
863 ((float *)d)[i] = atof (w);
869 *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
873 def = ED_FindField (s);
876 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
877 if (strcmp(s, "sky") && strncmp(s, "fog_", 4) && strcmp(s, "skyboxsize"))
878 Con_DPrintf ("Can't find field %s\n", s);
881 *(int *)d = G_INT(def->ofs);
885 func = ED_FindFunction (s);
888 Con_DPrintf ("Can't find function %s\n", s);
891 *(func_t *)d = func - pr_functions;
904 Parses an edict out of the given string, returning the new position
905 ed should be a properly initialized empty edict.
906 Used for initial level load and for savegames.
909 char *ED_ParseEdict (char *data, edict_t *ent)
920 if (ent != sv.edicts) // hack
921 memset (&ent->v, 0, progs->entityfields * 4);
923 // go through all the dictionary pairs
927 data = COM_Parse (data);
928 if (com_token[0] == '}')
931 Host_Error ("ED_ParseEntity: EOF without closing brace");
933 // anglehack is to allow QuakeEd to write single scalar angles
934 // and allow them to be turned into vectors. (FIXME...)
935 if (!strcmp(com_token, "angle"))
937 strcpy (com_token, "angles");
943 // FIXME: change light to _light to get rid of this hack
944 if (!strcmp(com_token, "light"))
945 strcpy (com_token, "light_lev"); // hack for single light def
947 strcpy (keyname, com_token);
949 // another hack to fix heynames with trailing spaces
951 while (n && keyname[n-1] == ' ')
958 data = COM_Parse (data);
960 Host_Error ("ED_ParseEntity: EOF without closing brace");
962 if (com_token[0] == '}')
963 Host_Error ("ED_ParseEntity: closing brace without data");
967 // keynames with a leading underscore are used for utility comments,
968 // and are immediately discarded by quake
969 if (keyname[0] == '_')
972 key = ED_FindField (keyname);
975 Con_DPrintf ("'%s' is not a field\n", keyname);
982 strcpy (temp, com_token);
983 sprintf (com_token, "0 %s 0", temp);
986 if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
987 Host_Error ("ED_ParseEdict: parse error");
1001 The entities are directly placed in the array, rather than allocated with
1002 ED_Alloc, because otherwise an error loading the map would have entity
1003 number references out of order.
1005 Creates a server's entity / program execution context by
1006 parsing textual entity definitions out of an ent file.
1008 Used for both fresh maps and savegame loads. A fresh map would also need
1009 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1012 void ED_LoadFromFile (char *data)
1020 pr_global_struct->time = sv.time;
1025 // parse the opening brace
1026 data = COM_Parse (data);
1029 if (com_token[0] != '{')
1030 Sys_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1036 data = ED_ParseEdict (data, ent);
1038 // remove things from different skill levels or deathmatch
1039 if (deathmatch.value)
1041 if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1048 else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY ))
1049 || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
1050 || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD )))
1058 // immediately call spawn function
1060 if (!ent->v.classname)
1062 Con_Printf ("No classname for:\n");
1068 // look for the spawn function
1069 func = ED_FindFunction ( pr_strings + ent->v.classname );
1073 if (developer.value) // don't confuse non-developers with errors
1075 Con_Printf ("No spawn function for:\n");
1082 pr_global_struct->self = EDICT_TO_PROG(ent);
1083 PR_ExecuteProgram (func - pr_functions);
1086 Con_DPrintf ("%i entities inhibited\n", inhibit);
1095 void PR_LoadProgs (void)
1100 // flush the non-C variable lookup cache
1101 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1102 gefvCache[i].field[0] = 0;
1104 progs = (dprograms_t *)COM_LoadHunkFile ("progs.dat", false);
1106 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1107 Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024);
1109 pr_crc = CRC_Block((byte *)progs, com_filesize);
1111 // byte swap the header
1112 for (i=0 ; i<sizeof(*progs)/4 ; i++)
1113 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1115 if (progs->version != PROG_VERSION)
1116 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1117 if (progs->crc != PROGHEADER_CRC)
1118 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1120 pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
1121 pr_strings = (char *)progs + progs->ofs_strings;
1122 pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
1123 pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
1124 pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
1126 pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);
1127 pr_globals = (float *)pr_global_struct;
1129 pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
1131 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1133 // byte swap the lumps
1134 for (i=0 ; i<progs->numstatements ; i++)
1136 pr_statements[i].op = LittleShort(pr_statements[i].op);
1137 pr_statements[i].a = LittleShort(pr_statements[i].a);
1138 pr_statements[i].b = LittleShort(pr_statements[i].b);
1139 pr_statements[i].c = LittleShort(pr_statements[i].c);
1142 for (i=0 ; i<progs->numfunctions; i++)
1144 pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
1145 pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
1146 pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
1147 pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
1148 pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
1149 pr_functions[i].locals = LittleLong (pr_functions[i].locals);
1152 for (i=0 ; i<progs->numglobaldefs ; i++)
1154 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1155 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1156 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1159 for (i=0 ; i<progs->numfielddefs ; i++)
1161 pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
1162 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1163 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1164 pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs);
1165 pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
1168 for (i=0 ; i<progs->numglobals ; i++)
1169 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1171 // LordHavoc: bounds check anything static
1172 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1178 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1179 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1182 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1183 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1185 // global global global
1220 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1221 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1223 // global none global
1229 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1230 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1246 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1247 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1261 if ((unsigned short) st->a >= progs->numglobals)
1262 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1265 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1270 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1281 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1282 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1283 Cmd_AddCommand ("edictcount", ED_Count);
1284 Cmd_AddCommand ("profile", PR_Profile_f);
1285 Cvar_RegisterVariable (&nomonsters);
1286 Cvar_RegisterVariable (&gamecfg);
1287 Cvar_RegisterVariable (&scratch1);
1288 Cvar_RegisterVariable (&scratch2);
1289 Cvar_RegisterVariable (&scratch3);
1290 Cvar_RegisterVariable (&scratch4);
1291 Cvar_RegisterVariable (&savedgamecfg);
1292 Cvar_RegisterVariable (&saved1);
1293 Cvar_RegisterVariable (&saved2);
1294 Cvar_RegisterVariable (&saved3);
1295 Cvar_RegisterVariable (&saved4);
1296 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1297 Cvar_RegisterVariable (&decors);
1298 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1301 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1302 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1303 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1304 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1305 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1306 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1307 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1308 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1309 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1310 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1312 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1313 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1314 Cvar_RegisterVariable (&pr_boundscheck);
1317 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1318 edict_t *EDICT_NUM_ERROR(int n)
1320 Sys_Error ("EDICT_NUM: bad number %i", n);
1324 edict_t *EDICT_NUM(int n)
1326 if (n < 0 || n >= sv.max_edicts)
1327 Sys_Error ("EDICT_NUM: bad number %i", n);
1328 return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size);
1332 int NUM_FOR_EDICT(edict_t *e)
1336 b = (byte *)e - (byte *)sv.edicts;
1337 b = b / pr_edict_size;
1339 if (b < 0 || b >= sv.num_edicts)
1340 Sys_Error ("NUM_FOR_EDICT: bad pointer");