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 mfunction_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"};
71 // LordHavoc: prints every opcode as it executes - warning: this is significant spew
72 cvar_t pr_traceqc = {0, "pr_traceqc", "0"};
74 #define MAX_FIELD_LEN 64
75 #define GEFV_CACHESIZE 2
79 char field[MAX_FIELD_LEN];
82 static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};
84 ddef_t *ED_FindField (const char *name);
85 mfunction_t *ED_FindFunction (const char *name);
87 // LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue... these are defined as externs in progs.h
101 int eval_renderamt; // HalfLife support
102 int eval_rendermode; // HalfLife support
104 int eval_ammo_shells1;
105 int eval_ammo_nails1;
106 int eval_ammo_lava_nails;
107 int eval_ammo_rockets1;
108 int eval_ammo_multi_rockets;
109 int eval_ammo_cells1;
110 int eval_ammo_plasma;
112 int eval_pitch_speed;
113 int eval_viewmodelforclient;
114 int eval_nodrawtoclient;
115 int eval_exteriormodeltoclient;
116 int eval_drawonlytoclient;
120 int eval_punchvector;
123 mfunction_t *SV_PlayerPhysicsQC;
124 mfunction_t *EndFrameQC;
126 int FindFieldOffset(const char *field)
129 d = ED_FindField(field);
135 void FindEdictFieldOffsets(void)
137 eval_gravity = FindFieldOffset("gravity");
138 eval_button3 = FindFieldOffset("button3");
139 eval_button4 = FindFieldOffset("button4");
140 eval_button5 = FindFieldOffset("button5");
141 eval_button6 = FindFieldOffset("button6");
142 eval_button7 = FindFieldOffset("button7");
143 eval_button8 = FindFieldOffset("button8");
144 eval_glow_size = FindFieldOffset("glow_size");
145 eval_glow_trail = FindFieldOffset("glow_trail");
146 eval_glow_color = FindFieldOffset("glow_color");
147 eval_items2 = FindFieldOffset("items2");
148 eval_scale = FindFieldOffset("scale");
149 eval_alpha = FindFieldOffset("alpha");
150 eval_renderamt = FindFieldOffset("renderamt"); // HalfLife support
151 eval_rendermode = FindFieldOffset("rendermode"); // HalfLife support
152 eval_fullbright = FindFieldOffset("fullbright");
153 eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
154 eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
155 eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
156 eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
157 eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
158 eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
159 eval_ammo_plasma = FindFieldOffset("ammo_plasma");
160 eval_idealpitch = FindFieldOffset("idealpitch");
161 eval_pitch_speed = FindFieldOffset("pitch_speed");
162 eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
163 eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
164 eval_exteriormodeltoclient = FindFieldOffset("exteriormodeltoclient");
165 eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
166 eval_ping = FindFieldOffset("ping");
167 eval_movement = FindFieldOffset("movement");
168 eval_pmodel = FindFieldOffset("pmodel");
169 eval_punchvector = FindFieldOffset("punchvector");
170 eval_viewzoom = FindFieldOffset("viewzoom");
172 // LordHavoc: allowing QuakeC to override the player movement code
173 SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
174 // LordHavoc: support for endframe
175 EndFrameQC = ED_FindFunction ("EndFrame");
182 Sets everything to NULL
185 void ED_ClearEdict (edict_t *e)
187 memset (e->v, 0, progs->entityfields * 4);
195 Either finds a free edict, or allocates a new one.
196 Try to avoid reusing an entity that was recently freed, because it
197 can cause the client to think the entity morphed into something else
198 instead of being removed and recreated, which can cause interpolated
199 angles and bad trails.
202 edict_t *ED_Alloc (void)
207 for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
210 // the first couple seconds of server time can involve a lot of
211 // freeing and allocating, so relax the replacement policy
212 if (e->free && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) )
220 Host_Error ("ED_Alloc: no free edicts");
233 Marks the edict as free
234 FIXME: walk all entities and NULL out references to this entity
237 void ED_Free (edict_t *ed)
239 SV_UnlinkEdict (ed); // unlink from world bsp
243 ed->v->takedamage = 0;
244 ed->v->modelindex = 0;
248 VectorClear(ed->v->origin);
249 VectorClear(ed->v->angles);
250 ed->v->nextthink = -1;
253 ed->freetime = sv.time;
256 //===========================================================================
263 ddef_t *ED_GlobalAtOfs (int ofs)
268 for (i=0 ; i<progs->numglobaldefs ; i++)
270 def = &pr_globaldefs[i];
282 ddef_t *ED_FieldAtOfs (int ofs)
287 for (i=0 ; i<progs->numfielddefs ; i++)
289 def = &pr_fielddefs[i];
301 ddef_t *ED_FindField (const char *name)
306 for (i=0 ; i<progs->numfielddefs ; i++)
308 def = &pr_fielddefs[i];
309 if (!strcmp(PR_GetString(def->s_name), name))
320 ddef_t *ED_FindGlobal (const char *name)
325 for (i=0 ; i<progs->numglobaldefs ; i++)
327 def = &pr_globaldefs[i];
328 if (!strcmp(PR_GetString(def->s_name), name))
340 mfunction_t *ED_FindFunction (const char *name)
345 for (i=0 ; i<progs->numfunctions ; i++)
347 func = &pr_functions[i];
348 if (!strcmp(PR_GetString(func->s_name), name))
359 Returns a string describing *data in a type specific manner
362 int NoCrash_NUM_FOR_EDICT(edict_t *e);
363 char *PR_ValueString (etype_t type, eval_t *val)
365 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
370 type &= ~DEF_SAVEGLOBAL;
375 sprintf (line, "%s", PR_GetString(val->string));
378 n = NoCrash_NUM_FOR_EDICT(PROG_TO_EDICT(val->edict));
379 if (n < 0 || n >= MAX_EDICTS)
380 sprintf (line, "entity %i (invalid!)", n);
382 sprintf (line, "entity %i", n);
385 f = pr_functions + val->function;
386 sprintf (line, "%s()", PR_GetString(f->s_name));
389 def = ED_FieldAtOfs ( val->_int );
390 sprintf (line, ".%s", PR_GetString(def->s_name));
393 sprintf (line, "void");
396 // LordHavoc: changed from %5.1f to %10.4f
397 sprintf (line, "%10.4f", val->_float);
400 // LordHavoc: changed from %5.1f to %10.4f
401 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
404 sprintf (line, "pointer");
407 sprintf (line, "bad type %i", type);
418 Returns a string describing *data in a type specific manner
419 Easier to parse than PR_ValueString
422 char *PR_UglyValueString (etype_t type, eval_t *val)
424 static char line[4096];
430 type &= ~DEF_SAVEGLOBAL;
435 sprintf (line, "%s", PR_GetString(val->string));
438 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
441 f = pr_functions + val->function;
442 sprintf (line, "%s", PR_GetString(f->s_name));
445 def = ED_FieldAtOfs ( val->_int );
446 // LordHavoc: parse the string a bit to turn special characters
447 // (like newline, specifically) into escape codes,
448 // this fixes saving games from various mods
449 //sprintf (line, "%s", PR_GetString(def->s_name));
450 s = PR_GetString(def->s_name);
451 for (i = 0;i < 4095 && *s;)
470 sprintf (line, "void");
473 sprintf (line, "%f", val->_float);
476 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
479 sprintf (line, "bad type %i", type);
490 Returns a string with a description and the contents of a global,
491 padded to 20 field width
494 char *PR_GlobalString (int ofs)
500 static char line[128];
502 val = (void *)&pr_globals[ofs];
503 def = ED_GlobalAtOfs(ofs);
505 sprintf (line,"%i(?)", ofs);
508 s = PR_ValueString (def->type, val);
509 sprintf (line,"%i(%s)%s", ofs, PR_GetString(def->s_name), s);
520 char *PR_GlobalStringNoContents (int ofs)
524 static char line[128];
526 def = ED_GlobalAtOfs(ofs);
528 sprintf (line,"%i(?)", ofs);
530 sprintf (line,"%i(%s)", ofs, PR_GetString(def->s_name));
548 // LordHavoc: optimized this to print out much more quickly (tempstring)
549 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
550 void ED_Print (edict_t *ed)
558 char tempstring[8192], tempstring2[260]; // temporary string buffers
562 Con_Printf ("FREE\n");
567 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
568 for (i=1 ; i<progs->numfielddefs ; i++)
570 d = &pr_fielddefs[i];
571 name = PR_GetString(d->s_name);
572 if (name[strlen(name)-2] == '_')
573 continue; // skip _x, _y, _z vars
575 v = (int *)((char *)ed->v + d->ofs*4);
577 // if the value is still all 0, skip the field
578 type = d->type & ~DEF_SAVEGLOBAL;
580 for (j=0 ; j<type_size[type] ; j++)
583 if (j == type_size[type])
586 if (strlen(name) > 256)
588 strncpy(tempstring2, name, 256);
589 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
590 tempstring2[259] = 0;
593 strcat(tempstring, name);
594 for (l = strlen(name);l < 14;l++)
595 strcat(tempstring, " ");
596 strcat(tempstring, " ");
598 name = PR_ValueString(d->type, (eval_t *)v);
599 if (strlen(name) > 256)
601 strncpy(tempstring2, name, 256);
602 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
603 tempstring2[259] = 0;
606 strcat(tempstring, name);
607 strcat(tempstring, "\n");
608 if (strlen(tempstring) >= 4096)
610 Con_Printf("%s", tempstring);
615 Con_Printf("%s", tempstring);
625 void ED_Write (qfile_t *f, edict_t *ed)
633 FS_Printf (f, "{\n");
637 FS_Printf (f, "}\n");
641 for (i=1 ; i<progs->numfielddefs ; i++)
643 d = &pr_fielddefs[i];
644 name = PR_GetString(d->s_name);
645 if (name[strlen(name)-2] == '_')
646 continue; // skip _x, _y, _z vars
648 v = (int *)((char *)ed->v + d->ofs*4);
650 // if the value is still all 0, skip the field
651 type = d->type & ~DEF_SAVEGLOBAL;
652 for (j=0 ; j<type_size[type] ; j++)
655 if (j == type_size[type])
658 FS_Printf (f,"\"%s\" ",name);
659 FS_Printf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
662 FS_Printf (f, "}\n");
665 void ED_PrintNum (int ent)
667 ED_Print (EDICT_NUM(ent));
674 For debugging, prints all the entities in the current server
677 void ED_PrintEdicts (void)
681 Con_Printf ("%i entities\n", sv.num_edicts);
682 for (i=0 ; i<sv.num_edicts ; i++)
690 For debugging, prints a single edict
693 void ED_PrintEdict_f (void)
697 i = atoi (Cmd_Argv(1));
698 if (i >= sv.num_edicts)
700 Con_Printf("Bad edict number\n");
717 int active, models, solid, step;
719 active = models = solid = step = 0;
720 for (i=0 ; i<sv.num_edicts ; i++)
730 if (ent->v->movetype == MOVETYPE_STEP)
734 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
735 Con_Printf ("active :%3i\n", active);
736 Con_Printf ("view :%3i\n", models);
737 Con_Printf ("touch :%3i\n", solid);
738 Con_Printf ("step :%3i\n", step);
743 ==============================================================================
747 FIXME: need to tag constants, doesn't really work
748 ==============================================================================
756 void ED_WriteGlobals (qfile_t *f)
764 for (i=0 ; i<progs->numglobaldefs ; i++)
766 def = &pr_globaldefs[i];
768 if ( !(def->type & DEF_SAVEGLOBAL) )
770 type &= ~DEF_SAVEGLOBAL;
772 if (type != ev_string && type != ev_float && type != ev_entity)
775 name = PR_GetString(def->s_name);
776 FS_Printf (f,"\"%s\" ", name);
777 FS_Printf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
787 void ED_ParseGlobals (const char *data)
789 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
795 if (!COM_ParseToken (&data))
796 Host_Error ("ED_ParseEntity: EOF without closing brace");
797 if (com_token[0] == '}')
800 strcpy (keyname, com_token);
803 if (!COM_ParseToken (&data))
804 Host_Error ("ED_ParseEntity: EOF without closing brace");
806 if (com_token[0] == '}')
807 Host_Error ("ED_ParseEntity: closing brace without data");
809 key = ED_FindGlobal (keyname);
812 Con_DPrintf ("'%s' is not a global\n", keyname);
816 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
817 Host_Error ("ED_ParseGlobals: parse error");
821 //============================================================================
829 char *ED_NewString (const char *string)
834 l = strlen(string) + 1;
835 new = Mem_Alloc(edictstring_mempool, l);
838 for (i=0 ; i< l ; i++)
840 if (string[i] == '\\' && i < l-1)
843 if (string[i] == 'n')
849 *new_p++ = string[i];
860 Can parse either fields or globals
861 returns false if error
864 qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s)
873 d = (void *)((int *)base + key->ofs);
875 switch (key->type & ~DEF_SAVEGLOBAL)
878 *(string_t *)d = PR_SetString(ED_NewString(s));
882 *(float *)d = atof (s);
889 for (i=0 ; i<3 ; i++)
891 while (*v && *v != ' ')
894 ((float *)d)[i] = atof (w);
900 *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
904 def = ED_FindField (s);
907 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
908 if (strcmp(s, "sky") && strcmp(s, "fog") && strncmp(s, "fog_", 4) && strcmp(s, "farclip"))
909 Con_DPrintf ("Can't find field %s\n", s);
912 *(int *)d = G_INT(def->ofs);
916 func = ED_FindFunction (s);
919 Con_DPrintf ("Can't find function %s\n", s);
922 *(func_t *)d = func - pr_functions;
935 Parses an edict out of the given string, returning the new position
936 ed should be a properly initialized empty edict.
937 Used for initial level load and for savegames.
940 const char *ED_ParseEdict (const char *data, edict_t *ent)
951 if (ent != sv.edicts) // hack
952 memset (ent->v, 0, progs->entityfields * 4);
954 // go through all the dictionary pairs
958 if (!COM_ParseToken (&data))
959 Host_Error ("ED_ParseEntity: EOF without closing brace");
960 if (com_token[0] == '}')
963 // anglehack is to allow QuakeEd to write single scalar angles
964 // and allow them to be turned into vectors. (FIXME...)
965 if (!strcmp(com_token, "angle"))
967 strcpy (com_token, "angles");
973 // FIXME: change light to _light to get rid of this hack
974 if (!strcmp(com_token, "light"))
975 strcpy (com_token, "light_lev"); // hack for single light def
977 strcpy (keyname, com_token);
979 // another hack to fix heynames with trailing spaces
981 while (n && keyname[n-1] == ' ')
988 if (!COM_ParseToken (&data))
989 Host_Error ("ED_ParseEntity: EOF without closing brace");
991 if (com_token[0] == '}')
992 Host_Error ("ED_ParseEntity: closing brace without data");
996 // keynames with a leading underscore are used for utility comments,
997 // and are immediately discarded by quake
998 if (keyname[0] == '_')
1001 key = ED_FindField (keyname);
1004 Con_DPrintf ("'%s' is not a field\n", keyname);
1011 strcpy (temp, com_token);
1012 sprintf (com_token, "0 %s 0", temp);
1015 if (!ED_ParseEpair ((void *)ent->v, key, com_token))
1016 Host_Error ("ED_ParseEdict: parse error");
1030 The entities are directly placed in the array, rather than allocated with
1031 ED_Alloc, because otherwise an error loading the map would have entity
1032 number references out of order.
1034 Creates a server's entity / program execution context by
1035 parsing textual entity definitions out of an ent file.
1037 Used for both fresh maps and savegame loads. A fresh map would also need
1038 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1041 void ED_LoadFromFile (const char *data)
1044 int parsed, inhibited, spawned, died;
1052 pr_global_struct->time = sv.time;
1057 // parse the opening brace
1058 if (!COM_ParseToken (&data))
1060 if (com_token[0] != '{')
1061 Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1067 data = ED_ParseEdict (data, ent);
1070 // remove things from different skill levels or deathmatch
1071 if (deathmatch.integer)
1073 if (((int)ent->v->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1080 else if ((current_skill == 0 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_EASY ))
1081 || (current_skill == 1 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_MEDIUM))
1082 || (current_skill >= 2 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_HARD )))
1090 // immediately call spawn function
1092 if (!ent->v->classname)
1094 Con_Printf ("No classname for:\n");
1100 // look for the spawn function
1101 func = ED_FindFunction (PR_GetString(ent->v->classname));
1105 if (developer.integer) // don't confuse non-developers with errors
1107 Con_Printf ("No spawn function for:\n");
1114 pr_global_struct->self = EDICT_TO_PROG(ent);
1115 PR_ExecuteProgram (func - pr_functions, "");
1121 Con_DPrintf ("%i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", parsed, inhibited, spawned, died, spawned - died);
1125 typedef struct dpfield_s
1132 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1134 dpfield_t dpfields[] =
1136 {ev_float, "gravity"},
1137 {ev_float, "button3"},
1138 {ev_float, "button4"},
1139 {ev_float, "button5"},
1140 {ev_float, "button6"},
1141 {ev_float, "button7"},
1142 {ev_float, "button8"},
1143 {ev_float, "glow_size"},
1144 {ev_float, "glow_trail"},
1145 {ev_float, "glow_color"},
1146 {ev_float, "items2"},
1147 {ev_float, "scale"},
1148 {ev_float, "alpha"},
1149 {ev_float, "renderamt"},
1150 {ev_float, "rendermode"},
1151 {ev_float, "fullbright"},
1152 {ev_float, "ammo_shells1"},
1153 {ev_float, "ammo_nails1"},
1154 {ev_float, "ammo_lava_nails"},
1155 {ev_float, "ammo_rockets1"},
1156 {ev_float, "ammo_multi_rockets"},
1157 {ev_float, "ammo_cells1"},
1158 {ev_float, "ammo_plasma"},
1159 {ev_float, "idealpitch"},
1160 {ev_float, "pitch_speed"},
1161 {ev_entity, "viewmodelforclient"},
1162 {ev_entity, "nodrawtoclient"},
1163 {ev_entity, "exteriormodeltoclient"},
1164 {ev_entity, "drawonlytoclient"},
1166 {ev_vector, "movement"},
1167 {ev_float, "pmodel"},
1168 {ev_vector, "punchvector"}
1176 extern void PR_Cmd_Reset (void);
1177 void PR_LoadProgs (void)
1181 ddef_t *infielddefs;
1183 dfunction_t *dfunctions;
1185 // flush the non-C variable lookup cache
1186 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1187 gefvCache[i].field[0] = 0;
1189 Mem_EmptyPool(progs_mempool);
1190 Mem_EmptyPool(edictstring_mempool);
1192 temp = FS_LoadFile ("progs.dat", false);
1194 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1196 progs = (dprograms_t *)Mem_Alloc(progs_mempool, fs_filesize);
1198 memcpy(progs, temp, fs_filesize);
1201 Con_DPrintf ("Programs occupy %iK.\n", fs_filesize/1024);
1203 pr_crc = CRC_Block((qbyte *)progs, fs_filesize);
1205 // byte swap the header
1206 for (i = 0;i < (int) sizeof(*progs) / 4;i++)
1207 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1209 if (progs->version != PROG_VERSION)
1210 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1211 if (progs->crc != PROGHEADER_CRC)
1212 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1214 //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1215 dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1216 pr_strings = (char *)progs + progs->ofs_strings;
1217 pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1219 // we need to expand the fielddefs list to include all the engine fields,
1220 // so allocate a new place for it
1221 infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1222 pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1224 pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1226 // moved edict_size calculation down below field adding code
1228 pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1229 pr_globals = (float *)pr_global_struct;
1231 // byte swap the lumps
1232 for (i=0 ; i<progs->numstatements ; i++)
1234 pr_statements[i].op = LittleShort(pr_statements[i].op);
1235 pr_statements[i].a = LittleShort(pr_statements[i].a);
1236 pr_statements[i].b = LittleShort(pr_statements[i].b);
1237 pr_statements[i].c = LittleShort(pr_statements[i].c);
1240 pr_functions = Mem_Alloc(progs_mempool, sizeof(mfunction_t) * progs->numfunctions);
1241 for (i = 0;i < progs->numfunctions;i++)
1243 pr_functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1244 pr_functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1245 pr_functions[i].s_name = LittleLong (dfunctions[i].s_name);
1246 pr_functions[i].s_file = LittleLong (dfunctions[i].s_file);
1247 pr_functions[i].numparms = LittleLong (dfunctions[i].numparms);
1248 pr_functions[i].locals = LittleLong (dfunctions[i].locals);
1249 memcpy(pr_functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1252 for (i=0 ; i<progs->numglobaldefs ; i++)
1254 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1255 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1256 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1259 // copy the progs fields to the new fields list
1260 for (i = 0;i < progs->numfielddefs;i++)
1262 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1263 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1264 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1265 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1266 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1269 // append the darkplaces fields
1270 for (i = 0;i < (int) DPFIELDS;i++)
1272 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1273 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1274 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1275 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1276 progs->entityfields += 3;
1278 progs->entityfields++;
1279 progs->numfielddefs++;
1282 for (i=0 ; i<progs->numglobals ; i++)
1283 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1285 // moved edict_size calculation down here, below field adding code
1286 // LordHavoc: this no longer includes the edict_t header
1287 pr_edict_size = progs->entityfields * 4;
1288 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1290 // LordHavoc: bounds check anything static
1291 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1297 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1298 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1301 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1302 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1304 // global global global
1339 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1340 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1342 // global none global
1348 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1349 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1365 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1366 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1380 if ((unsigned short) st->a >= progs->numglobals)
1381 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1384 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1389 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1390 PR_Execute_ProgsLoaded();
1395 void PR_Fields_f (void)
1397 int i, j, ednum, used, usedamount;
1399 char tempstring[5000], tempstring2[260], *name;
1405 Con_Printf("no progs loaded\n");
1408 counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1409 for (ednum = 0;ednum < MAX_EDICTS;ednum++)
1411 ed = EDICT_NUM(ednum);
1414 for (i = 1;i < progs->numfielddefs;i++)
1416 d = &pr_fielddefs[i];
1417 name = PR_GetString(d->s_name);
1418 if (name[strlen(name)-2] == '_')
1419 continue; // skip _x, _y, _z vars
1420 v = (int *)((char *)ed->v + d->ofs*4);
1421 // if the value is still all 0, skip the field
1422 for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1435 for (i = 0;i < progs->numfielddefs;i++)
1437 d = &pr_fielddefs[i];
1438 name = PR_GetString(d->s_name);
1439 if (name[strlen(name)-2] == '_')
1440 continue; // skip _x, _y, _z vars
1441 switch(d->type & ~DEF_SAVEGLOBAL)
1444 strcat(tempstring, "string ");
1447 strcat(tempstring, "entity ");
1450 strcat(tempstring, "function ");
1453 strcat(tempstring, "field ");
1456 strcat(tempstring, "void ");
1459 strcat(tempstring, "float ");
1462 strcat(tempstring, "vector ");
1465 strcat(tempstring, "pointer ");
1468 sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1469 strcat(tempstring, tempstring2);
1472 if (strlen(name) > 256)
1474 strncpy(tempstring2, name, 256);
1475 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1476 tempstring2[259] = 0;
1479 strcat(tempstring, name);
1480 for (j = strlen(name);j < 25;j++)
1481 strcat(tempstring, " ");
1482 sprintf(tempstring2, "%5d", counts[i]);
1483 strcat(tempstring, tempstring2);
1484 strcat(tempstring, "\n");
1485 if (strlen(tempstring) >= 4096)
1487 Con_Printf("%s", tempstring);
1493 usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1497 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);
1500 void PR_Globals_f (void)
1505 Con_Printf("no progs loaded\n");
1508 for (i = 0;i < progs->numglobaldefs;i++)
1509 Con_Printf("%s\n", PR_GetString(pr_globaldefs[i].s_name));
1510 Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1518 extern void PR_Cmd_Init(void);
1521 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1522 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1523 Cmd_AddCommand ("edictcount", ED_Count);
1524 Cmd_AddCommand ("profile", PR_Profile_f);
1525 Cmd_AddCommand ("pr_fields", PR_Fields_f);
1526 Cmd_AddCommand ("pr_globals", PR_Globals_f);
1527 Cvar_RegisterVariable (&pr_checkextension);
1528 Cvar_RegisterVariable (&nomonsters);
1529 Cvar_RegisterVariable (&gamecfg);
1530 Cvar_RegisterVariable (&scratch1);
1531 Cvar_RegisterVariable (&scratch2);
1532 Cvar_RegisterVariable (&scratch3);
1533 Cvar_RegisterVariable (&scratch4);
1534 Cvar_RegisterVariable (&savedgamecfg);
1535 Cvar_RegisterVariable (&saved1);
1536 Cvar_RegisterVariable (&saved2);
1537 Cvar_RegisterVariable (&saved3);
1538 Cvar_RegisterVariable (&saved4);
1539 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1540 Cvar_RegisterVariable (&decors);
1541 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1542 if (gamemode == GAME_NEHAHRA)
1544 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1545 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1546 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1547 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1548 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1549 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1550 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1551 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1552 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1553 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1555 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1556 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1557 Cvar_RegisterVariable (&pr_boundscheck);
1558 Cvar_RegisterVariable (&pr_traceqc);
1560 progs_mempool = Mem_AllocPool("progs.dat");
1561 edictstring_mempool = Mem_AllocPool("edict strings");
1566 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1567 edict_t *EDICT_NUM_ERROR(int n)
1569 Host_Error ("EDICT_NUM: bad number %i", n);
1573 int NUM_FOR_EDICT(edict_t *e)
1577 if ((unsigned int)n >= MAX_EDICTS)
1578 Host_Error ("NUM_FOR_EDICT: bad pointer");
1582 int NoCrash_NUM_FOR_EDICT(edict_t *e)
1584 return e - sv.edicts;
1587 //#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1588 //#define PROG_TO_EDICT(e) (sv.edictstable[(e) / (progs->entityfields * 4)])
1589 int EDICT_TO_PROG(edict_t *e)
1593 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1594 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1595 return n;// EXPERIMENTAL
1596 //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1598 edict_t *PROG_TO_EDICT(int n)
1600 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1601 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1602 return sv.edictstable[n]; // EXPERIMENTAL
1603 //return sv.edictstable[(n) / (progs->entityfields * 4)];