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 pr_checkextension = {"pr_checkextension", "1"};
43 cvar_t nomonsters = {"nomonsters", "0"};
44 cvar_t gamecfg = {"gamecfg", "0"};
45 cvar_t scratch1 = {"scratch1", "0"};
46 cvar_t scratch2 = {"scratch2", "0"};
47 cvar_t scratch3 = {"scratch3", "0"};
48 cvar_t scratch4 = {"scratch4", "0"};
49 cvar_t savedgamecfg = {"savedgamecfg", "0", true};
50 cvar_t saved1 = {"saved1", "0", true};
51 cvar_t saved2 = {"saved2", "0", true};
52 cvar_t saved3 = {"saved3", "0", true};
53 cvar_t saved4 = {"saved4", "0", true};
54 cvar_t decors = {"decors", "0"};
55 cvar_t nehx00 = {"nehx00", "0"};cvar_t nehx01 = {"nehx01", "0"};
56 cvar_t nehx02 = {"nehx02", "0"};cvar_t nehx03 = {"nehx03", "0"};
57 cvar_t nehx04 = {"nehx04", "0"};cvar_t nehx05 = {"nehx05", "0"};
58 cvar_t nehx06 = {"nehx06", "0"};cvar_t nehx07 = {"nehx07", "0"};
59 cvar_t nehx08 = {"nehx08", "0"};cvar_t nehx09 = {"nehx09", "0"};
60 cvar_t nehx10 = {"nehx10", "0"};cvar_t nehx11 = {"nehx11", "0"};
61 cvar_t nehx12 = {"nehx12", "0"};cvar_t nehx13 = {"nehx13", "0"};
62 cvar_t nehx14 = {"nehx14", "0"};cvar_t nehx15 = {"nehx15", "0"};
63 cvar_t nehx16 = {"nehx16", "0"};cvar_t nehx17 = {"nehx17", "0"};
64 cvar_t nehx18 = {"nehx18", "0"};cvar_t nehx19 = {"nehx19", "0"};
65 cvar_t cutscene = {"cutscene", "1"};
66 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
67 cvar_t pr_boundscheck = {"pr_boundscheck", "1"};
69 #define MAX_FIELD_LEN 64
70 #define GEFV_CACHESIZE 2
74 char field[MAX_FIELD_LEN];
77 static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};
79 ddef_t *ED_FindField (char *name);
80 dfunction_t *ED_FindFunction (char *name);
82 // LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue... these are defined as externs in progs.h
96 int eval_renderamt; // HalfLife support
97 int eval_rendermode; // HalfLife support
99 int eval_ammo_shells1;
100 int eval_ammo_nails1;
101 int eval_ammo_lava_nails;
102 int eval_ammo_rockets1;
103 int eval_ammo_multi_rockets;
104 int eval_ammo_cells1;
105 int eval_ammo_plasma;
107 int eval_pitch_speed;
108 int eval_viewmodelforclient;
109 int eval_nodrawtoclient;
110 int eval_drawonlytoclient;
115 int eval_punchvector;
117 dfunction_t *SV_PlayerPhysicsQC;
118 dfunction_t *EndFrameQC;
120 int FindFieldOffset(char *field)
123 d = ED_FindField(field);
129 void FindEdictFieldOffsets()
131 eval_gravity = FindFieldOffset("gravity");
132 eval_button3 = FindFieldOffset("button3");
133 eval_button4 = FindFieldOffset("button4");
134 eval_button5 = FindFieldOffset("button5");
135 eval_button6 = FindFieldOffset("button6");
136 eval_button7 = FindFieldOffset("button7");
137 eval_button8 = FindFieldOffset("button8");
138 eval_glow_size = FindFieldOffset("glow_size");
139 eval_glow_trail = FindFieldOffset("glow_trail");
140 eval_glow_color = FindFieldOffset("glow_color");
141 eval_items2 = FindFieldOffset("items2");
142 eval_scale = FindFieldOffset("scale");
143 eval_alpha = FindFieldOffset("alpha");
144 eval_renderamt = FindFieldOffset("renderamt"); // HalfLife support
145 eval_rendermode = FindFieldOffset("rendermode"); // HalfLife support
146 eval_fullbright = FindFieldOffset("fullbright");
147 eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
148 eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
149 eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
150 eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
151 eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
152 eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
153 eval_ammo_plasma = FindFieldOffset("ammo_plasma");
154 eval_idealpitch = FindFieldOffset("idealpitch");
155 eval_pitch_speed = FindFieldOffset("pitch_speed");
156 eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
157 eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
158 eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
159 eval_colormod = FindFieldOffset("colormod");
160 eval_ping = FindFieldOffset("ping");
161 eval_movement = FindFieldOffset("movement");
162 eval_pmodel = FindFieldOffset("pmodel");
163 eval_punchvector = FindFieldOffset("punchvector");
165 // LordHavoc: allowing QuakeC to override the player movement code
166 SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
167 // LordHavoc: support for endframe
168 EndFrameQC = ED_FindFunction ("EndFrame");
175 Sets everything to NULL
178 void ED_ClearEdict (edict_t *e)
180 memset (&e->v, 0, progs->entityfields * 4);
188 Either finds a free edict, or allocates a new one.
189 Try to avoid reusing an entity that was recently freed, because it
190 can cause the client to think the entity morphed into something else
191 instead of being removed and recreated, which can cause interpolated
192 angles and bad trails.
195 edict_t *ED_Alloc (void)
200 for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
203 // the first couple seconds of server time can involve a lot of
204 // freeing and allocating, so relax the replacement policy
205 if (e->free && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) )
213 Host_Error ("ED_Alloc: no free edicts");
226 Marks the edict as free
227 FIXME: walk all entities and NULL out references to this entity
230 void ED_Free (edict_t *ed)
232 SV_UnlinkEdict (ed); // unlink from world bsp
236 ed->v.takedamage = 0;
237 ed->v.modelindex = 0;
241 VectorClear(ed->v.origin);
242 VectorClear(ed->v.angles);
243 ed->v.nextthink = -1;
246 ed->freetime = sv.time;
249 //===========================================================================
256 ddef_t *ED_GlobalAtOfs (int ofs)
261 for (i=0 ; i<progs->numglobaldefs ; i++)
263 def = &pr_globaldefs[i];
275 ddef_t *ED_FieldAtOfs (int ofs)
280 for (i=0 ; i<progs->numfielddefs ; i++)
282 def = &pr_fielddefs[i];
294 ddef_t *ED_FindField (char *name)
299 for (i=0 ; i<progs->numfielddefs ; i++)
301 def = &pr_fielddefs[i];
302 if (!strcmp(pr_strings + def->s_name,name) )
314 ddef_t *ED_FindGlobal (char *name)
319 for (i=0 ; i<progs->numglobaldefs ; i++)
321 def = &pr_globaldefs[i];
322 if (!strcmp(pr_strings + def->s_name,name) )
334 dfunction_t *ED_FindFunction (char *name)
339 for (i=0 ; i<progs->numfunctions ; i++)
341 func = &pr_functions[i];
342 if (!strcmp(pr_strings + func->s_name,name) )
350 eval_t *GetEdictFieldValue(edict_t *ed, char *field)
356 for (i=0 ; i<GEFV_CACHESIZE ; i++)
358 if (!strcmp(field, gefvCache[i].field))
360 def = gefvCache[i].pcache;
365 def = ED_FindField (field);
367 if (strlen(field) < MAX_FIELD_LEN)
369 gefvCache[rep].pcache = def;
370 strcpy (gefvCache[rep].field, field);
378 return (eval_t *)((char *)&ed->v + def->ofs*4);
386 Returns a string describing *data in a type specific manner
389 char *PR_ValueString (etype_t type, eval_t *val)
391 static char line[256];
395 type &= ~DEF_SAVEGLOBAL;
400 sprintf (line, "%s", pr_strings + val->string);
403 sprintf (line, "entity %i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)) );
406 f = pr_functions + val->function;
407 sprintf (line, "%s()", pr_strings + f->s_name);
410 def = ED_FieldAtOfs ( val->_int );
411 sprintf (line, ".%s", pr_strings + def->s_name);
414 sprintf (line, "void");
417 sprintf (line, "%5.1f", val->_float);
420 sprintf (line, "'%5.1f %5.1f %5.1f'", val->vector[0], val->vector[1], val->vector[2]);
423 sprintf (line, "pointer");
426 sprintf (line, "bad type %i", type);
437 Returns a string describing *data in a type specific manner
438 Easier to parse than PR_ValueString
441 char *PR_UglyValueString (etype_t type, eval_t *val)
443 static char line[256];
447 type &= ~DEF_SAVEGLOBAL;
452 sprintf (line, "%s", pr_strings + val->string);
455 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
458 f = pr_functions + val->function;
459 sprintf (line, "%s", pr_strings + f->s_name);
462 def = ED_FieldAtOfs ( val->_int );
463 sprintf (line, "%s", pr_strings + def->s_name);
466 sprintf (line, "void");
469 sprintf (line, "%f", val->_float);
472 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
475 sprintf (line, "bad type %i", type);
486 Returns a string with a description and the contents of a global,
487 padded to 20 field width
490 char *PR_GlobalString (int ofs)
496 static char line[128];
498 val = (void *)&pr_globals[ofs];
499 def = ED_GlobalAtOfs(ofs);
501 sprintf (line,"%i(???)", ofs);
504 s = PR_ValueString (def->type, val);
505 sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s);
516 char *PR_GlobalStringNoContents (int ofs)
520 static char line[128];
522 def = ED_GlobalAtOfs(ofs);
524 sprintf (line,"%i(???)", ofs);
526 sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name);
544 // LordHavoc: optimized this to print out much more quickly
545 void ED_Print (edict_t *ed)
553 char tempstring[8192]; // temporary string buffer
557 Con_Printf ("FREE\n");
562 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
563 for (i=1 ; i<progs->numfielddefs ; i++)
565 d = &pr_fielddefs[i];
566 name = pr_strings + d->s_name;
567 if (name[strlen(name)-2] == '_')
568 continue; // skip _x, _y, _z vars
570 v = (int *)((char *)&ed->v + d->ofs*4);
572 // if the value is still all 0, skip the field
573 type = d->type & ~DEF_SAVEGLOBAL;
575 for (j=0 ; j<type_size[type] ; j++)
578 if (j == type_size[type])
581 strcat(tempstring, name);
584 strcat(tempstring, " ");
586 strcat(tempstring, PR_ValueString(d->type, (eval_t *)v));
587 strcat(tempstring, "\n");
589 Con_Printf(tempstring);
599 void ED_Write (FILE *f, edict_t *ed)
615 for (i=1 ; i<progs->numfielddefs ; i++)
617 d = &pr_fielddefs[i];
618 name = pr_strings + d->s_name;
619 if (name[strlen(name)-2] == '_')
620 continue; // skip _x, _y, _z vars
622 v = (int *)((char *)&ed->v + d->ofs*4);
624 // if the value is still all 0, skip the field
625 type = d->type & ~DEF_SAVEGLOBAL;
626 for (j=0 ; j<type_size[type] ; j++)
629 if (j == type_size[type])
632 fprintf (f,"\"%s\" ",name);
633 fprintf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
639 void ED_PrintNum (int ent)
641 ED_Print (EDICT_NUM(ent));
648 For debugging, prints all the entities in the current server
651 void ED_PrintEdicts (void)
655 Con_Printf ("%i entities\n", sv.num_edicts);
656 for (i=0 ; i<sv.num_edicts ; i++)
664 For debugging, prints a single edicy
667 void ED_PrintEdict_f (void)
671 i = atoi (Cmd_Argv(1));
672 if (i >= sv.num_edicts)
674 Con_Printf("Bad edict number\n");
691 int active, models, solid, step;
693 active = models = solid = step = 0;
694 for (i=0 ; i<sv.num_edicts ; i++)
704 if (ent->v.movetype == MOVETYPE_STEP)
708 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
709 Con_Printf ("active :%3i\n", active);
710 Con_Printf ("view :%3i\n", models);
711 Con_Printf ("touch :%3i\n", solid);
712 Con_Printf ("step :%3i\n", step);
717 ==============================================================================
721 FIXME: need to tag constants, doesn't really work
722 ==============================================================================
730 void ED_WriteGlobals (FILE *f)
738 for (i=0 ; i<progs->numglobaldefs ; i++)
740 def = &pr_globaldefs[i];
742 if ( !(def->type & DEF_SAVEGLOBAL) )
744 type &= ~DEF_SAVEGLOBAL;
746 if (type != ev_string
748 && type != ev_entity)
751 name = pr_strings + def->s_name;
752 fprintf (f,"\"%s\" ", name);
753 fprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
763 void ED_ParseGlobals (char *data)
765 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
771 data = COM_Parse (data);
772 if (com_token[0] == '}')
775 Host_Error ("ED_ParseEntity: EOF without closing brace");
777 strcpy (keyname, com_token);
780 data = COM_Parse (data);
782 Host_Error ("ED_ParseEntity: EOF without closing brace");
784 if (com_token[0] == '}')
785 Host_Error ("ED_ParseEntity: closing brace without data");
787 key = ED_FindGlobal (keyname);
790 Con_DPrintf ("'%s' is not a global\n", keyname);
794 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
795 Host_Error ("ED_ParseGlobals: parse error");
799 //============================================================================
807 char *ED_NewString (char *string)
812 l = strlen(string) + 1;
813 new = Hunk_AllocName (l, "edict string");
816 for (i=0 ; i< l ; i++)
818 if (string[i] == '\\' && i < l-1)
821 if (string[i] == 'n')
827 *new_p++ = string[i];
838 Can parse either fields or globals
839 returns false if error
842 qboolean ED_ParseEpair (void *base, ddef_t *key, char *s)
851 d = (void *)((int *)base + key->ofs);
853 switch (key->type & ~DEF_SAVEGLOBAL)
856 *(string_t *)d = ED_NewString (s) - pr_strings;
860 *(float *)d = atof (s);
867 for (i=0 ; i<3 ; i++)
869 while (*v && *v != ' ')
872 ((float *)d)[i] = atof (w);
878 *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
882 def = ED_FindField (s);
885 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
886 if (strcmp(s, "sky") && strcmp(s, "fog") && strncmp(s, "fog_", 4) && strcmp(s, "farclip"))
887 Con_DPrintf ("Can't find field %s\n", s);
890 *(int *)d = G_INT(def->ofs);
894 func = ED_FindFunction (s);
897 Con_DPrintf ("Can't find function %s\n", s);
900 *(func_t *)d = func - pr_functions;
913 Parses an edict out of the given string, returning the new position
914 ed should be a properly initialized empty edict.
915 Used for initial level load and for savegames.
918 char *ED_ParseEdict (char *data, edict_t *ent)
929 if (ent != sv.edicts) // hack
930 memset (&ent->v, 0, progs->entityfields * 4);
932 // go through all the dictionary pairs
936 data = COM_Parse (data);
937 if (com_token[0] == '}')
940 Host_Error ("ED_ParseEntity: EOF without closing brace");
942 // anglehack is to allow QuakeEd to write single scalar angles
943 // and allow them to be turned into vectors. (FIXME...)
944 if (!strcmp(com_token, "angle"))
946 strcpy (com_token, "angles");
952 // FIXME: change light to _light to get rid of this hack
953 if (!strcmp(com_token, "light"))
954 strcpy (com_token, "light_lev"); // hack for single light def
956 strcpy (keyname, com_token);
958 // another hack to fix heynames with trailing spaces
960 while (n && keyname[n-1] == ' ')
967 data = COM_Parse (data);
969 Host_Error ("ED_ParseEntity: EOF without closing brace");
971 if (com_token[0] == '}')
972 Host_Error ("ED_ParseEntity: closing brace without data");
976 // keynames with a leading underscore are used for utility comments,
977 // and are immediately discarded by quake
978 if (keyname[0] == '_')
981 key = ED_FindField (keyname);
984 Con_DPrintf ("'%s' is not a field\n", keyname);
991 strcpy (temp, com_token);
992 sprintf (com_token, "0 %s 0", temp);
995 if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
996 Host_Error ("ED_ParseEdict: parse error");
1010 The entities are directly placed in the array, rather than allocated with
1011 ED_Alloc, because otherwise an error loading the map would have entity
1012 number references out of order.
1014 Creates a server's entity / program execution context by
1015 parsing textual entity definitions out of an ent file.
1017 Used for both fresh maps and savegame loads. A fresh map would also need
1018 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1021 void ED_LoadFromFile (char *data)
1029 pr_global_struct->time = sv.time;
1034 // parse the opening brace
1035 data = COM_Parse (data);
1038 if (com_token[0] != '{')
1039 Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1045 data = ED_ParseEdict (data, ent);
1047 // remove things from different skill levels or deathmatch
1048 if (deathmatch.value)
1050 if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1057 else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY ))
1058 || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
1059 || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD )))
1067 // immediately call spawn function
1069 if (!ent->v.classname)
1071 Con_Printf ("No classname for:\n");
1077 // look for the spawn function
1078 func = ED_FindFunction ( pr_strings + ent->v.classname );
1082 if (developer.value) // don't confuse non-developers with errors
1084 Con_Printf ("No spawn function for:\n");
1091 pr_global_struct->self = EDICT_TO_PROG(ent);
1092 PR_ExecuteProgram (func - pr_functions, "");
1095 Con_DPrintf ("%i entities inhibited\n", inhibit);
1104 void PR_LoadProgs (void)
1109 // flush the non-C variable lookup cache
1110 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1111 gefvCache[i].field[0] = 0;
1113 progs = (dprograms_t *)COM_LoadHunkFile ("progs.dat", false);
1115 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1116 Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024);
1118 pr_crc = CRC_Block((byte *)progs, com_filesize);
1120 // byte swap the header
1121 for (i=0 ; i<sizeof(*progs)/4 ; i++)
1122 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1124 if (progs->version != PROG_VERSION)
1125 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1126 if (progs->crc != PROGHEADER_CRC)
1127 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1129 pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
1130 pr_strings = (char *)progs + progs->ofs_strings;
1131 pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
1132 pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
1133 pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
1135 pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);
1136 pr_globals = (float *)pr_global_struct;
1138 pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
1140 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1142 // byte swap the lumps
1143 for (i=0 ; i<progs->numstatements ; i++)
1145 pr_statements[i].op = LittleShort(pr_statements[i].op);
1146 pr_statements[i].a = LittleShort(pr_statements[i].a);
1147 pr_statements[i].b = LittleShort(pr_statements[i].b);
1148 pr_statements[i].c = LittleShort(pr_statements[i].c);
1151 for (i=0 ; i<progs->numfunctions; i++)
1153 pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
1154 pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
1155 pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
1156 pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
1157 pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
1158 pr_functions[i].locals = LittleLong (pr_functions[i].locals);
1161 for (i=0 ; i<progs->numglobaldefs ; i++)
1163 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1164 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1165 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1168 for (i=0 ; i<progs->numfielddefs ; i++)
1170 pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
1171 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1172 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1173 pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs);
1174 pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
1177 for (i=0 ; i<progs->numglobals ; i++)
1178 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1180 // LordHavoc: bounds check anything static
1181 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1187 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1188 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1191 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1192 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1194 // global global global
1229 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1230 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1232 // global none global
1238 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1239 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1255 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1256 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1270 if ((unsigned short) st->a >= progs->numglobals)
1271 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1274 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1279 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1290 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1291 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1292 Cmd_AddCommand ("edictcount", ED_Count);
1293 Cmd_AddCommand ("profile", PR_Profile_f);
1294 Cvar_RegisterVariable (&pr_checkextension);
1295 Cvar_RegisterVariable (&nomonsters);
1296 Cvar_RegisterVariable (&gamecfg);
1297 Cvar_RegisterVariable (&scratch1);
1298 Cvar_RegisterVariable (&scratch2);
1299 Cvar_RegisterVariable (&scratch3);
1300 Cvar_RegisterVariable (&scratch4);
1301 Cvar_RegisterVariable (&savedgamecfg);
1302 Cvar_RegisterVariable (&saved1);
1303 Cvar_RegisterVariable (&saved2);
1304 Cvar_RegisterVariable (&saved3);
1305 Cvar_RegisterVariable (&saved4);
1306 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1307 Cvar_RegisterVariable (&decors);
1308 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1311 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1312 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1313 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1314 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1315 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1316 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1317 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1318 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1319 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1320 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1322 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1323 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1324 Cvar_RegisterVariable (&pr_boundscheck);
1327 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1328 edict_t *EDICT_NUM_ERROR(int n)
1330 Host_Error ("EDICT_NUM: bad number %i", n);
1334 edict_t *EDICT_NUM(int n)
1336 if (n < 0 || n >= sv.max_edicts)
1337 Sys_Error ("EDICT_NUM: bad number %i", n);
1338 return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size);
1342 int NUM_FOR_EDICT(edict_t *e)
1346 b = (byte *)e - (byte *)sv.edicts;
1347 b = b / pr_edict_size;
1349 if (b < 0 || b >= sv.num_edicts)
1350 Host_Error ("NUM_FOR_EDICT: bad pointer");