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;
113 dfunction_t *SV_PlayerPhysicsQC;
114 dfunction_t *EndFrameQC;
116 int FindFieldOffset(char *field)
119 d = ED_FindField(field);
125 void FindEdictFieldOffsets()
127 eval_gravity = FindFieldOffset("gravity");
128 eval_button3 = FindFieldOffset("button3");
129 eval_button4 = FindFieldOffset("button4");
130 eval_button5 = FindFieldOffset("button5");
131 eval_button6 = FindFieldOffset("button6");
132 eval_button7 = FindFieldOffset("button7");
133 eval_button8 = FindFieldOffset("button8");
134 eval_glow_size = FindFieldOffset("glow_size");
135 eval_glow_trail = FindFieldOffset("glow_trail");
136 eval_glow_color = FindFieldOffset("glow_color");
137 eval_items2 = FindFieldOffset("items2");
138 eval_scale = FindFieldOffset("scale");
139 eval_alpha = FindFieldOffset("alpha");
140 eval_fullbright = FindFieldOffset("fullbright");
141 eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
142 eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
143 eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
144 eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
145 eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
146 eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
147 eval_ammo_plasma = FindFieldOffset("ammo_plasma");
148 eval_idealpitch = FindFieldOffset("idealpitch");
149 eval_pitch_speed = FindFieldOffset("pitch_speed");
150 eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
151 eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
152 eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
153 eval_colormod = FindFieldOffset("colormod");
154 eval_ping = FindFieldOffset("ping");
155 eval_movement = FindFieldOffset("movement");
156 eval_pmodel = FindFieldOffset("pmodel");
158 // LordHavoc: allowing QuakeC to override the player movement code
159 SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
160 // LordHavoc: support for endframe
161 EndFrameQC = ED_FindFunction ("EndFrame");
168 Sets everything to NULL
171 void ED_ClearEdict (edict_t *e)
173 memset (&e->v, 0, progs->entityfields * 4);
181 Either finds a free edict, or allocates a new one.
182 Try to avoid reusing an entity that was recently freed, because it
183 can cause the client to think the entity morphed into something else
184 instead of being removed and recreated, which can cause interpolated
185 angles and bad trails.
188 edict_t *ED_Alloc (void)
193 for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
196 // the first couple seconds of server time can involve a lot of
197 // freeing and allocating, so relax the replacement policy
198 if (e->free && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) )
206 Sys_Error ("ED_Alloc: no free edicts");
219 Marks the edict as free
220 FIXME: walk all entities and NULL out references to this entity
223 void ED_Free (edict_t *ed)
225 SV_UnlinkEdict (ed); // unlink from world bsp
229 ed->v.takedamage = 0;
230 ed->v.modelindex = 0;
234 VectorCopy (vec3_origin, ed->v.origin);
235 VectorCopy (vec3_origin, ed->v.angles);
236 ed->v.nextthink = -1;
239 ed->freetime = sv.time;
242 //===========================================================================
249 ddef_t *ED_GlobalAtOfs (int ofs)
254 for (i=0 ; i<progs->numglobaldefs ; i++)
256 def = &pr_globaldefs[i];
268 ddef_t *ED_FieldAtOfs (int ofs)
273 for (i=0 ; i<progs->numfielddefs ; i++)
275 def = &pr_fielddefs[i];
287 ddef_t *ED_FindField (char *name)
292 for (i=0 ; i<progs->numfielddefs ; i++)
294 def = &pr_fielddefs[i];
295 if (!strcmp(pr_strings + def->s_name,name) )
307 ddef_t *ED_FindGlobal (char *name)
312 for (i=0 ; i<progs->numglobaldefs ; i++)
314 def = &pr_globaldefs[i];
315 if (!strcmp(pr_strings + def->s_name,name) )
327 dfunction_t *ED_FindFunction (char *name)
332 for (i=0 ; i<progs->numfunctions ; i++)
334 func = &pr_functions[i];
335 if (!strcmp(pr_strings + func->s_name,name) )
343 eval_t *GetEdictFieldValue(edict_t *ed, char *field)
349 for (i=0 ; i<GEFV_CACHESIZE ; i++)
351 if (!strcmp(field, gefvCache[i].field))
353 def = gefvCache[i].pcache;
358 def = ED_FindField (field);
360 if (strlen(field) < MAX_FIELD_LEN)
362 gefvCache[rep].pcache = def;
363 strcpy (gefvCache[rep].field, field);
371 return (eval_t *)((char *)&ed->v + def->ofs*4);
379 Returns a string describing *data in a type specific manner
382 char *PR_ValueString (etype_t type, eval_t *val)
384 static char line[256];
388 type &= ~DEF_SAVEGLOBAL;
393 sprintf (line, "%s", pr_strings + val->string);
396 sprintf (line, "entity %i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)) );
399 f = pr_functions + val->function;
400 sprintf (line, "%s()", pr_strings + f->s_name);
403 def = ED_FieldAtOfs ( val->_int );
404 sprintf (line, ".%s", pr_strings + def->s_name);
407 sprintf (line, "void");
410 sprintf (line, "%5.1f", val->_float);
413 sprintf (line, "'%5.1f %5.1f %5.1f'", val->vector[0], val->vector[1], val->vector[2]);
416 sprintf (line, "pointer");
419 sprintf (line, "bad type %i", type);
430 Returns a string describing *data in a type specific manner
431 Easier to parse than PR_ValueString
434 char *PR_UglyValueString (etype_t type, eval_t *val)
436 static char line[256];
440 type &= ~DEF_SAVEGLOBAL;
445 sprintf (line, "%s", pr_strings + val->string);
448 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
451 f = pr_functions + val->function;
452 sprintf (line, "%s", pr_strings + f->s_name);
455 def = ED_FieldAtOfs ( val->_int );
456 sprintf (line, "%s", pr_strings + def->s_name);
459 sprintf (line, "void");
462 sprintf (line, "%f", val->_float);
465 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
468 sprintf (line, "bad type %i", type);
479 Returns a string with a description and the contents of a global,
480 padded to 20 field width
483 char *PR_GlobalString (int ofs)
489 static char line[128];
491 val = (void *)&pr_globals[ofs];
492 def = ED_GlobalAtOfs(ofs);
494 sprintf (line,"%i(???)", ofs);
497 s = PR_ValueString (def->type, val);
498 sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s);
509 char *PR_GlobalStringNoContents (int ofs)
513 static char line[128];
515 def = ED_GlobalAtOfs(ofs);
517 sprintf (line,"%i(???)", ofs);
519 sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name);
537 // LordHavoc: optimized this to print out much more quickly
538 void ED_Print (edict_t *ed)
546 char tempstring[8192]; // temporary string buffer
550 Con_Printf ("FREE\n");
555 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
556 for (i=1 ; i<progs->numfielddefs ; i++)
558 d = &pr_fielddefs[i];
559 name = pr_strings + d->s_name;
560 if (name[strlen(name)-2] == '_')
561 continue; // skip _x, _y, _z vars
563 v = (int *)((char *)&ed->v + d->ofs*4);
565 // if the value is still all 0, skip the field
566 type = d->type & ~DEF_SAVEGLOBAL;
568 for (j=0 ; j<type_size[type] ; j++)
571 if (j == type_size[type])
574 strcat(tempstring, name);
577 strcat(tempstring, " ");
579 strcat(tempstring, PR_ValueString(d->type, (eval_t *)v));
580 strcat(tempstring, "\n");
582 Con_Printf(tempstring);
592 void ED_Write (FILE *f, edict_t *ed)
608 for (i=1 ; i<progs->numfielddefs ; i++)
610 d = &pr_fielddefs[i];
611 name = pr_strings + d->s_name;
612 if (name[strlen(name)-2] == '_')
613 continue; // skip _x, _y, _z vars
615 v = (int *)((char *)&ed->v + d->ofs*4);
617 // if the value is still all 0, skip the field
618 type = d->type & ~DEF_SAVEGLOBAL;
619 for (j=0 ; j<type_size[type] ; j++)
622 if (j == type_size[type])
625 fprintf (f,"\"%s\" ",name);
626 fprintf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
632 void ED_PrintNum (int ent)
634 ED_Print (EDICT_NUM(ent));
641 For debugging, prints all the entities in the current server
644 void ED_PrintEdicts (void)
648 Con_Printf ("%i entities\n", sv.num_edicts);
649 for (i=0 ; i<sv.num_edicts ; i++)
657 For debugging, prints a single edicy
660 void ED_PrintEdict_f (void)
664 i = atoi (Cmd_Argv(1));
665 if (i >= sv.num_edicts)
667 Con_Printf("Bad edict number\n");
684 int active, models, solid, step;
686 active = models = solid = step = 0;
687 for (i=0 ; i<sv.num_edicts ; i++)
697 if (ent->v.movetype == MOVETYPE_STEP)
701 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
702 Con_Printf ("active :%3i\n", active);
703 Con_Printf ("view :%3i\n", models);
704 Con_Printf ("touch :%3i\n", solid);
705 Con_Printf ("step :%3i\n", step);
710 ==============================================================================
714 FIXME: need to tag constants, doesn't really work
715 ==============================================================================
723 void ED_WriteGlobals (FILE *f)
731 for (i=0 ; i<progs->numglobaldefs ; i++)
733 def = &pr_globaldefs[i];
735 if ( !(def->type & DEF_SAVEGLOBAL) )
737 type &= ~DEF_SAVEGLOBAL;
739 if (type != ev_string
741 && type != ev_entity)
744 name = pr_strings + def->s_name;
745 fprintf (f,"\"%s\" ", name);
746 fprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
756 void ED_ParseGlobals (char *data)
764 data = COM_Parse (data);
765 if (com_token[0] == '}')
768 Host_Error ("ED_ParseEntity: EOF without closing brace");
770 strcpy (keyname, com_token);
773 data = COM_Parse (data);
775 Host_Error ("ED_ParseEntity: EOF without closing brace");
777 if (com_token[0] == '}')
778 Host_Error ("ED_ParseEntity: closing brace without data");
780 key = ED_FindGlobal (keyname);
783 Con_DPrintf ("'%s' is not a global\n", keyname);
787 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
788 Host_Error ("ED_ParseGlobals: parse error");
792 //============================================================================
800 char *ED_NewString (char *string)
805 l = strlen(string) + 1;
806 new = Hunk_Alloc (l);
809 for (i=0 ; i< l ; i++)
811 if (string[i] == '\\' && i < l-1)
814 if (string[i] == 'n')
820 *new_p++ = string[i];
831 Can parse either fields or globals
832 returns false if error
835 qboolean ED_ParseEpair (void *base, ddef_t *key, char *s)
844 d = (void *)((int *)base + key->ofs);
846 switch (key->type & ~DEF_SAVEGLOBAL)
849 *(string_t *)d = ED_NewString (s) - pr_strings;
853 *(float *)d = atof (s);
860 for (i=0 ; i<3 ; i++)
862 while (*v && *v != ' ')
865 ((float *)d)[i] = atof (w);
871 *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
875 def = ED_FindField (s);
878 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
879 if (strcmp(s, "sky") && strncmp(s, "fog_", 4) && strcmp(s, "skyboxsize"))
880 Con_DPrintf ("Can't find field %s\n", s);
883 *(int *)d = G_INT(def->ofs);
887 func = ED_FindFunction (s);
890 Con_DPrintf ("Can't find function %s\n", s);
893 *(func_t *)d = func - pr_functions;
906 Parses an edict out of the given string, returning the new position
907 ed should be a properly initialized empty edict.
908 Used for initial level load and for savegames.
911 char *ED_ParseEdict (char *data, edict_t *ent)
922 if (ent != sv.edicts) // hack
923 memset (&ent->v, 0, progs->entityfields * 4);
925 // go through all the dictionary pairs
929 data = COM_Parse (data);
930 if (com_token[0] == '}')
933 Host_Error ("ED_ParseEntity: EOF without closing brace");
935 // anglehack is to allow QuakeEd to write single scalar angles
936 // and allow them to be turned into vectors. (FIXME...)
937 if (!strcmp(com_token, "angle"))
939 strcpy (com_token, "angles");
945 // FIXME: change light to _light to get rid of this hack
946 if (!strcmp(com_token, "light"))
947 strcpy (com_token, "light_lev"); // hack for single light def
949 strcpy (keyname, com_token);
951 // another hack to fix heynames with trailing spaces
953 while (n && keyname[n-1] == ' ')
960 data = COM_Parse (data);
962 Host_Error ("ED_ParseEntity: EOF without closing brace");
964 if (com_token[0] == '}')
965 Host_Error ("ED_ParseEntity: closing brace without data");
969 // keynames with a leading underscore are used for utility comments,
970 // and are immediately discarded by quake
971 if (keyname[0] == '_')
974 key = ED_FindField (keyname);
977 Con_DPrintf ("'%s' is not a field\n", keyname);
984 strcpy (temp, com_token);
985 sprintf (com_token, "0 %s 0", temp);
988 if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
989 Host_Error ("ED_ParseEdict: parse error");
1003 The entities are directly placed in the array, rather than allocated with
1004 ED_Alloc, because otherwise an error loading the map would have entity
1005 number references out of order.
1007 Creates a server's entity / program execution context by
1008 parsing textual entity definitions out of an ent file.
1010 Used for both fresh maps and savegame loads. A fresh map would also need
1011 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1014 void ED_LoadFromFile (char *data)
1022 pr_global_struct->time = sv.time;
1027 // parse the opening brace
1028 data = COM_Parse (data);
1031 if (com_token[0] != '{')
1032 Sys_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1038 data = ED_ParseEdict (data, ent);
1040 // remove things from different skill levels or deathmatch
1041 if (deathmatch.value)
1043 if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1050 else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY ))
1051 || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
1052 || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD )))
1060 // immediately call spawn function
1062 if (!ent->v.classname)
1064 Con_Printf ("No classname for:\n");
1070 // look for the spawn function
1071 func = ED_FindFunction ( pr_strings + ent->v.classname );
1075 if (developer.value) // don't confuse non-developers with errors
1077 Con_Printf ("No spawn function for:\n");
1084 pr_global_struct->self = EDICT_TO_PROG(ent);
1085 PR_ExecuteProgram (func - pr_functions);
1088 Con_DPrintf ("%i entities inhibited\n", inhibit);
1097 void PR_LoadProgs (void)
1102 // flush the non-C variable lookup cache
1103 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1104 gefvCache[i].field[0] = 0;
1106 progs = (dprograms_t *)COM_LoadHunkFile ("progs.dat", false);
1108 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1109 Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024);
1111 pr_crc = CRC_Block((byte *)progs, com_filesize);
1113 // byte swap the header
1114 for (i=0 ; i<sizeof(*progs)/4 ; i++)
1115 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1117 if (progs->version != PROG_VERSION)
1118 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1119 if (progs->crc != PROGHEADER_CRC)
1120 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1122 pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
1123 pr_strings = (char *)progs + progs->ofs_strings;
1124 pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
1125 pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
1126 pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
1128 pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);
1129 pr_globals = (float *)pr_global_struct;
1131 pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
1133 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1135 // byte swap the lumps
1136 for (i=0 ; i<progs->numstatements ; i++)
1138 pr_statements[i].op = LittleShort(pr_statements[i].op);
1139 pr_statements[i].a = LittleShort(pr_statements[i].a);
1140 pr_statements[i].b = LittleShort(pr_statements[i].b);
1141 pr_statements[i].c = LittleShort(pr_statements[i].c);
1144 for (i=0 ; i<progs->numfunctions; i++)
1146 pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
1147 pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
1148 pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
1149 pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
1150 pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
1151 pr_functions[i].locals = LittleLong (pr_functions[i].locals);
1154 for (i=0 ; i<progs->numglobaldefs ; i++)
1156 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1157 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1158 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1161 for (i=0 ; i<progs->numfielddefs ; i++)
1163 pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
1164 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1165 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1166 pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs);
1167 pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
1170 for (i=0 ; i<progs->numglobals ; i++)
1171 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1173 // LordHavoc: bounds check anything static
1174 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1180 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1181 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1184 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1185 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1187 // global global global
1222 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1223 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1225 // global none global
1231 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1232 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1248 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1249 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1263 if ((unsigned short) st->a >= progs->numglobals)
1264 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1267 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1272 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1283 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1284 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1285 Cmd_AddCommand ("edictcount", ED_Count);
1286 Cmd_AddCommand ("profile", PR_Profile_f);
1287 Cvar_RegisterVariable (&nomonsters);
1288 Cvar_RegisterVariable (&gamecfg);
1289 Cvar_RegisterVariable (&scratch1);
1290 Cvar_RegisterVariable (&scratch2);
1291 Cvar_RegisterVariable (&scratch3);
1292 Cvar_RegisterVariable (&scratch4);
1293 Cvar_RegisterVariable (&savedgamecfg);
1294 Cvar_RegisterVariable (&saved1);
1295 Cvar_RegisterVariable (&saved2);
1296 Cvar_RegisterVariable (&saved3);
1297 Cvar_RegisterVariable (&saved4);
1298 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1299 Cvar_RegisterVariable (&decors);
1300 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1303 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1304 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1305 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1306 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1307 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1308 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1309 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1310 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1311 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1312 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1314 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1315 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1316 Cvar_RegisterVariable (&pr_boundscheck);
1319 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1320 edict_t *EDICT_NUM_ERROR(int n)
1322 Sys_Error ("EDICT_NUM: bad number %i", n);
1326 edict_t *EDICT_NUM(int n)
1328 if (n < 0 || n >= sv.max_edicts)
1329 Sys_Error ("EDICT_NUM: bad number %i", n);
1330 return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size);
1334 int NUM_FOR_EDICT(edict_t *e)
1338 b = (byte *)e - (byte *)sv.edicts;
1339 b = b / pr_edict_size;
1341 if (b < 0 || b >= sv.num_edicts)
1342 Sys_Error ("NUM_FOR_EDICT: bad pointer");