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, const 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 (const char *name);
83 dfunction_t *ED_FindFunction (const 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(const 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 (const 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 (const 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 (const char *name)
343 for (i=0 ; i<progs->numfunctions ; i++)
345 func = &pr_functions[i];
346 if (!strcmp(pr_strings + func->s_name,name) )
357 Returns a string describing *data in a type specific manner
360 int NoCrash_NUM_FOR_EDICT(edict_t *e);
361 char *PR_ValueString (etype_t type, eval_t *val)
363 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
368 type &= ~DEF_SAVEGLOBAL;
373 sprintf (line, "%s", pr_strings + val->string);
376 n = NoCrash_NUM_FOR_EDICT(PROG_TO_EDICT(val->edict));
377 if (n < 0 || n >= MAX_EDICTS)
378 sprintf (line, "entity %i (invalid!)", n);
380 sprintf (line, "entity %i", n);
383 f = pr_functions + val->function;
384 sprintf (line, "%s()", pr_strings + f->s_name);
387 def = ED_FieldAtOfs ( val->_int );
388 sprintf (line, ".%s", pr_strings + def->s_name);
391 sprintf (line, "void");
394 // LordHavoc: changed from %5.1f to %10.4f
395 sprintf (line, "%10.4f", val->_float);
398 // LordHavoc: changed from %5.1f to %10.4f
399 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
402 sprintf (line, "pointer");
405 sprintf (line, "bad type %i", type);
416 Returns a string describing *data in a type specific manner
417 Easier to parse than PR_ValueString
420 char *PR_UglyValueString (etype_t type, eval_t *val)
422 static char line[4096];
428 type &= ~DEF_SAVEGLOBAL;
433 sprintf (line, "%s", pr_strings + val->string);
436 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
439 f = pr_functions + val->function;
440 sprintf (line, "%s", pr_strings + f->s_name);
443 def = ED_FieldAtOfs ( val->_int );
444 // LordHavoc: parse the string a bit to turn special characters
445 // (like newline, specifically) into escape codes,
446 // this fixes saving games from various mods
447 //sprintf (line, "%s", pr_strings + def->s_name);
448 s = pr_strings + def->s_name;
449 for (i = 0;i < 4095 && *s;)
468 sprintf (line, "void");
471 sprintf (line, "%f", val->_float);
474 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
477 sprintf (line, "bad type %i", type);
488 Returns a string with a description and the contents of a global,
489 padded to 20 field width
492 char *PR_GlobalString (int ofs)
498 static char line[128];
500 val = (void *)&pr_globals[ofs];
501 def = ED_GlobalAtOfs(ofs);
503 sprintf (line,"%i(?)", ofs);
506 s = PR_ValueString (def->type, val);
507 sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s);
518 char *PR_GlobalStringNoContents (int ofs)
522 static char line[128];
524 def = ED_GlobalAtOfs(ofs);
526 sprintf (line,"%i(?)", ofs);
528 sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name);
546 // LordHavoc: optimized this to print out much more quickly (tempstring)
547 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
548 void ED_Print (edict_t *ed)
556 char tempstring[8192], tempstring2[260]; // temporary string buffers
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 if (strlen(name) > 256)
586 strncpy(tempstring2, name, 256);
587 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
588 tempstring2[259] = 0;
591 strcat(tempstring, name);
592 for (l = strlen(name);l < 14;l++)
593 strcat(tempstring, " ");
594 strcat(tempstring, " ");
596 name = PR_ValueString(d->type, (eval_t *)v);
597 if (strlen(name) > 256)
599 strncpy(tempstring2, name, 256);
600 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
601 tempstring2[259] = 0;
604 strcat(tempstring, name);
605 strcat(tempstring, "\n");
606 if (strlen(tempstring) >= 4096)
608 Con_Printf("%s", tempstring);
613 Con_Printf("%s", tempstring);
623 void ED_Write (QFile *f, edict_t *ed)
639 for (i=1 ; i<progs->numfielddefs ; i++)
641 d = &pr_fielddefs[i];
642 name = pr_strings + d->s_name;
643 if (name[strlen(name)-2] == '_')
644 continue; // skip _x, _y, _z vars
646 v = (int *)((char *)&ed->v + d->ofs*4);
648 // if the value is still all 0, skip the field
649 type = d->type & ~DEF_SAVEGLOBAL;
650 for (j=0 ; j<type_size[type] ; j++)
653 if (j == type_size[type])
656 Qprintf (f,"\"%s\" ",name);
657 Qprintf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
663 void ED_PrintNum (int ent)
665 ED_Print (EDICT_NUM(ent));
672 For debugging, prints all the entities in the current server
675 void ED_PrintEdicts (void)
679 Con_Printf ("%i entities\n", sv.num_edicts);
680 for (i=0 ; i<sv.num_edicts ; i++)
688 For debugging, prints a single edict
691 void ED_PrintEdict_f (void)
695 i = atoi (Cmd_Argv(1));
696 if (i >= sv.num_edicts)
698 Con_Printf("Bad edict number\n");
715 int active, models, solid, step;
717 active = models = solid = step = 0;
718 for (i=0 ; i<sv.num_edicts ; i++)
728 if (ent->v.movetype == MOVETYPE_STEP)
732 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
733 Con_Printf ("active :%3i\n", active);
734 Con_Printf ("view :%3i\n", models);
735 Con_Printf ("touch :%3i\n", solid);
736 Con_Printf ("step :%3i\n", step);
741 ==============================================================================
745 FIXME: need to tag constants, doesn't really work
746 ==============================================================================
754 void ED_WriteGlobals (QFile *f)
762 for (i=0 ; i<progs->numglobaldefs ; i++)
764 def = &pr_globaldefs[i];
766 if ( !(def->type & DEF_SAVEGLOBAL) )
768 type &= ~DEF_SAVEGLOBAL;
770 if (type != ev_string && type != ev_float && type != ev_entity)
773 name = pr_strings + def->s_name;
774 Qprintf (f,"\"%s\" ", name);
775 Qprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
785 void ED_ParseGlobals (const char *data)
787 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
793 if (!COM_ParseToken (&data))
794 Host_Error ("ED_ParseEntity: EOF without closing brace");
795 if (com_token[0] == '}')
798 strcpy (keyname, com_token);
801 if (!COM_ParseToken (&data))
802 Host_Error ("ED_ParseEntity: EOF without closing brace");
804 if (com_token[0] == '}')
805 Host_Error ("ED_ParseEntity: closing brace without data");
807 key = ED_FindGlobal (keyname);
810 Con_DPrintf ("'%s' is not a global\n", keyname);
814 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
815 Host_Error ("ED_ParseGlobals: parse error");
819 //============================================================================
827 char *ED_NewString (const char *string)
832 l = strlen(string) + 1;
833 new = Mem_Alloc(edictstring_mempool, l);
836 for (i=0 ; i< l ; i++)
838 if (string[i] == '\\' && i < l-1)
841 if (string[i] == 'n')
847 *new_p++ = string[i];
858 Can parse either fields or globals
859 returns false if error
862 qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s)
871 d = (void *)((int *)base + key->ofs);
873 switch (key->type & ~DEF_SAVEGLOBAL)
876 *(string_t *)d = ED_NewString (s) - pr_strings;
880 *(float *)d = atof (s);
887 for (i=0 ; i<3 ; i++)
889 while (*v && *v != ' ')
892 ((float *)d)[i] = atof (w);
898 *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
902 def = ED_FindField (s);
905 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
906 if (strcmp(s, "sky") && strcmp(s, "fog") && strncmp(s, "fog_", 4) && strcmp(s, "farclip"))
907 Con_DPrintf ("Can't find field %s\n", s);
910 *(int *)d = G_INT(def->ofs);
914 func = ED_FindFunction (s);
917 Con_DPrintf ("Can't find function %s\n", s);
920 *(func_t *)d = func - pr_functions;
933 Parses an edict out of the given string, returning the new position
934 ed should be a properly initialized empty edict.
935 Used for initial level load and for savegames.
938 const char *ED_ParseEdict (const char *data, edict_t *ent)
949 if (ent != sv.edicts) // hack
950 memset (&ent->v, 0, progs->entityfields * 4);
952 // go through all the dictionary pairs
956 if (!COM_ParseToken (&data))
957 Host_Error ("ED_ParseEntity: EOF without closing brace");
958 if (com_token[0] == '}')
961 // anglehack is to allow QuakeEd to write single scalar angles
962 // and allow them to be turned into vectors. (FIXME...)
963 if (!strcmp(com_token, "angle"))
965 strcpy (com_token, "angles");
971 // FIXME: change light to _light to get rid of this hack
972 if (!strcmp(com_token, "light"))
973 strcpy (com_token, "light_lev"); // hack for single light def
975 strcpy (keyname, com_token);
977 // another hack to fix heynames with trailing spaces
979 while (n && keyname[n-1] == ' ')
986 if (!COM_ParseToken (&data))
987 Host_Error ("ED_ParseEntity: EOF without closing brace");
989 if (com_token[0] == '}')
990 Host_Error ("ED_ParseEntity: closing brace without data");
994 // keynames with a leading underscore are used for utility comments,
995 // and are immediately discarded by quake
996 if (keyname[0] == '_')
999 key = ED_FindField (keyname);
1002 Con_DPrintf ("'%s' is not a field\n", keyname);
1009 strcpy (temp, com_token);
1010 sprintf (com_token, "0 %s 0", temp);
1013 if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
1014 Host_Error ("ED_ParseEdict: parse error");
1028 The entities are directly placed in the array, rather than allocated with
1029 ED_Alloc, because otherwise an error loading the map would have entity
1030 number references out of order.
1032 Creates a server's entity / program execution context by
1033 parsing textual entity definitions out of an ent file.
1035 Used for both fresh maps and savegame loads. A fresh map would also need
1036 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1039 void ED_LoadFromFile (const char *data)
1047 pr_global_struct->time = sv.time;
1052 // parse the opening brace
1053 if (!COM_ParseToken (&data))
1055 if (com_token[0] != '{')
1056 Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1062 data = ED_ParseEdict (data, ent);
1064 // remove things from different skill levels or deathmatch
1065 if (deathmatch.integer)
1067 if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1074 else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY ))
1075 || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
1076 || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD )))
1084 // immediately call spawn function
1086 if (!ent->v.classname)
1088 Con_Printf ("No classname for:\n");
1094 // look for the spawn function
1095 func = ED_FindFunction ( pr_strings + ent->v.classname );
1099 if (developer.integer) // don't confuse non-developers with errors
1101 Con_Printf ("No spawn function for:\n");
1108 pr_global_struct->self = EDICT_TO_PROG(ent);
1109 PR_ExecuteProgram (func - pr_functions, "");
1112 Con_DPrintf ("%i entities inhibited\n", inhibit);
1116 typedef struct dpfield_s
1123 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1125 dpfield_t dpfields[] =
1127 {ev_float, "gravity"},
1128 {ev_float, "button3"},
1129 {ev_float, "button4"},
1130 {ev_float, "button5"},
1131 {ev_float, "button6"},
1132 {ev_float, "button7"},
1133 {ev_float, "button8"},
1134 {ev_float, "glow_size"},
1135 {ev_float, "glow_trail"},
1136 {ev_float, "glow_color"},
1137 {ev_float, "items2"},
1138 {ev_float, "scale"},
1139 {ev_float, "alpha"},
1140 {ev_float, "renderamt"},
1141 {ev_float, "rendermode"},
1142 {ev_float, "fullbright"},
1143 {ev_float, "ammo_shells1"},
1144 {ev_float, "ammo_nails1"},
1145 {ev_float, "ammo_lava_nails"},
1146 {ev_float, "ammo_rockets1"},
1147 {ev_float, "ammo_multi_rockets"},
1148 {ev_float, "ammo_cells1"},
1149 {ev_float, "ammo_plasma"},
1150 {ev_float, "idealpitch"},
1151 {ev_float, "pitch_speed"},
1152 {ev_entity, "viewmodelforclient"},
1153 {ev_entity, "nodrawtoclient"},
1154 {ev_entity, "exteriormodeltoclient"},
1155 {ev_entity, "drawonlytoclient"},
1157 {ev_vector, "movement"},
1158 {ev_float, "pmodel"},
1159 {ev_vector, "punchvector"}
1167 void PR_LoadProgs (void)
1171 ddef_t *infielddefs;
1174 // flush the non-C variable lookup cache
1175 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1176 gefvCache[i].field[0] = 0;
1178 Mem_EmptyPool(progs_mempool);
1179 Mem_EmptyPool(edictstring_mempool);
1181 temp = COM_LoadFile ("progs.dat", false);
1183 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1185 progs = (dprograms_t *)Mem_Alloc(progs_mempool, com_filesize);
1187 memcpy(progs, temp, com_filesize);
1190 Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024);
1192 pr_crc = CRC_Block((qbyte *)progs, com_filesize);
1194 // byte swap the header
1195 for (i=0 ; i<sizeof(*progs)/4 ; i++)
1196 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1198 if (progs->version != PROG_VERSION)
1199 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1200 if (progs->crc != PROGHEADER_CRC)
1201 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1203 pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1204 pr_strings = (char *)progs + progs->ofs_strings;
1205 pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1207 // we need to expand the fielddefs list to include all the engine fields,
1208 // so allocate a new place for it
1209 infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1210 pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1212 pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1214 // moved edict_size calculation down below field adding code
1216 pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1217 pr_globals = (float *)pr_global_struct;
1219 // byte swap the lumps
1220 for (i=0 ; i<progs->numstatements ; i++)
1222 pr_statements[i].op = LittleShort(pr_statements[i].op);
1223 pr_statements[i].a = LittleShort(pr_statements[i].a);
1224 pr_statements[i].b = LittleShort(pr_statements[i].b);
1225 pr_statements[i].c = LittleShort(pr_statements[i].c);
1228 for (i=0 ; i<progs->numfunctions; i++)
1230 pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
1231 pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
1232 pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
1233 pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
1234 pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
1235 pr_functions[i].locals = LittleLong (pr_functions[i].locals);
1238 for (i=0 ; i<progs->numglobaldefs ; i++)
1240 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1241 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1242 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1245 // copy the progs fields to the new fields list
1246 for (i = 0;i < progs->numfielddefs;i++)
1248 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1249 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1250 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1251 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1252 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1255 // append the darkplaces fields
1256 for (i = 0;i < DPFIELDS;i++)
1258 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1259 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1260 pr_fielddefs[progs->numfielddefs].s_name = dpfields[i].string - pr_strings;
1261 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1262 progs->entityfields += 3;
1264 progs->entityfields++;
1265 progs->numfielddefs++;
1268 for (i=0 ; i<progs->numglobals ; i++)
1269 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1271 // moved edict_size calculation down here, below field adding code
1272 pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
1274 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1276 // LordHavoc: bounds check anything static
1277 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1283 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1284 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1287 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1288 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1290 // global global global
1325 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1326 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1328 // global none global
1334 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1335 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1351 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1352 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1366 if ((unsigned short) st->a >= progs->numglobals)
1367 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1370 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1375 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1376 PR_Execute_ProgsLoaded();
1380 void PR_Fields_f (void)
1382 int i, j, ednum, used, usedamount;
1384 char tempstring[5000], tempstring2[260], *name;
1390 Con_Printf("no progs loaded\n");
1393 counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1394 for (ednum = 0;ednum < MAX_EDICTS;ednum++)
1396 ed = EDICT_NUM(ednum);
1399 for (i = 1;i < progs->numfielddefs;i++)
1401 d = &pr_fielddefs[i];
1402 name = pr_strings + d->s_name;
1403 if (name[strlen(name)-2] == '_')
1404 continue; // skip _x, _y, _z vars
1405 v = (int *)((char *)&ed->v + d->ofs*4);
1406 // if the value is still all 0, skip the field
1407 for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1420 for (i = 0;i < progs->numfielddefs;i++)
1422 d = &pr_fielddefs[i];
1423 name = pr_strings + d->s_name;
1424 if (name[strlen(name)-2] == '_')
1425 continue; // skip _x, _y, _z vars
1426 switch(d->type & ~DEF_SAVEGLOBAL)
1429 strcat(tempstring, "string ");
1432 strcat(tempstring, "entity ");
1435 strcat(tempstring, "function ");
1438 strcat(tempstring, "field ");
1441 strcat(tempstring, "void ");
1444 strcat(tempstring, "float ");
1447 strcat(tempstring, "vector ");
1450 strcat(tempstring, "pointer ");
1453 sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1454 strcat(tempstring, tempstring2);
1457 if (strlen(name) > 256)
1459 strncpy(tempstring2, name, 256);
1460 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1461 tempstring2[259] = 0;
1464 strcat(tempstring, name);
1465 for (j = strlen(name);j < 25;j++)
1466 strcat(tempstring, " ");
1467 sprintf(tempstring2, "%5d", counts[i]);
1468 strcat(tempstring, tempstring2);
1469 strcat(tempstring, "\n");
1470 if (strlen(tempstring) >= 4096)
1472 Con_Printf("%s", tempstring);
1478 usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1482 Con_Printf("%i entity fields (%i in use), totalling %i bytes per edict (%i in use), %i edicts, %i bytes total spent on edict fields (%i needed)\n", progs->entityfields, used, progs->entityfields * 4, usedamount * 4, MAX_EDICTS, progs->entityfields * 4 * MAX_EDICTS, usedamount * 4 * MAX_EDICTS);
1485 void PR_Globals_f (void)
1490 Con_Printf("no progs loaded\n");
1493 for (i = 0;i < progs->numglobaldefs;i++)
1494 Con_Printf("%s\n", (pr_strings + pr_globaldefs[i].s_name));
1495 Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1505 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1506 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1507 Cmd_AddCommand ("edictcount", ED_Count);
1508 Cmd_AddCommand ("profile", PR_Profile_f);
1509 Cmd_AddCommand ("pr_fields", PR_Fields_f);
1510 Cmd_AddCommand ("pr_globals", PR_Globals_f);
1511 Cvar_RegisterVariable (&pr_checkextension);
1512 Cvar_RegisterVariable (&nomonsters);
1513 Cvar_RegisterVariable (&gamecfg);
1514 Cvar_RegisterVariable (&scratch1);
1515 Cvar_RegisterVariable (&scratch2);
1516 Cvar_RegisterVariable (&scratch3);
1517 Cvar_RegisterVariable (&scratch4);
1518 Cvar_RegisterVariable (&savedgamecfg);
1519 Cvar_RegisterVariable (&saved1);
1520 Cvar_RegisterVariable (&saved2);
1521 Cvar_RegisterVariable (&saved3);
1522 Cvar_RegisterVariable (&saved4);
1523 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1524 Cvar_RegisterVariable (&decors);
1525 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1526 if (gamemode == GAME_NEHAHRA)
1528 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1529 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1530 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1531 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1532 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1533 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1534 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1535 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1536 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1537 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1539 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1540 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1541 Cvar_RegisterVariable (&pr_boundscheck);
1543 progs_mempool = Mem_AllocPool("progs.dat");
1544 edictstring_mempool = Mem_AllocPool("edict strings");
1547 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1548 edict_t *EDICT_NUM_ERROR(int n)
1550 Host_Error ("EDICT_NUM: bad number %i", n);
1554 int NUM_FOR_EDICT(edict_t *e)
1558 b = (qbyte *)e - (qbyte *)sv.edicts;
1559 b = b / pr_edict_size;
1561 if (b < 0 || b >= sv.num_edicts)
1562 Host_Error ("NUM_FOR_EDICT: bad pointer");
1566 int NoCrash_NUM_FOR_EDICT(edict_t *e)
1570 b = (qbyte *)e - (qbyte *)sv.edicts;
1571 b = b / pr_edict_size;