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 mempool_t *progs_mempool;
38 mempool_t *edictstring_mempool;
40 int type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
42 ddef_t *ED_FieldAtOfs (int ofs);
43 qboolean ED_ParseEpair (void *base, ddef_t *key, char *s);
45 cvar_t pr_checkextension = {0, "pr_checkextension", "1"};
46 cvar_t nomonsters = {0, "nomonsters", "0"};
47 cvar_t gamecfg = {0, "gamecfg", "0"};
48 cvar_t scratch1 = {0, "scratch1", "0"};
49 cvar_t scratch2 = {0,"scratch2", "0"};
50 cvar_t scratch3 = {0, "scratch3", "0"};
51 cvar_t scratch4 = {0, "scratch4", "0"};
52 cvar_t savedgamecfg = {CVAR_SAVE, "savedgamecfg", "0"};
53 cvar_t saved1 = {CVAR_SAVE, "saved1", "0"};
54 cvar_t saved2 = {CVAR_SAVE, "saved2", "0"};
55 cvar_t saved3 = {CVAR_SAVE, "saved3", "0"};
56 cvar_t saved4 = {CVAR_SAVE, "saved4", "0"};
57 cvar_t decors = {0, "decors", "0"};
58 cvar_t nehx00 = {0, "nehx00", "0"};cvar_t nehx01 = {0, "nehx01", "0"};
59 cvar_t nehx02 = {0, "nehx02", "0"};cvar_t nehx03 = {0, "nehx03", "0"};
60 cvar_t nehx04 = {0, "nehx04", "0"};cvar_t nehx05 = {0, "nehx05", "0"};
61 cvar_t nehx06 = {0, "nehx06", "0"};cvar_t nehx07 = {0, "nehx07", "0"};
62 cvar_t nehx08 = {0, "nehx08", "0"};cvar_t nehx09 = {0, "nehx09", "0"};
63 cvar_t nehx10 = {0, "nehx10", "0"};cvar_t nehx11 = {0, "nehx11", "0"};
64 cvar_t nehx12 = {0, "nehx12", "0"};cvar_t nehx13 = {0, "nehx13", "0"};
65 cvar_t nehx14 = {0, "nehx14", "0"};cvar_t nehx15 = {0, "nehx15", "0"};
66 cvar_t nehx16 = {0, "nehx16", "0"};cvar_t nehx17 = {0, "nehx17", "0"};
67 cvar_t nehx18 = {0, "nehx18", "0"};cvar_t nehx19 = {0, "nehx19", "0"};
68 cvar_t cutscene = {0, "cutscene", "1"};
69 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
70 cvar_t pr_boundscheck = {0, "pr_boundscheck", "1"};
72 #define MAX_FIELD_LEN 64
73 #define GEFV_CACHESIZE 2
77 char field[MAX_FIELD_LEN];
80 static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};
82 ddef_t *ED_FindField (char *name);
83 dfunction_t *ED_FindFunction (char *name);
85 // LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue... these are defined as externs in progs.h
99 int eval_renderamt; // HalfLife support
100 int eval_rendermode; // HalfLife support
102 int eval_ammo_shells1;
103 int eval_ammo_nails1;
104 int eval_ammo_lava_nails;
105 int eval_ammo_rockets1;
106 int eval_ammo_multi_rockets;
107 int eval_ammo_cells1;
108 int eval_ammo_plasma;
110 int eval_pitch_speed;
111 int eval_viewmodelforclient;
112 int eval_nodrawtoclient;
113 int eval_exteriormodeltoclient;
114 int eval_drawonlytoclient;
118 int eval_punchvector;
121 dfunction_t *SV_PlayerPhysicsQC;
122 dfunction_t *EndFrameQC;
124 int FindFieldOffset(char *field)
127 d = ED_FindField(field);
133 void FindEdictFieldOffsets(void)
135 eval_gravity = FindFieldOffset("gravity");
136 eval_button3 = FindFieldOffset("button3");
137 eval_button4 = FindFieldOffset("button4");
138 eval_button5 = FindFieldOffset("button5");
139 eval_button6 = FindFieldOffset("button6");
140 eval_button7 = FindFieldOffset("button7");
141 eval_button8 = FindFieldOffset("button8");
142 eval_glow_size = FindFieldOffset("glow_size");
143 eval_glow_trail = FindFieldOffset("glow_trail");
144 eval_glow_color = FindFieldOffset("glow_color");
145 eval_items2 = FindFieldOffset("items2");
146 eval_scale = FindFieldOffset("scale");
147 eval_alpha = FindFieldOffset("alpha");
148 eval_renderamt = FindFieldOffset("renderamt"); // HalfLife support
149 eval_rendermode = FindFieldOffset("rendermode"); // HalfLife support
150 eval_fullbright = FindFieldOffset("fullbright");
151 eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
152 eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
153 eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
154 eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
155 eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
156 eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
157 eval_ammo_plasma = FindFieldOffset("ammo_plasma");
158 eval_idealpitch = FindFieldOffset("idealpitch");
159 eval_pitch_speed = FindFieldOffset("pitch_speed");
160 eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
161 eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
162 eval_exteriormodeltoclient = FindFieldOffset("exteriormodeltoclient");
163 eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
164 eval_ping = FindFieldOffset("ping");
165 eval_movement = FindFieldOffset("movement");
166 eval_pmodel = FindFieldOffset("pmodel");
167 eval_punchvector = FindFieldOffset("punchvector");
168 eval_viewzoom = FindFieldOffset("viewzoom");
170 // LordHavoc: allowing QuakeC to override the player movement code
171 SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
172 // LordHavoc: support for endframe
173 EndFrameQC = ED_FindFunction ("EndFrame");
180 Sets everything to NULL
183 void ED_ClearEdict (edict_t *e)
185 memset (&e->v, 0, progs->entityfields * 4);
193 Either finds a free edict, or allocates a new one.
194 Try to avoid reusing an entity that was recently freed, because it
195 can cause the client to think the entity morphed into something else
196 instead of being removed and recreated, which can cause interpolated
197 angles and bad trails.
200 edict_t *ED_Alloc (void)
205 for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
208 // the first couple seconds of server time can involve a lot of
209 // freeing and allocating, so relax the replacement policy
210 if (e->free && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) )
218 Host_Error ("ED_Alloc: no free edicts");
231 Marks the edict as free
232 FIXME: walk all entities and NULL out references to this entity
235 void ED_Free (edict_t *ed)
237 SV_UnlinkEdict (ed); // unlink from world bsp
241 ed->v.takedamage = 0;
242 ed->v.modelindex = 0;
246 VectorClear(ed->v.origin);
247 VectorClear(ed->v.angles);
248 ed->v.nextthink = -1;
251 ed->freetime = sv.time;
254 //===========================================================================
261 ddef_t *ED_GlobalAtOfs (int ofs)
266 for (i=0 ; i<progs->numglobaldefs ; i++)
268 def = &pr_globaldefs[i];
280 ddef_t *ED_FieldAtOfs (int ofs)
285 for (i=0 ; i<progs->numfielddefs ; i++)
287 def = &pr_fielddefs[i];
299 ddef_t *ED_FindField (char *name)
304 for (i=0 ; i<progs->numfielddefs ; i++)
306 def = &pr_fielddefs[i];
307 if (!strcmp(pr_strings + def->s_name,name) )
318 ddef_t *ED_FindGlobal (char *name)
323 for (i=0 ; i<progs->numglobaldefs ; i++)
325 def = &pr_globaldefs[i];
326 if (!strcmp(pr_strings + def->s_name,name) )
338 dfunction_t *ED_FindFunction (char *name)
343 for (i=0 ; i<progs->numfunctions ; i++)
345 func = &pr_functions[i];
346 if (!strcmp(pr_strings + func->s_name,name) )
354 eval_t *GetEdictFieldValue(edict_t *ed, char *field)
360 for (i=0 ; i<GEFV_CACHESIZE ; i++)
362 if (!strcmp(field, gefvCache[i].field))
364 def = gefvCache[i].pcache;
369 def = ED_FindField (field);
371 if (strlen(field) < MAX_FIELD_LEN)
373 gefvCache[rep].pcache = def;
374 strcpy (gefvCache[rep].field, field);
382 return (eval_t *)((char *)&ed->v + def->ofs*4);
390 Returns a string describing *data in a type specific manner
393 int NoCrash_NUM_FOR_EDICT(edict_t *e);
394 char *PR_ValueString (etype_t type, eval_t *val)
396 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
401 type &= ~DEF_SAVEGLOBAL;
406 sprintf (line, "%s", pr_strings + val->string);
409 n = NoCrash_NUM_FOR_EDICT(PROG_TO_EDICT(val->edict));
410 if (n < 0 || n >= MAX_EDICTS)
411 sprintf (line, "entity %i (invalid!)", n);
413 sprintf (line, "entity %i", n);
416 f = pr_functions + val->function;
417 sprintf (line, "%s()", pr_strings + f->s_name);
420 def = ED_FieldAtOfs ( val->_int );
421 sprintf (line, ".%s", pr_strings + def->s_name);
424 sprintf (line, "void");
427 // LordHavoc: changed from %5.1f to %10.4f
428 sprintf (line, "%10.4f", val->_float);
431 // LordHavoc: changed from %5.1f to %10.4f
432 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
435 sprintf (line, "pointer");
438 sprintf (line, "bad type %i", type);
449 Returns a string describing *data in a type specific manner
450 Easier to parse than PR_ValueString
453 char *PR_UglyValueString (etype_t type, eval_t *val)
455 static char line[4096];
461 type &= ~DEF_SAVEGLOBAL;
466 sprintf (line, "%s", pr_strings + val->string);
469 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
472 f = pr_functions + val->function;
473 sprintf (line, "%s", pr_strings + f->s_name);
476 def = ED_FieldAtOfs ( val->_int );
477 // LordHavoc: parse the string a bit to turn special characters
478 // (like newline, specifically) into escape codes,
479 // this fixes saving games from various mods
480 //sprintf (line, "%s", pr_strings + def->s_name);
481 s = pr_strings + def->s_name;
482 for (i = 0;i < 4095 && *s;)
501 sprintf (line, "void");
504 sprintf (line, "%f", val->_float);
507 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
510 sprintf (line, "bad type %i", type);
521 Returns a string with a description and the contents of a global,
522 padded to 20 field width
525 char *PR_GlobalString (int ofs)
531 static char line[128];
533 val = (void *)&pr_globals[ofs];
534 def = ED_GlobalAtOfs(ofs);
536 sprintf (line,"%i(\?\?\?)", ofs); // LordHavoc: escaping the ?s so it is not a trigraph
539 s = PR_ValueString (def->type, val);
540 sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s);
551 char *PR_GlobalStringNoContents (int ofs)
555 static char line[128];
557 def = ED_GlobalAtOfs(ofs);
559 sprintf (line,"%i(\?\?\?)", ofs); // LordHavoc: escaping the ?s so it is not a trigraph
561 sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name);
579 // LordHavoc: optimized this to print out much more quickly (tempstring)
580 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
581 void ED_Print (edict_t *ed)
589 char tempstring[8192], tempstring2[260]; // temporary string buffers
593 Con_Printf ("FREE\n");
598 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
599 for (i=1 ; i<progs->numfielddefs ; i++)
601 d = &pr_fielddefs[i];
602 name = pr_strings + d->s_name;
603 if (name[strlen(name)-2] == '_')
604 continue; // skip _x, _y, _z vars
606 v = (int *)((char *)&ed->v + d->ofs*4);
608 // if the value is still all 0, skip the field
609 type = d->type & ~DEF_SAVEGLOBAL;
611 for (j=0 ; j<type_size[type] ; j++)
614 if (j == type_size[type])
617 if (strlen(name) > 256)
619 strncpy(tempstring2, name, 256);
620 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
621 tempstring2[259] = 0;
624 strcat(tempstring, name);
625 for (l = strlen(name);l < 14;l++)
626 strcat(tempstring, " ");
627 strcat(tempstring, " ");
629 name = PR_ValueString(d->type, (eval_t *)v);
630 if (strlen(name) > 256)
632 strncpy(tempstring2, name, 256);
633 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
634 tempstring2[259] = 0;
637 strcat(tempstring, name);
638 strcat(tempstring, "\n");
639 if (strlen(tempstring) >= 4096)
641 Con_Printf("%s", tempstring);
646 Con_Printf("%s", tempstring);
656 void ED_Write (QFile *f, edict_t *ed)
672 for (i=1 ; i<progs->numfielddefs ; i++)
674 d = &pr_fielddefs[i];
675 name = pr_strings + d->s_name;
676 if (name[strlen(name)-2] == '_')
677 continue; // skip _x, _y, _z vars
679 v = (int *)((char *)&ed->v + d->ofs*4);
681 // if the value is still all 0, skip the field
682 type = d->type & ~DEF_SAVEGLOBAL;
683 for (j=0 ; j<type_size[type] ; j++)
686 if (j == type_size[type])
689 Qprintf (f,"\"%s\" ",name);
690 Qprintf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
696 void ED_PrintNum (int ent)
698 ED_Print (EDICT_NUM(ent));
705 For debugging, prints all the entities in the current server
708 void ED_PrintEdicts (void)
712 Con_Printf ("%i entities\n", sv.num_edicts);
713 for (i=0 ; i<sv.num_edicts ; i++)
721 For debugging, prints a single edicy
724 void ED_PrintEdict_f (void)
728 i = atoi (Cmd_Argv(1));
729 if (i >= sv.num_edicts)
731 Con_Printf("Bad edict number\n");
748 int active, models, solid, step;
750 active = models = solid = step = 0;
751 for (i=0 ; i<sv.num_edicts ; i++)
761 if (ent->v.movetype == MOVETYPE_STEP)
765 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
766 Con_Printf ("active :%3i\n", active);
767 Con_Printf ("view :%3i\n", models);
768 Con_Printf ("touch :%3i\n", solid);
769 Con_Printf ("step :%3i\n", step);
774 ==============================================================================
778 FIXME: need to tag constants, doesn't really work
779 ==============================================================================
787 void ED_WriteGlobals (QFile *f)
795 for (i=0 ; i<progs->numglobaldefs ; i++)
797 def = &pr_globaldefs[i];
799 if ( !(def->type & DEF_SAVEGLOBAL) )
801 type &= ~DEF_SAVEGLOBAL;
803 if (type != ev_string && type != ev_float && type != ev_entity)
806 name = pr_strings + def->s_name;
807 Qprintf (f,"\"%s\" ", name);
808 Qprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
818 void ED_ParseGlobals (char *data)
820 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
826 data = COM_Parse (data);
827 if (com_token[0] == '}')
830 Host_Error ("ED_ParseEntity: EOF without closing brace");
832 strcpy (keyname, com_token);
835 data = COM_Parse (data);
837 Host_Error ("ED_ParseEntity: EOF without closing brace");
839 if (com_token[0] == '}')
840 Host_Error ("ED_ParseEntity: closing brace without data");
842 key = ED_FindGlobal (keyname);
845 Con_DPrintf ("'%s' is not a global\n", keyname);
849 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
850 Host_Error ("ED_ParseGlobals: parse error");
854 //============================================================================
862 char *ED_NewString (char *string)
867 l = strlen(string) + 1;
868 new = Mem_Alloc(edictstring_mempool, l);
871 for (i=0 ; i< l ; i++)
873 if (string[i] == '\\' && i < l-1)
876 if (string[i] == 'n')
882 *new_p++ = string[i];
893 Can parse either fields or globals
894 returns false if error
897 qboolean ED_ParseEpair (void *base, ddef_t *key, char *s)
906 d = (void *)((int *)base + key->ofs);
908 switch (key->type & ~DEF_SAVEGLOBAL)
911 *(string_t *)d = ED_NewString (s) - pr_strings;
915 *(float *)d = atof (s);
922 for (i=0 ; i<3 ; i++)
924 while (*v && *v != ' ')
927 ((float *)d)[i] = atof (w);
933 *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
937 def = ED_FindField (s);
940 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
941 if (strcmp(s, "sky") && strcmp(s, "fog") && strncmp(s, "fog_", 4) && strcmp(s, "farclip"))
942 Con_DPrintf ("Can't find field %s\n", s);
945 *(int *)d = G_INT(def->ofs);
949 func = ED_FindFunction (s);
952 Con_DPrintf ("Can't find function %s\n", s);
955 *(func_t *)d = func - pr_functions;
968 Parses an edict out of the given string, returning the new position
969 ed should be a properly initialized empty edict.
970 Used for initial level load and for savegames.
973 char *ED_ParseEdict (char *data, edict_t *ent)
984 if (ent != sv.edicts) // hack
985 memset (&ent->v, 0, progs->entityfields * 4);
987 // go through all the dictionary pairs
991 data = COM_Parse (data);
992 if (com_token[0] == '}')
995 Host_Error ("ED_ParseEntity: EOF without closing brace");
997 // anglehack is to allow QuakeEd to write single scalar angles
998 // and allow them to be turned into vectors. (FIXME...)
999 if (!strcmp(com_token, "angle"))
1001 strcpy (com_token, "angles");
1007 // FIXME: change light to _light to get rid of this hack
1008 if (!strcmp(com_token, "light"))
1009 strcpy (com_token, "light_lev"); // hack for single light def
1011 strcpy (keyname, com_token);
1013 // another hack to fix heynames with trailing spaces
1014 n = strlen(keyname);
1015 while (n && keyname[n-1] == ' ')
1022 data = COM_Parse (data);
1024 Host_Error ("ED_ParseEntity: EOF without closing brace");
1026 if (com_token[0] == '}')
1027 Host_Error ("ED_ParseEntity: closing brace without data");
1031 // keynames with a leading underscore are used for utility comments,
1032 // and are immediately discarded by quake
1033 if (keyname[0] == '_')
1036 key = ED_FindField (keyname);
1039 Con_DPrintf ("'%s' is not a field\n", keyname);
1046 strcpy (temp, com_token);
1047 sprintf (com_token, "0 %s 0", temp);
1050 if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
1051 Host_Error ("ED_ParseEdict: parse error");
1065 The entities are directly placed in the array, rather than allocated with
1066 ED_Alloc, because otherwise an error loading the map would have entity
1067 number references out of order.
1069 Creates a server's entity / program execution context by
1070 parsing textual entity definitions out of an ent file.
1072 Used for both fresh maps and savegame loads. A fresh map would also need
1073 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1076 void ED_LoadFromFile (char *data)
1084 pr_global_struct->time = sv.time;
1089 // parse the opening brace
1090 data = COM_Parse (data);
1093 if (com_token[0] != '{')
1094 Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1100 data = ED_ParseEdict (data, ent);
1102 // remove things from different skill levels or deathmatch
1103 if (deathmatch.integer)
1105 if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1112 else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY ))
1113 || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
1114 || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD )))
1122 // immediately call spawn function
1124 if (!ent->v.classname)
1126 Con_Printf ("No classname for:\n");
1132 // look for the spawn function
1133 func = ED_FindFunction ( pr_strings + ent->v.classname );
1137 if (developer.integer) // don't confuse non-developers with errors
1139 Con_Printf ("No spawn function for:\n");
1146 pr_global_struct->self = EDICT_TO_PROG(ent);
1147 PR_ExecuteProgram (func - pr_functions, "");
1150 Con_DPrintf ("%i entities inhibited\n", inhibit);
1154 typedef struct dpfield_s
1161 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1163 dpfield_t dpfields[] =
1165 {ev_float, "gravity"},
1166 {ev_float, "button3"},
1167 {ev_float, "button4"},
1168 {ev_float, "button5"},
1169 {ev_float, "button6"},
1170 {ev_float, "button7"},
1171 {ev_float, "button8"},
1172 {ev_float, "glow_size"},
1173 {ev_float, "glow_trail"},
1174 {ev_float, "glow_color"},
1175 {ev_float, "items2"},
1176 {ev_float, "scale"},
1177 {ev_float, "alpha"},
1178 {ev_float, "renderamt"},
1179 {ev_float, "rendermode"},
1180 {ev_float, "fullbright"},
1181 {ev_float, "ammo_shells1"},
1182 {ev_float, "ammo_nails1"},
1183 {ev_float, "ammo_lava_nails"},
1184 {ev_float, "ammo_rockets1"},
1185 {ev_float, "ammo_multi_rockets"},
1186 {ev_float, "ammo_cells1"},
1187 {ev_float, "ammo_plasma"},
1188 {ev_float, "idealpitch"},
1189 {ev_float, "pitch_speed"},
1190 {ev_entity, "viewmodelforclient"},
1191 {ev_entity, "nodrawtoclient"},
1192 {ev_entity, "exteriormodeltoclient"},
1193 {ev_entity, "drawonlytoclient"},
1195 {ev_vector, "movement"},
1196 {ev_float, "pmodel"},
1197 {ev_vector, "punchvector"}
1205 void PR_LoadProgs (void)
1209 ddef_t *infielddefs;
1212 // flush the non-C variable lookup cache
1213 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1214 gefvCache[i].field[0] = 0;
1216 Mem_EmptyPool(progs_mempool);
1217 Mem_EmptyPool(edictstring_mempool);
1219 temp = COM_LoadFile ("progs.dat", false);
1221 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1223 progs = (dprograms_t *)Mem_Alloc(progs_mempool, com_filesize);
1225 memcpy(progs, temp, com_filesize);
1228 Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024);
1230 pr_crc = CRC_Block((qbyte *)progs, com_filesize);
1232 // byte swap the header
1233 for (i=0 ; i<sizeof(*progs)/4 ; i++)
1234 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1236 if (progs->version != PROG_VERSION)
1237 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1238 if (progs->crc != PROGHEADER_CRC)
1239 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1241 pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1242 pr_strings = (char *)progs + progs->ofs_strings;
1243 pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1245 // we need to expand the fielddefs list to include all the engine fields,
1246 // so allocate a new place for it
1247 infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1248 pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1250 pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1252 // moved edict_size calculation down below field adding code
1254 pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1255 pr_globals = (float *)pr_global_struct;
1257 // byte swap the lumps
1258 for (i=0 ; i<progs->numstatements ; i++)
1260 pr_statements[i].op = LittleShort(pr_statements[i].op);
1261 pr_statements[i].a = LittleShort(pr_statements[i].a);
1262 pr_statements[i].b = LittleShort(pr_statements[i].b);
1263 pr_statements[i].c = LittleShort(pr_statements[i].c);
1266 for (i=0 ; i<progs->numfunctions; i++)
1268 pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
1269 pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
1270 pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
1271 pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
1272 pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
1273 pr_functions[i].locals = LittleLong (pr_functions[i].locals);
1276 for (i=0 ; i<progs->numglobaldefs ; i++)
1278 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1279 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1280 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1283 // copy the progs fields to the new fields list
1284 for (i = 0;i < progs->numfielddefs;i++)
1286 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1287 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1288 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1289 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1290 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1293 // append the darkplaces fields
1294 for (i = 0;i < DPFIELDS;i++)
1296 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1297 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1298 pr_fielddefs[progs->numfielddefs].s_name = dpfields[i].string - pr_strings;
1299 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1300 progs->entityfields += 3;
1302 progs->entityfields++;
1303 progs->numfielddefs++;
1306 for (i=0 ; i<progs->numglobals ; i++)
1307 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1309 // moved edict_size calculation down here, below field adding code
1310 pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
1312 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1314 // LordHavoc: bounds check anything static
1315 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1321 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1322 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1325 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1326 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1328 // global global global
1363 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1364 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1366 // global none global
1372 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1373 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1389 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1390 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1404 if ((unsigned short) st->a >= progs->numglobals)
1405 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1408 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1413 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1417 void PR_Fields_f (void)
1422 Con_Printf("no progs loaded\n");
1425 for (i = 0;i < progs->numfielddefs;i++)
1426 Con_Printf("%s\n", (pr_strings + pr_fielddefs[i].s_name));
1427 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);
1430 void PR_Globals_f (void)
1435 Con_Printf("no progs loaded\n");
1438 for (i = 0;i < progs->numglobaldefs;i++)
1439 Con_Printf("%s\n", (pr_strings + pr_globaldefs[i].s_name));
1440 Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1450 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1451 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1452 Cmd_AddCommand ("edictcount", ED_Count);
1453 Cmd_AddCommand ("profile", PR_Profile_f);
1454 Cmd_AddCommand ("pr_fields", PR_Fields_f);
1455 Cmd_AddCommand ("pr_globals", PR_Globals_f);
1456 Cvar_RegisterVariable (&pr_checkextension);
1457 Cvar_RegisterVariable (&nomonsters);
1458 Cvar_RegisterVariable (&gamecfg);
1459 Cvar_RegisterVariable (&scratch1);
1460 Cvar_RegisterVariable (&scratch2);
1461 Cvar_RegisterVariable (&scratch3);
1462 Cvar_RegisterVariable (&scratch4);
1463 Cvar_RegisterVariable (&savedgamecfg);
1464 Cvar_RegisterVariable (&saved1);
1465 Cvar_RegisterVariable (&saved2);
1466 Cvar_RegisterVariable (&saved3);
1467 Cvar_RegisterVariable (&saved4);
1468 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1469 Cvar_RegisterVariable (&decors);
1470 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1471 if (gamemode == GAME_NEHAHRA)
1473 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1474 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1475 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1476 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1477 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1478 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1479 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1480 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1481 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1482 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1484 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1485 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1486 Cvar_RegisterVariable (&pr_boundscheck);
1488 progs_mempool = Mem_AllocPool("progs.dat");
1489 edictstring_mempool = Mem_AllocPool("edict strings");
1492 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1493 edict_t *EDICT_NUM_ERROR(int n)
1495 Host_Error ("EDICT_NUM: bad number %i", n);
1499 edict_t *EDICT_NUM(int n)
1501 if (n < 0 || n >= sv.max_edicts)
1502 Sys_Error ("EDICT_NUM: bad number %i", n);
1503 return (edict_t *)((qbyte *)sv.edicts+ (n)*pr_edict_size);
1507 int NUM_FOR_EDICT(edict_t *e)
1511 b = (qbyte *)e - (qbyte *)sv.edicts;
1512 b = b / pr_edict_size;
1514 if (b < 0 || b >= sv.num_edicts)
1515 Host_Error ("NUM_FOR_EDICT: bad pointer");
1519 int NoCrash_NUM_FOR_EDICT(edict_t *e)
1523 b = (qbyte *)e - (qbyte *)sv.edicts;
1524 b = b / pr_edict_size;