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;
120 dfunction_t *SV_PlayerPhysicsQC;
121 dfunction_t *EndFrameQC;
123 int FindFieldOffset(char *field)
126 d = ED_FindField(field);
132 void FindEdictFieldOffsets(void)
134 eval_gravity = FindFieldOffset("gravity");
135 eval_button3 = FindFieldOffset("button3");
136 eval_button4 = FindFieldOffset("button4");
137 eval_button5 = FindFieldOffset("button5");
138 eval_button6 = FindFieldOffset("button6");
139 eval_button7 = FindFieldOffset("button7");
140 eval_button8 = FindFieldOffset("button8");
141 eval_glow_size = FindFieldOffset("glow_size");
142 eval_glow_trail = FindFieldOffset("glow_trail");
143 eval_glow_color = FindFieldOffset("glow_color");
144 eval_items2 = FindFieldOffset("items2");
145 eval_scale = FindFieldOffset("scale");
146 eval_alpha = FindFieldOffset("alpha");
147 eval_renderamt = FindFieldOffset("renderamt"); // HalfLife support
148 eval_rendermode = FindFieldOffset("rendermode"); // HalfLife support
149 eval_fullbright = FindFieldOffset("fullbright");
150 eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
151 eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
152 eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
153 eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
154 eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
155 eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
156 eval_ammo_plasma = FindFieldOffset("ammo_plasma");
157 eval_idealpitch = FindFieldOffset("idealpitch");
158 eval_pitch_speed = FindFieldOffset("pitch_speed");
159 eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
160 eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
161 eval_exteriormodeltoclient = FindFieldOffset("exteriormodeltoclient");
162 eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
163 eval_ping = FindFieldOffset("ping");
164 eval_movement = FindFieldOffset("movement");
165 eval_pmodel = FindFieldOffset("pmodel");
166 eval_punchvector = FindFieldOffset("punchvector");
168 // LordHavoc: allowing QuakeC to override the player movement code
169 SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
170 // LordHavoc: support for endframe
171 EndFrameQC = ED_FindFunction ("EndFrame");
178 Sets everything to NULL
181 void ED_ClearEdict (edict_t *e)
183 memset (&e->v, 0, progs->entityfields * 4);
191 Either finds a free edict, or allocates a new one.
192 Try to avoid reusing an entity that was recently freed, because it
193 can cause the client to think the entity morphed into something else
194 instead of being removed and recreated, which can cause interpolated
195 angles and bad trails.
198 edict_t *ED_Alloc (void)
203 for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
206 // the first couple seconds of server time can involve a lot of
207 // freeing and allocating, so relax the replacement policy
208 if (e->free && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) )
216 Host_Error ("ED_Alloc: no free edicts");
229 Marks the edict as free
230 FIXME: walk all entities and NULL out references to this entity
233 void ED_Free (edict_t *ed)
235 SV_UnlinkEdict (ed); // unlink from world bsp
239 ed->v.takedamage = 0;
240 ed->v.modelindex = 0;
244 VectorClear(ed->v.origin);
245 VectorClear(ed->v.angles);
246 ed->v.nextthink = -1;
249 ed->freetime = sv.time;
252 //===========================================================================
259 ddef_t *ED_GlobalAtOfs (int ofs)
264 for (i=0 ; i<progs->numglobaldefs ; i++)
266 def = &pr_globaldefs[i];
278 ddef_t *ED_FieldAtOfs (int ofs)
283 for (i=0 ; i<progs->numfielddefs ; i++)
285 def = &pr_fielddefs[i];
297 ddef_t *ED_FindField (char *name)
302 for (i=0 ; i<progs->numfielddefs ; i++)
304 def = &pr_fielddefs[i];
305 if (!strcmp(pr_strings + def->s_name,name) )
316 ddef_t *ED_FindGlobal (char *name)
321 for (i=0 ; i<progs->numglobaldefs ; i++)
323 def = &pr_globaldefs[i];
324 if (!strcmp(pr_strings + def->s_name,name) )
336 dfunction_t *ED_FindFunction (char *name)
341 for (i=0 ; i<progs->numfunctions ; i++)
343 func = &pr_functions[i];
344 if (!strcmp(pr_strings + func->s_name,name) )
352 eval_t *GetEdictFieldValue(edict_t *ed, char *field)
358 for (i=0 ; i<GEFV_CACHESIZE ; i++)
360 if (!strcmp(field, gefvCache[i].field))
362 def = gefvCache[i].pcache;
367 def = ED_FindField (field);
369 if (strlen(field) < MAX_FIELD_LEN)
371 gefvCache[rep].pcache = def;
372 strcpy (gefvCache[rep].field, field);
380 return (eval_t *)((char *)&ed->v + def->ofs*4);
388 Returns a string describing *data in a type specific manner
391 int NoCrash_NUM_FOR_EDICT(edict_t *e);
392 char *PR_ValueString (etype_t type, eval_t *val)
394 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
399 type &= ~DEF_SAVEGLOBAL;
404 sprintf (line, "%s", pr_strings + val->string);
407 n = NoCrash_NUM_FOR_EDICT(PROG_TO_EDICT(val->edict));
408 if (n < 0 || n >= MAX_EDICTS)
409 sprintf (line, "entity %i (invalid!)", n);
411 sprintf (line, "entity %i", n);
414 f = pr_functions + val->function;
415 sprintf (line, "%s()", pr_strings + f->s_name);
418 def = ED_FieldAtOfs ( val->_int );
419 sprintf (line, ".%s", pr_strings + def->s_name);
422 sprintf (line, "void");
425 // LordHavoc: changed from %5.1f to %10.4f
426 sprintf (line, "%10.4f", val->_float);
429 // LordHavoc: changed from %5.1f to %10.4f
430 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
433 sprintf (line, "pointer");
436 sprintf (line, "bad type %i", type);
447 Returns a string describing *data in a type specific manner
448 Easier to parse than PR_ValueString
451 char *PR_UglyValueString (etype_t type, eval_t *val)
453 static char line[256];
457 type &= ~DEF_SAVEGLOBAL;
462 sprintf (line, "%s", pr_strings + val->string);
465 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
468 f = pr_functions + val->function;
469 sprintf (line, "%s", pr_strings + f->s_name);
472 def = ED_FieldAtOfs ( val->_int );
473 sprintf (line, "%s", pr_strings + def->s_name);
476 sprintf (line, "void");
479 sprintf (line, "%f", val->_float);
482 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
485 sprintf (line, "bad type %i", type);
496 Returns a string with a description and the contents of a global,
497 padded to 20 field width
500 char *PR_GlobalString (int ofs)
506 static char line[128];
508 val = (void *)&pr_globals[ofs];
509 def = ED_GlobalAtOfs(ofs);
511 sprintf (line,"%i(\?\?\?)", ofs); // LordHavoc: escaping the ?s so it is not a trigraph
514 s = PR_ValueString (def->type, val);
515 sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s);
526 char *PR_GlobalStringNoContents (int ofs)
530 static char line[128];
532 def = ED_GlobalAtOfs(ofs);
534 sprintf (line,"%i(\?\?\?)", ofs); // LordHavoc: escaping the ?s so it is not a trigraph
536 sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name);
554 // LordHavoc: optimized this to print out much more quickly (tempstring)
555 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
556 void ED_Print (edict_t *ed)
564 char tempstring[8192], tempstring2[260]; // temporary string buffers
568 Con_Printf ("FREE\n");
573 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
574 for (i=1 ; i<progs->numfielddefs ; i++)
576 d = &pr_fielddefs[i];
577 name = pr_strings + d->s_name;
578 if (name[strlen(name)-2] == '_')
579 continue; // skip _x, _y, _z vars
581 v = (int *)((char *)&ed->v + d->ofs*4);
583 // if the value is still all 0, skip the field
584 type = d->type & ~DEF_SAVEGLOBAL;
586 for (j=0 ; j<type_size[type] ; j++)
589 if (j == type_size[type])
592 if (strlen(name) > 256)
594 strncpy(tempstring2, name, 256);
595 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
596 tempstring2[259] = 0;
599 strcat(tempstring, name);
600 for (l = strlen(name);l < 14;l++)
601 strcat(tempstring, " ");
602 strcat(tempstring, " ");
604 name = PR_ValueString(d->type, (eval_t *)v);
605 if (strlen(name) > 256)
607 strncpy(tempstring2, name, 256);
608 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
609 tempstring2[259] = 0;
612 strcat(tempstring, name);
613 strcat(tempstring, "\n");
614 if (strlen(tempstring) >= 4096)
616 Con_Printf("%s", tempstring);
621 Con_Printf("%s", tempstring);
631 void ED_Write (QFile *f, edict_t *ed)
647 for (i=1 ; i<progs->numfielddefs ; i++)
649 d = &pr_fielddefs[i];
650 name = pr_strings + d->s_name;
651 if (name[strlen(name)-2] == '_')
652 continue; // skip _x, _y, _z vars
654 v = (int *)((char *)&ed->v + d->ofs*4);
656 // if the value is still all 0, skip the field
657 type = d->type & ~DEF_SAVEGLOBAL;
658 for (j=0 ; j<type_size[type] ; j++)
661 if (j == type_size[type])
664 Qprintf (f,"\"%s\" ",name);
665 Qprintf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
671 void ED_PrintNum (int ent)
673 ED_Print (EDICT_NUM(ent));
680 For debugging, prints all the entities in the current server
683 void ED_PrintEdicts (void)
687 Con_Printf ("%i entities\n", sv.num_edicts);
688 for (i=0 ; i<sv.num_edicts ; i++)
696 For debugging, prints a single edicy
699 void ED_PrintEdict_f (void)
703 i = atoi (Cmd_Argv(1));
704 if (i >= sv.num_edicts)
706 Con_Printf("Bad edict number\n");
723 int active, models, solid, step;
725 active = models = solid = step = 0;
726 for (i=0 ; i<sv.num_edicts ; i++)
736 if (ent->v.movetype == MOVETYPE_STEP)
740 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
741 Con_Printf ("active :%3i\n", active);
742 Con_Printf ("view :%3i\n", models);
743 Con_Printf ("touch :%3i\n", solid);
744 Con_Printf ("step :%3i\n", step);
749 ==============================================================================
753 FIXME: need to tag constants, doesn't really work
754 ==============================================================================
762 void ED_WriteGlobals (QFile *f)
770 for (i=0 ; i<progs->numglobaldefs ; i++)
772 def = &pr_globaldefs[i];
774 if ( !(def->type & DEF_SAVEGLOBAL) )
776 type &= ~DEF_SAVEGLOBAL;
778 if (type != ev_string && type != ev_float && type != ev_entity)
781 name = pr_strings + def->s_name;
782 Qprintf (f,"\"%s\" ", name);
783 Qprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
793 void ED_ParseGlobals (char *data)
795 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
801 data = COM_Parse (data);
802 if (com_token[0] == '}')
805 Host_Error ("ED_ParseEntity: EOF without closing brace");
807 strcpy (keyname, com_token);
810 data = COM_Parse (data);
812 Host_Error ("ED_ParseEntity: EOF without closing brace");
814 if (com_token[0] == '}')
815 Host_Error ("ED_ParseEntity: closing brace without data");
817 key = ED_FindGlobal (keyname);
820 Con_DPrintf ("'%s' is not a global\n", keyname);
824 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
825 Host_Error ("ED_ParseGlobals: parse error");
829 //============================================================================
837 char *ED_NewString (char *string)
842 l = strlen(string) + 1;
843 new = Mem_Alloc(edictstring_mempool, l);
846 for (i=0 ; i< l ; i++)
848 if (string[i] == '\\' && i < l-1)
851 if (string[i] == 'n')
857 *new_p++ = string[i];
868 Can parse either fields or globals
869 returns false if error
872 qboolean ED_ParseEpair (void *base, ddef_t *key, char *s)
881 d = (void *)((int *)base + key->ofs);
883 switch (key->type & ~DEF_SAVEGLOBAL)
886 *(string_t *)d = ED_NewString (s) - pr_strings;
890 *(float *)d = atof (s);
897 for (i=0 ; i<3 ; i++)
899 while (*v && *v != ' ')
902 ((float *)d)[i] = atof (w);
908 *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
912 def = ED_FindField (s);
915 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
916 if (strcmp(s, "sky") && strcmp(s, "fog") && strncmp(s, "fog_", 4) && strcmp(s, "farclip"))
917 Con_DPrintf ("Can't find field %s\n", s);
920 *(int *)d = G_INT(def->ofs);
924 func = ED_FindFunction (s);
927 Con_DPrintf ("Can't find function %s\n", s);
930 *(func_t *)d = func - pr_functions;
943 Parses an edict out of the given string, returning the new position
944 ed should be a properly initialized empty edict.
945 Used for initial level load and for savegames.
948 char *ED_ParseEdict (char *data, edict_t *ent)
959 if (ent != sv.edicts) // hack
960 memset (&ent->v, 0, progs->entityfields * 4);
962 // go through all the dictionary pairs
966 data = COM_Parse (data);
967 if (com_token[0] == '}')
970 Host_Error ("ED_ParseEntity: EOF without closing brace");
972 // anglehack is to allow QuakeEd to write single scalar angles
973 // and allow them to be turned into vectors. (FIXME...)
974 if (!strcmp(com_token, "angle"))
976 strcpy (com_token, "angles");
982 // FIXME: change light to _light to get rid of this hack
983 if (!strcmp(com_token, "light"))
984 strcpy (com_token, "light_lev"); // hack for single light def
986 strcpy (keyname, com_token);
988 // another hack to fix heynames with trailing spaces
990 while (n && keyname[n-1] == ' ')
997 data = COM_Parse (data);
999 Host_Error ("ED_ParseEntity: EOF without closing brace");
1001 if (com_token[0] == '}')
1002 Host_Error ("ED_ParseEntity: closing brace without data");
1006 // keynames with a leading underscore are used for utility comments,
1007 // and are immediately discarded by quake
1008 if (keyname[0] == '_')
1011 key = ED_FindField (keyname);
1014 Con_DPrintf ("'%s' is not a field\n", keyname);
1021 strcpy (temp, com_token);
1022 sprintf (com_token, "0 %s 0", temp);
1025 if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
1026 Host_Error ("ED_ParseEdict: parse error");
1040 The entities are directly placed in the array, rather than allocated with
1041 ED_Alloc, because otherwise an error loading the map would have entity
1042 number references out of order.
1044 Creates a server's entity / program execution context by
1045 parsing textual entity definitions out of an ent file.
1047 Used for both fresh maps and savegame loads. A fresh map would also need
1048 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1051 void ED_LoadFromFile (char *data)
1059 pr_global_struct->time = sv.time;
1064 // parse the opening brace
1065 data = COM_Parse (data);
1068 if (com_token[0] != '{')
1069 Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1075 data = ED_ParseEdict (data, ent);
1077 // remove things from different skill levels or deathmatch
1078 if (deathmatch.integer)
1080 if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1087 else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY ))
1088 || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
1089 || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD )))
1097 // immediately call spawn function
1099 if (!ent->v.classname)
1101 Con_Printf ("No classname for:\n");
1107 // look for the spawn function
1108 func = ED_FindFunction ( pr_strings + ent->v.classname );
1112 if (developer.integer) // don't confuse non-developers with errors
1114 Con_Printf ("No spawn function for:\n");
1121 pr_global_struct->self = EDICT_TO_PROG(ent);
1122 PR_ExecuteProgram (func - pr_functions, "");
1125 Con_DPrintf ("%i entities inhibited\n", inhibit);
1129 typedef struct dpfield_s
1136 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1138 dpfield_t dpfields[] =
1140 {ev_float, "gravity"},
1141 {ev_float, "button3"},
1142 {ev_float, "button4"},
1143 {ev_float, "button5"},
1144 {ev_float, "button6"},
1145 {ev_float, "button7"},
1146 {ev_float, "button8"},
1147 {ev_float, "glow_size"},
1148 {ev_float, "glow_trail"},
1149 {ev_float, "glow_color"},
1150 {ev_float, "items2"},
1151 {ev_float, "scale"},
1152 {ev_float, "alpha"},
1153 {ev_float, "renderamt"},
1154 {ev_float, "rendermode"},
1155 {ev_float, "fullbright"},
1156 {ev_float, "ammo_shells1"},
1157 {ev_float, "ammo_nails1"},
1158 {ev_float, "ammo_lava_nails"},
1159 {ev_float, "ammo_rockets1"},
1160 {ev_float, "ammo_multi_rockets"},
1161 {ev_float, "ammo_cells1"},
1162 {ev_float, "ammo_plasma"},
1163 {ev_float, "idealpitch"},
1164 {ev_float, "pitch_speed"},
1165 {ev_entity, "viewmodelforclient"},
1166 {ev_entity, "nodrawtoclient"},
1167 {ev_entity, "exteriormodeltoclient"},
1168 {ev_entity, "drawonlytoclient"},
1170 {ev_vector, "movement"},
1171 {ev_float, "pmodel"},
1172 {ev_vector, "punchvector"}
1180 void PR_LoadProgs (void)
1184 ddef_t *infielddefs;
1187 // flush the non-C variable lookup cache
1188 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1189 gefvCache[i].field[0] = 0;
1191 Mem_EmptyPool(progs_mempool);
1192 Mem_EmptyPool(edictstring_mempool);
1194 temp = COM_LoadFile ("progs.dat", false);
1196 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1198 progs = (dprograms_t *)Mem_Alloc(progs_mempool, com_filesize);
1200 memcpy(progs, temp, com_filesize);
1203 Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024);
1205 pr_crc = CRC_Block((byte *)progs, com_filesize);
1207 // byte swap the header
1208 for (i=0 ; i<sizeof(*progs)/4 ; i++)
1209 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1211 if (progs->version != PROG_VERSION)
1212 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1213 if (progs->crc != PROGHEADER_CRC)
1214 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1216 pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
1217 pr_strings = (char *)progs + progs->ofs_strings;
1218 pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
1220 // we need to expand the fielddefs list to include all the engine fields,
1221 // so allocate a new place for it
1222 infielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
1223 pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1225 pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
1227 // moved edict_size calculation down below field adding code
1229 pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);
1230 pr_globals = (float *)pr_global_struct;
1232 // byte swap the lumps
1233 for (i=0 ; i<progs->numstatements ; i++)
1235 pr_statements[i].op = LittleShort(pr_statements[i].op);
1236 pr_statements[i].a = LittleShort(pr_statements[i].a);
1237 pr_statements[i].b = LittleShort(pr_statements[i].b);
1238 pr_statements[i].c = LittleShort(pr_statements[i].c);
1241 for (i=0 ; i<progs->numfunctions; i++)
1243 pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
1244 pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
1245 pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
1246 pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
1247 pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
1248 pr_functions[i].locals = LittleLong (pr_functions[i].locals);
1251 for (i=0 ; i<progs->numglobaldefs ; i++)
1253 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1254 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1255 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1258 // copy the progs fields to the new fields list
1259 for (i = 0;i < progs->numfielddefs;i++)
1261 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1262 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1263 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1264 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1265 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1268 // append the darkplaces fields
1269 for (i = 0;i < DPFIELDS;i++)
1271 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1272 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1273 pr_fielddefs[progs->numfielddefs].s_name = dpfields[i].string - pr_strings;
1274 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1275 progs->entityfields += 3;
1277 progs->entityfields++;
1278 progs->numfielddefs++;
1281 for (i=0 ; i<progs->numglobals ; i++)
1282 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1284 // moved edict_size calculation down here, below field adding code
1285 pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
1287 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1289 // LordHavoc: bounds check anything static
1290 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1296 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1297 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1300 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1301 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1303 // global global global
1338 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1339 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1341 // global none global
1347 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1348 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1364 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1365 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1379 if ((unsigned short) st->a >= progs->numglobals)
1380 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1383 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1388 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1392 void PR_Fields_f (void)
1397 Con_Printf("no progs loaded\n");
1400 for (i = 0;i < progs->numfielddefs;i++)
1401 Con_Printf("%s\n", (pr_strings + pr_fielddefs[i].s_name));
1402 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);
1405 void PR_Globals_f (void)
1410 Con_Printf("no progs loaded\n");
1413 for (i = 0;i < progs->numglobaldefs;i++)
1414 Con_Printf("%s\n", (pr_strings + pr_globaldefs[i].s_name));
1415 Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1425 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1426 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1427 Cmd_AddCommand ("edictcount", ED_Count);
1428 Cmd_AddCommand ("profile", PR_Profile_f);
1429 Cmd_AddCommand ("pr_fields", PR_Fields_f);
1430 Cmd_AddCommand ("pr_globals", PR_Globals_f);
1431 Cvar_RegisterVariable (&pr_checkextension);
1432 Cvar_RegisterVariable (&nomonsters);
1433 Cvar_RegisterVariable (&gamecfg);
1434 Cvar_RegisterVariable (&scratch1);
1435 Cvar_RegisterVariable (&scratch2);
1436 Cvar_RegisterVariable (&scratch3);
1437 Cvar_RegisterVariable (&scratch4);
1438 Cvar_RegisterVariable (&savedgamecfg);
1439 Cvar_RegisterVariable (&saved1);
1440 Cvar_RegisterVariable (&saved2);
1441 Cvar_RegisterVariable (&saved3);
1442 Cvar_RegisterVariable (&saved4);
1443 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1444 Cvar_RegisterVariable (&decors);
1445 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1446 if (gamemode == GAME_NEHAHRA)
1448 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1449 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1450 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1451 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1452 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1453 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1454 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1455 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1456 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1457 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1459 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1460 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1461 Cvar_RegisterVariable (&pr_boundscheck);
1463 progs_mempool = Mem_AllocPool("progs.dat");
1464 edictstring_mempool = Mem_AllocPool("edict strings");
1467 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1468 edict_t *EDICT_NUM_ERROR(int n)
1470 Host_Error ("EDICT_NUM: bad number %i", n);
1474 edict_t *EDICT_NUM(int n)
1476 if (n < 0 || n >= sv.max_edicts)
1477 Sys_Error ("EDICT_NUM: bad number %i", n);
1478 return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size);
1482 int NUM_FOR_EDICT(edict_t *e)
1486 b = (byte *)e - (byte *)sv.edicts;
1487 b = b / pr_edict_size;
1489 if (b < 0 || b >= sv.num_edicts)
1490 Host_Error ("NUM_FOR_EDICT: bad pointer");
1494 int NoCrash_NUM_FOR_EDICT(edict_t *e)
1498 b = (byte *)e - (byte *)sv.edicts;
1499 b = b / pr_edict_size;