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_exteriormodeltoclient;
111 int eval_drawonlytoclient;
116 int eval_punchvector;
118 dfunction_t *SV_PlayerPhysicsQC;
119 dfunction_t *EndFrameQC;
121 int FindFieldOffset(char *field)
124 d = ED_FindField(field);
130 void FindEdictFieldOffsets(void)
132 eval_gravity = FindFieldOffset("gravity");
133 eval_button3 = FindFieldOffset("button3");
134 eval_button4 = FindFieldOffset("button4");
135 eval_button5 = FindFieldOffset("button5");
136 eval_button6 = FindFieldOffset("button6");
137 eval_button7 = FindFieldOffset("button7");
138 eval_button8 = FindFieldOffset("button8");
139 eval_glow_size = FindFieldOffset("glow_size");
140 eval_glow_trail = FindFieldOffset("glow_trail");
141 eval_glow_color = FindFieldOffset("glow_color");
142 eval_items2 = FindFieldOffset("items2");
143 eval_scale = FindFieldOffset("scale");
144 eval_alpha = FindFieldOffset("alpha");
145 eval_renderamt = FindFieldOffset("renderamt"); // HalfLife support
146 eval_rendermode = FindFieldOffset("rendermode"); // HalfLife support
147 eval_fullbright = FindFieldOffset("fullbright");
148 eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
149 eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
150 eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
151 eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
152 eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
153 eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
154 eval_ammo_plasma = FindFieldOffset("ammo_plasma");
155 eval_idealpitch = FindFieldOffset("idealpitch");
156 eval_pitch_speed = FindFieldOffset("pitch_speed");
157 eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
158 eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
159 eval_exteriormodeltoclient = FindFieldOffset("exteriormodeltoclient");
160 eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
161 eval_colormod = FindFieldOffset("colormod");
162 eval_ping = FindFieldOffset("ping");
163 eval_movement = FindFieldOffset("movement");
164 eval_pmodel = FindFieldOffset("pmodel");
165 eval_punchvector = FindFieldOffset("punchvector");
167 // LordHavoc: allowing QuakeC to override the player movement code
168 SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
169 // LordHavoc: support for endframe
170 EndFrameQC = ED_FindFunction ("EndFrame");
177 Sets everything to NULL
180 void ED_ClearEdict (edict_t *e)
182 memset (&e->v, 0, progs->entityfields * 4);
190 Either finds a free edict, or allocates a new one.
191 Try to avoid reusing an entity that was recently freed, because it
192 can cause the client to think the entity morphed into something else
193 instead of being removed and recreated, which can cause interpolated
194 angles and bad trails.
197 edict_t *ED_Alloc (void)
202 for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
205 // the first couple seconds of server time can involve a lot of
206 // freeing and allocating, so relax the replacement policy
207 if (e->free && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) )
215 Host_Error ("ED_Alloc: no free edicts");
228 Marks the edict as free
229 FIXME: walk all entities and NULL out references to this entity
232 void ED_Free (edict_t *ed)
234 SV_UnlinkEdict (ed); // unlink from world bsp
238 ed->v.takedamage = 0;
239 ed->v.modelindex = 0;
243 VectorClear(ed->v.origin);
244 VectorClear(ed->v.angles);
245 ed->v.nextthink = -1;
248 ed->freetime = sv.time;
251 //===========================================================================
258 ddef_t *ED_GlobalAtOfs (int ofs)
263 for (i=0 ; i<progs->numglobaldefs ; i++)
265 def = &pr_globaldefs[i];
277 ddef_t *ED_FieldAtOfs (int ofs)
282 for (i=0 ; i<progs->numfielddefs ; i++)
284 def = &pr_fielddefs[i];
296 ddef_t *ED_FindField (char *name)
301 for (i=0 ; i<progs->numfielddefs ; i++)
303 def = &pr_fielddefs[i];
304 if (!strcmp(pr_strings + def->s_name,name) )
315 ddef_t *ED_FindGlobal (char *name)
320 for (i=0 ; i<progs->numglobaldefs ; i++)
322 def = &pr_globaldefs[i];
323 if (!strcmp(pr_strings + def->s_name,name) )
335 dfunction_t *ED_FindFunction (char *name)
340 for (i=0 ; i<progs->numfunctions ; i++)
342 func = &pr_functions[i];
343 if (!strcmp(pr_strings + func->s_name,name) )
351 eval_t *GetEdictFieldValue(edict_t *ed, char *field)
357 for (i=0 ; i<GEFV_CACHESIZE ; i++)
359 if (!strcmp(field, gefvCache[i].field))
361 def = gefvCache[i].pcache;
366 def = ED_FindField (field);
368 if (strlen(field) < MAX_FIELD_LEN)
370 gefvCache[rep].pcache = def;
371 strcpy (gefvCache[rep].field, field);
379 return (eval_t *)((char *)&ed->v + def->ofs*4);
387 Returns a string describing *data in a type specific manner
390 char *PR_ValueString (etype_t type, eval_t *val)
392 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
396 type &= ~DEF_SAVEGLOBAL;
401 sprintf (line, "%s", pr_strings + val->string);
404 sprintf (line, "entity %i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)) );
407 f = pr_functions + val->function;
408 sprintf (line, "%s()", pr_strings + f->s_name);
411 def = ED_FieldAtOfs ( val->_int );
412 sprintf (line, ".%s", pr_strings + def->s_name);
415 sprintf (line, "void");
418 // LordHavoc: changed from %5.1f to %10.4f
419 sprintf (line, "%10.4f", val->_float);
422 // LordHavoc: changed from %5.1f to %10.4f
423 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
426 sprintf (line, "pointer");
429 sprintf (line, "bad type %i", type);
440 Returns a string describing *data in a type specific manner
441 Easier to parse than PR_ValueString
444 char *PR_UglyValueString (etype_t type, eval_t *val)
446 static char line[256];
450 type &= ~DEF_SAVEGLOBAL;
455 sprintf (line, "%s", pr_strings + val->string);
458 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
461 f = pr_functions + val->function;
462 sprintf (line, "%s", pr_strings + f->s_name);
465 def = ED_FieldAtOfs ( val->_int );
466 sprintf (line, "%s", pr_strings + def->s_name);
469 sprintf (line, "void");
472 sprintf (line, "%f", val->_float);
475 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
478 sprintf (line, "bad type %i", type);
489 Returns a string with a description and the contents of a global,
490 padded to 20 field width
493 char *PR_GlobalString (int ofs)
499 static char line[128];
501 val = (void *)&pr_globals[ofs];
502 def = ED_GlobalAtOfs(ofs);
504 sprintf (line,"%i(???)", ofs);
507 s = PR_ValueString (def->type, val);
508 sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s);
519 char *PR_GlobalStringNoContents (int ofs)
523 static char line[128];
525 def = ED_GlobalAtOfs(ofs);
527 sprintf (line,"%i(???)", ofs);
529 sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name);
547 // LordHavoc: optimized this to print out much more quickly (tempstring)
548 void ED_Print (edict_t *ed)
556 char tempstring[8192]; // temporary string buffer
560 Con_Printf ("FREE\n");
565 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
566 for (i=1 ; i<progs->numfielddefs ; i++)
568 d = &pr_fielddefs[i];
569 name = pr_strings + d->s_name;
570 if (name[strlen(name)-2] == '_')
571 continue; // skip _x, _y, _z vars
573 v = (int *)((char *)&ed->v + d->ofs*4);
575 // if the value is still all 0, skip the field
576 type = d->type & ~DEF_SAVEGLOBAL;
578 for (j=0 ; j<type_size[type] ; j++)
581 if (j == type_size[type])
584 strcat(tempstring, name);
585 for (l = strlen(name);l < 14;l++)
586 strcat(tempstring, " ");
587 strcat(tempstring, " ");
589 strcat(tempstring, PR_ValueString(d->type, (eval_t *)v));
590 strcat(tempstring, "\n");
592 Con_Printf(tempstring);
602 void ED_Write (QFile *f, edict_t *ed)
618 for (i=1 ; i<progs->numfielddefs ; i++)
620 d = &pr_fielddefs[i];
621 name = pr_strings + d->s_name;
622 if (name[strlen(name)-2] == '_')
623 continue; // skip _x, _y, _z vars
625 v = (int *)((char *)&ed->v + d->ofs*4);
627 // if the value is still all 0, skip the field
628 type = d->type & ~DEF_SAVEGLOBAL;
629 for (j=0 ; j<type_size[type] ; j++)
632 if (j == type_size[type])
635 Qprintf (f,"\"%s\" ",name);
636 Qprintf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
642 void ED_PrintNum (int ent)
644 ED_Print (EDICT_NUM(ent));
651 For debugging, prints all the entities in the current server
654 void ED_PrintEdicts (void)
658 Con_Printf ("%i entities\n", sv.num_edicts);
659 for (i=0 ; i<sv.num_edicts ; i++)
667 For debugging, prints a single edicy
670 void ED_PrintEdict_f (void)
674 i = atoi (Cmd_Argv(1));
675 if (i >= sv.num_edicts)
677 Con_Printf("Bad edict number\n");
694 int active, models, solid, step;
696 active = models = solid = step = 0;
697 for (i=0 ; i<sv.num_edicts ; i++)
707 if (ent->v.movetype == MOVETYPE_STEP)
711 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
712 Con_Printf ("active :%3i\n", active);
713 Con_Printf ("view :%3i\n", models);
714 Con_Printf ("touch :%3i\n", solid);
715 Con_Printf ("step :%3i\n", step);
720 ==============================================================================
724 FIXME: need to tag constants, doesn't really work
725 ==============================================================================
733 void ED_WriteGlobals (QFile *f)
741 for (i=0 ; i<progs->numglobaldefs ; i++)
743 def = &pr_globaldefs[i];
745 if ( !(def->type & DEF_SAVEGLOBAL) )
747 type &= ~DEF_SAVEGLOBAL;
749 if (type != ev_string && type != ev_float && type != ev_entity)
752 name = pr_strings + def->s_name;
753 Qprintf (f,"\"%s\" ", name);
754 Qprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
764 void ED_ParseGlobals (char *data)
766 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
772 data = COM_Parse (data);
773 if (com_token[0] == '}')
776 Host_Error ("ED_ParseEntity: EOF without closing brace");
778 strcpy (keyname, com_token);
781 data = COM_Parse (data);
783 Host_Error ("ED_ParseEntity: EOF without closing brace");
785 if (com_token[0] == '}')
786 Host_Error ("ED_ParseEntity: closing brace without data");
788 key = ED_FindGlobal (keyname);
791 Con_DPrintf ("'%s' is not a global\n", keyname);
795 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
796 Host_Error ("ED_ParseGlobals: parse error");
800 //============================================================================
808 char *ED_NewString (char *string)
813 l = strlen(string) + 1;
814 new = Hunk_AllocName (l, "edict string");
817 for (i=0 ; i< l ; i++)
819 if (string[i] == '\\' && i < l-1)
822 if (string[i] == 'n')
828 *new_p++ = string[i];
839 Can parse either fields or globals
840 returns false if error
843 qboolean ED_ParseEpair (void *base, ddef_t *key, char *s)
852 d = (void *)((int *)base + key->ofs);
854 switch (key->type & ~DEF_SAVEGLOBAL)
857 *(string_t *)d = ED_NewString (s) - pr_strings;
861 *(float *)d = atof (s);
868 for (i=0 ; i<3 ; i++)
870 while (*v && *v != ' ')
873 ((float *)d)[i] = atof (w);
879 *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
883 def = ED_FindField (s);
886 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
887 if (strcmp(s, "sky") && strcmp(s, "fog") && strncmp(s, "fog_", 4) && strcmp(s, "farclip"))
888 Con_DPrintf ("Can't find field %s\n", s);
891 *(int *)d = G_INT(def->ofs);
895 func = ED_FindFunction (s);
898 Con_DPrintf ("Can't find function %s\n", s);
901 *(func_t *)d = func - pr_functions;
914 Parses an edict out of the given string, returning the new position
915 ed should be a properly initialized empty edict.
916 Used for initial level load and for savegames.
919 char *ED_ParseEdict (char *data, edict_t *ent)
930 if (ent != sv.edicts) // hack
931 memset (&ent->v, 0, progs->entityfields * 4);
933 // go through all the dictionary pairs
937 data = COM_Parse (data);
938 if (com_token[0] == '}')
941 Host_Error ("ED_ParseEntity: EOF without closing brace");
943 // anglehack is to allow QuakeEd to write single scalar angles
944 // and allow them to be turned into vectors. (FIXME...)
945 if (!strcmp(com_token, "angle"))
947 strcpy (com_token, "angles");
953 // FIXME: change light to _light to get rid of this hack
954 if (!strcmp(com_token, "light"))
955 strcpy (com_token, "light_lev"); // hack for single light def
957 strcpy (keyname, com_token);
959 // another hack to fix heynames with trailing spaces
961 while (n && keyname[n-1] == ' ')
968 data = COM_Parse (data);
970 Host_Error ("ED_ParseEntity: EOF without closing brace");
972 if (com_token[0] == '}')
973 Host_Error ("ED_ParseEntity: closing brace without data");
977 // keynames with a leading underscore are used for utility comments,
978 // and are immediately discarded by quake
979 if (keyname[0] == '_')
982 key = ED_FindField (keyname);
985 Con_DPrintf ("'%s' is not a field\n", keyname);
992 strcpy (temp, com_token);
993 sprintf (com_token, "0 %s 0", temp);
996 if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
997 Host_Error ("ED_ParseEdict: parse error");
1011 The entities are directly placed in the array, rather than allocated with
1012 ED_Alloc, because otherwise an error loading the map would have entity
1013 number references out of order.
1015 Creates a server's entity / program execution context by
1016 parsing textual entity definitions out of an ent file.
1018 Used for both fresh maps and savegame loads. A fresh map would also need
1019 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1022 void ED_LoadFromFile (char *data)
1030 pr_global_struct->time = sv.time;
1035 // parse the opening brace
1036 data = COM_Parse (data);
1039 if (com_token[0] != '{')
1040 Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1046 data = ED_ParseEdict (data, ent);
1048 // remove things from different skill levels or deathmatch
1049 if (deathmatch.value)
1051 if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1058 else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY ))
1059 || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
1060 || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD )))
1068 // immediately call spawn function
1070 if (!ent->v.classname)
1072 Con_Printf ("No classname for:\n");
1078 // look for the spawn function
1079 func = ED_FindFunction ( pr_strings + ent->v.classname );
1083 if (developer.value) // don't confuse non-developers with errors
1085 Con_Printf ("No spawn function for:\n");
1092 pr_global_struct->self = EDICT_TO_PROG(ent);
1093 PR_ExecuteProgram (func - pr_functions, "");
1096 Con_DPrintf ("%i entities inhibited\n", inhibit);
1105 void PR_LoadProgs (void)
1110 // flush the non-C variable lookup cache
1111 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1112 gefvCache[i].field[0] = 0;
1114 progs = (dprograms_t *)COM_LoadHunkFile ("progs.dat", false);
1116 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1117 Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024);
1119 pr_crc = CRC_Block((byte *)progs, com_filesize);
1121 // byte swap the header
1122 for (i=0 ; i<sizeof(*progs)/4 ; i++)
1123 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1125 if (progs->version != PROG_VERSION)
1126 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1127 if (progs->crc != PROGHEADER_CRC)
1128 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1130 pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
1131 pr_strings = (char *)progs + progs->ofs_strings;
1132 pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
1133 pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
1134 pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
1136 pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);
1137 pr_globals = (float *)pr_global_struct;
1139 pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
1141 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1143 // byte swap the lumps
1144 for (i=0 ; i<progs->numstatements ; i++)
1146 pr_statements[i].op = LittleShort(pr_statements[i].op);
1147 pr_statements[i].a = LittleShort(pr_statements[i].a);
1148 pr_statements[i].b = LittleShort(pr_statements[i].b);
1149 pr_statements[i].c = LittleShort(pr_statements[i].c);
1152 for (i=0 ; i<progs->numfunctions; i++)
1154 pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
1155 pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
1156 pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
1157 pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
1158 pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
1159 pr_functions[i].locals = LittleLong (pr_functions[i].locals);
1162 for (i=0 ; i<progs->numglobaldefs ; i++)
1164 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1165 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1166 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1169 for (i=0 ; i<progs->numfielddefs ; i++)
1171 pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
1172 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1173 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1174 pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs);
1175 pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
1178 for (i=0 ; i<progs->numglobals ; i++)
1179 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1181 // LordHavoc: bounds check anything static
1182 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1188 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1189 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1192 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1193 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1195 // global global global
1230 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1231 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1233 // global none global
1239 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1240 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1256 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1257 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1271 if ((unsigned short) st->a >= progs->numglobals)
1272 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1275 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1280 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1284 void PR_Fields_f (void)
1289 Con_Printf("no progs loaded\n");
1292 for (i = 0;i < progs->numfielddefs;i++)
1293 Con_Printf("%s\n", (pr_strings + pr_fielddefs[i].s_name));
1294 Con_Printf("%i entity fields, totalling %i bytes per edict, %i edicts, %i bytes total spent on edict fields\n", progs->entityfields, progs->entityfields * 4, MAX_EDICTS, progs->entityfields * 4 * MAX_EDICTS);
1297 void PR_Globals_f (void)
1302 Con_Printf("no progs loaded\n");
1305 for (i = 0;i < progs->numglobaldefs;i++)
1306 Con_Printf("%s\n", (pr_strings + pr_globaldefs[i].s_name));
1307 Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1317 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1318 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1319 Cmd_AddCommand ("edictcount", ED_Count);
1320 Cmd_AddCommand ("profile", PR_Profile_f);
1321 Cmd_AddCommand ("pr_fields", PR_Fields_f);
1322 Cmd_AddCommand ("pr_globals", PR_Globals_f);
1323 Cvar_RegisterVariable (&pr_checkextension);
1324 Cvar_RegisterVariable (&nomonsters);
1325 Cvar_RegisterVariable (&gamecfg);
1326 Cvar_RegisterVariable (&scratch1);
1327 Cvar_RegisterVariable (&scratch2);
1328 Cvar_RegisterVariable (&scratch3);
1329 Cvar_RegisterVariable (&scratch4);
1330 Cvar_RegisterVariable (&savedgamecfg);
1331 Cvar_RegisterVariable (&saved1);
1332 Cvar_RegisterVariable (&saved2);
1333 Cvar_RegisterVariable (&saved3);
1334 Cvar_RegisterVariable (&saved4);
1335 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1336 Cvar_RegisterVariable (&decors);
1337 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1340 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1341 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1342 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1343 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1344 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1345 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1346 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1347 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1348 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1349 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1351 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1352 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1353 Cvar_RegisterVariable (&pr_boundscheck);
1356 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1357 edict_t *EDICT_NUM_ERROR(int n)
1359 Host_Error ("EDICT_NUM: bad number %i", n);
1363 edict_t *EDICT_NUM(int n)
1365 if (n < 0 || n >= sv.max_edicts)
1366 Sys_Error ("EDICT_NUM: bad number %i", n);
1367 return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size);
1371 int NUM_FOR_EDICT(edict_t *e)
1375 b = (byte *)e - (byte *)sv.edicts;
1376 b = b / pr_edict_size;
1378 if (b < 0 || b >= sv.num_edicts)
1379 Host_Error ("NUM_FOR_EDICT: bad pointer");