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(edict_t *ent, 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;
122 int eval_clientcolors;
126 mfunction_t *SV_PlayerPhysicsQC;
127 mfunction_t *EndFrameQC;
128 //KrimZon - SERVER COMMANDS IN QUAKEC
129 mfunction_t *SV_ParseClientCommandQC;
131 int FindFieldOffset(const char *field)
134 d = ED_FindField(field);
140 void FindEdictFieldOffsets(void)
142 eval_gravity = FindFieldOffset("gravity");
143 eval_button3 = FindFieldOffset("button3");
144 eval_button4 = FindFieldOffset("button4");
145 eval_button5 = FindFieldOffset("button5");
146 eval_button6 = FindFieldOffset("button6");
147 eval_button7 = FindFieldOffset("button7");
148 eval_button8 = FindFieldOffset("button8");
149 eval_glow_size = FindFieldOffset("glow_size");
150 eval_glow_trail = FindFieldOffset("glow_trail");
151 eval_glow_color = FindFieldOffset("glow_color");
152 eval_items2 = FindFieldOffset("items2");
153 eval_scale = FindFieldOffset("scale");
154 eval_alpha = FindFieldOffset("alpha");
155 eval_renderamt = FindFieldOffset("renderamt"); // HalfLife support
156 eval_rendermode = FindFieldOffset("rendermode"); // HalfLife support
157 eval_fullbright = FindFieldOffset("fullbright");
158 eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
159 eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
160 eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
161 eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
162 eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
163 eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
164 eval_ammo_plasma = FindFieldOffset("ammo_plasma");
165 eval_idealpitch = FindFieldOffset("idealpitch");
166 eval_pitch_speed = FindFieldOffset("pitch_speed");
167 eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
168 eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
169 eval_exteriormodeltoclient = FindFieldOffset("exteriormodeltoclient");
170 eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
171 eval_ping = FindFieldOffset("ping");
172 eval_movement = FindFieldOffset("movement");
173 eval_pmodel = FindFieldOffset("pmodel");
174 eval_punchvector = FindFieldOffset("punchvector");
175 eval_viewzoom = FindFieldOffset("viewzoom");
176 eval_clientcolors = FindFieldOffset("clientcolors");
177 eval_tag_entity = FindFieldOffset("tag_entity");
178 eval_tag_index = FindFieldOffset("tag_index");
180 // LordHavoc: allowing QuakeC to override the player movement code
181 SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
182 // LordHavoc: support for endframe
183 EndFrameQC = ED_FindFunction ("EndFrame");
184 //KrimZon - SERVER COMMANDS IN QUAKEC
185 SV_ParseClientCommandQC = ED_FindFunction ("SV_ParseClientCommand");
192 Sets everything to NULL
195 void ED_ClearEdict (edict_t *e)
198 memset (e->v, 0, progs->entityfields * 4);
200 // LordHavoc: for consistency set these here
201 num = NUM_FOR_EDICT(e) - 1;
202 if (num >= 0 && num < svs.maxclients)
204 e->v->colormap = num + 1;
205 e->v->team = (svs.clients[num].colors & 15) + 1;
206 e->v->netname = PR_SetString(svs.clients[num].name);
214 Either finds a free edict, or allocates a new one.
215 Try to avoid reusing an entity that was recently freed, because it
216 can cause the client to think the entity morphed into something else
217 instead of being removed and recreated, which can cause interpolated
218 angles and bad trails.
221 edict_t *ED_Alloc (void)
226 for (i = svs.maxclients + 1;i < sv.num_edicts;i++)
229 // the first couple seconds of server time can involve a lot of
230 // freeing and allocating, so relax the replacement policy
231 if (e->e->free && ( e->e->freetime < 2 || sv.time - e->e->freetime > 0.5 ) )
239 Host_Error ("ED_Alloc: no free edicts");
242 if (sv.num_edicts >= sv.max_edicts)
254 Marks the edict as free
255 FIXME: walk all entities and NULL out references to this entity
258 void ED_Free (edict_t *ed)
260 SV_UnlinkEdict (ed); // unlink from world bsp
264 ed->v->takedamage = 0;
265 ed->v->modelindex = 0;
269 VectorClear(ed->v->origin);
270 VectorClear(ed->v->angles);
271 ed->v->nextthink = -1;
274 ed->e->freetime = sv.time;
277 //===========================================================================
284 ddef_t *ED_GlobalAtOfs (int ofs)
289 for (i=0 ; i<progs->numglobaldefs ; i++)
291 def = &pr_globaldefs[i];
303 ddef_t *ED_FieldAtOfs (int ofs)
308 for (i=0 ; i<progs->numfielddefs ; i++)
310 def = &pr_fielddefs[i];
322 ddef_t *ED_FindField (const char *name)
327 for (i=0 ; i<progs->numfielddefs ; i++)
329 def = &pr_fielddefs[i];
330 if (!strcmp(PR_GetString(def->s_name), name))
341 ddef_t *ED_FindGlobal (const char *name)
346 for (i=0 ; i<progs->numglobaldefs ; i++)
348 def = &pr_globaldefs[i];
349 if (!strcmp(PR_GetString(def->s_name), name))
361 mfunction_t *ED_FindFunction (const char *name)
366 for (i=0 ; i<progs->numfunctions ; i++)
368 func = &pr_functions[i];
369 if (!strcmp(PR_GetString(func->s_name), name))
380 Returns a string describing *data in a type specific manner
383 int NoCrash_NUM_FOR_EDICT(edict_t *e);
384 char *PR_ValueString (etype_t type, eval_t *val)
386 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
391 type &= ~DEF_SAVEGLOBAL;
396 sprintf (line, "%s", PR_GetString(val->string));
399 //n = NoCrash_NUM_FOR_EDICT(PROG_TO_EDICT(val->edict));
401 if (n < 0 || n >= MAX_EDICTS)
402 sprintf (line, "entity %i (invalid!)", n);
404 sprintf (line, "entity %i", n);
407 f = pr_functions + val->function;
408 sprintf (line, "%s()", PR_GetString(f->s_name));
411 def = ED_FieldAtOfs ( val->_int );
412 sprintf (line, ".%s", PR_GetString(def->s_name));
415 sprintf (line, "void");
418 // LordHavoc: changed from %5.1f to %10.4f
419 sprintf (line, "%10.4f", val->_float);
422 // LordHavoc: changed from %5.1f to %10.4f
423 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
426 sprintf (line, "pointer");
429 sprintf (line, "bad type %i", type);
440 Returns a string describing *data in a type specific manner
441 Easier to parse than PR_ValueString
444 char *PR_UglyValueString (etype_t type, eval_t *val)
446 static char line[4096];
452 type &= ~DEF_SAVEGLOBAL;
457 sprintf (line, "%s", PR_GetString(val->string));
460 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
463 f = pr_functions + val->function;
464 sprintf (line, "%s", PR_GetString(f->s_name));
467 def = ED_FieldAtOfs ( val->_int );
468 // LordHavoc: parse the string a bit to turn special characters
469 // (like newline, specifically) into escape codes,
470 // this fixes saving games from various mods
471 //sprintf (line, "%s", PR_GetString(def->s_name));
472 s = PR_GetString(def->s_name);
473 for (i = 0;i < 4095 && *s;)
492 sprintf (line, "void");
495 sprintf (line, "%f", val->_float);
498 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
501 sprintf (line, "bad type %i", type);
512 Returns a string with a description and the contents of a global,
513 padded to 20 field width
516 char *PR_GlobalString (int ofs)
522 static char line[128];
524 val = (void *)&pr_globals[ofs];
525 def = ED_GlobalAtOfs(ofs);
527 snprintf (line, sizeof (line), "%i(?)", ofs);
530 s = PR_ValueString (def->type, val);
531 snprintf (line, sizeof (line), "%i(%s)%s", ofs, PR_GetString(def->s_name), s);
536 strlcat (line, " ", sizeof (line));
537 strlcat (line, " ", sizeof (line));
542 char *PR_GlobalStringNoContents (int ofs)
546 static char line[128];
548 def = ED_GlobalAtOfs(ofs);
550 snprintf (line, sizeof (line), "%i(?)", ofs);
552 snprintf (line, sizeof (line), "%i(%s)", ofs, PR_GetString(def->s_name));
556 strlcat (line, " ", sizeof (line));
557 strlcat (line, " ", sizeof (line));
570 // LordHavoc: optimized this to print out much more quickly (tempstring)
571 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
572 void ED_Print (edict_t *ed)
580 char tempstring[8192], tempstring2[260]; // temporary string buffers
584 Con_Printf ("FREE\n");
589 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
590 for (i=1 ; i<progs->numfielddefs ; i++)
592 d = &pr_fielddefs[i];
593 name = PR_GetString(d->s_name);
594 if (name[strlen(name)-2] == '_')
595 continue; // skip _x, _y, _z vars
597 v = (int *)((char *)ed->v + d->ofs*4);
599 // if the value is still all 0, skip the field
600 type = d->type & ~DEF_SAVEGLOBAL;
602 for (j=0 ; j<type_size[type] ; j++)
605 if (j == type_size[type])
608 if (strlen(name) > 256)
610 strncpy(tempstring2, name, 256);
611 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
612 tempstring2[259] = 0;
615 strlcat (tempstring, name, sizeof (tempstring));
616 for (l = strlen(name);l < 14;l++)
617 strcat(tempstring, " ");
618 strcat(tempstring, " ");
620 name = PR_ValueString(d->type, (eval_t *)v);
621 if (strlen(name) > 256)
623 strncpy(tempstring2, name, 256);
624 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
625 tempstring2[259] = 0;
628 strlcat (tempstring, name, sizeof (tempstring));
629 strlcat (tempstring, "\n", sizeof (tempstring));
630 if (strlen(tempstring) >= 4096)
632 Con_Printf("%s", tempstring);
637 Con_Printf("%s", tempstring);
647 void ED_Write (qfile_t *f, edict_t *ed)
655 FS_Printf (f, "{\n");
659 FS_Printf (f, "}\n");
663 for (i=1 ; i<progs->numfielddefs ; i++)
665 d = &pr_fielddefs[i];
666 name = PR_GetString(d->s_name);
667 if (name[strlen(name)-2] == '_')
668 continue; // skip _x, _y, _z vars
670 v = (int *)((char *)ed->v + d->ofs*4);
672 // if the value is still all 0, skip the field
673 type = d->type & ~DEF_SAVEGLOBAL;
674 for (j=0 ; j<type_size[type] ; j++)
677 if (j == type_size[type])
680 FS_Printf (f,"\"%s\" ",name);
681 FS_Printf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
684 FS_Printf (f, "}\n");
687 void ED_PrintNum (int ent)
689 ED_Print (EDICT_NUM(ent));
696 For debugging, prints all the entities in the current server
699 void ED_PrintEdicts (void)
703 Con_Printf ("%i entities\n", sv.num_edicts);
704 for (i=0 ; i<sv.num_edicts ; i++)
712 For debugging, prints a single edict
715 void ED_PrintEdict_f (void)
719 i = atoi (Cmd_Argv(1));
720 if (i >= sv.num_edicts)
722 Con_Printf("Bad edict number\n");
739 int active, models, solid, step;
741 active = models = solid = step = 0;
742 for (i=0 ; i<sv.num_edicts ; i++)
752 if (ent->v->movetype == MOVETYPE_STEP)
756 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
757 Con_Printf ("active :%3i\n", active);
758 Con_Printf ("view :%3i\n", models);
759 Con_Printf ("touch :%3i\n", solid);
760 Con_Printf ("step :%3i\n", step);
765 ==============================================================================
769 FIXME: need to tag constants, doesn't really work
770 ==============================================================================
778 void ED_WriteGlobals (qfile_t *f)
786 for (i=0 ; i<progs->numglobaldefs ; i++)
788 def = &pr_globaldefs[i];
790 if ( !(def->type & DEF_SAVEGLOBAL) )
792 type &= ~DEF_SAVEGLOBAL;
794 if (type != ev_string && type != ev_float && type != ev_entity)
797 name = PR_GetString(def->s_name);
798 FS_Printf (f,"\"%s\" ", name);
799 FS_Printf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
809 void ED_ParseGlobals (const char *data)
811 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
817 if (!COM_ParseToken(&data, false))
818 Host_Error ("ED_ParseEntity: EOF without closing brace");
819 if (com_token[0] == '}')
822 strcpy (keyname, com_token);
825 if (!COM_ParseToken(&data, false))
826 Host_Error ("ED_ParseEntity: EOF without closing brace");
828 if (com_token[0] == '}')
829 Host_Error ("ED_ParseEntity: closing brace without data");
831 key = ED_FindGlobal (keyname);
834 Con_DPrintf ("'%s' is not a global\n", keyname);
838 if (!ED_ParseEpair(NULL, key, com_token))
839 Host_Error ("ED_ParseGlobals: parse error");
843 //============================================================================
851 char *ED_NewString (const char *string)
856 l = strlen(string) + 1;
857 new = Mem_Alloc(edictstring_mempool, l);
860 for (i=0 ; i< l ; i++)
862 if (string[i] == '\\' && i < l-1)
865 if (string[i] == 'n')
871 *new_p++ = string[i];
882 Can parse either fields or globals
883 returns false if error
886 qboolean ED_ParseEpair(edict_t *ent, ddef_t *key, const char *s)
894 val = (eval_t *)((int *)ent->v + key->ofs);
896 val = (eval_t *)((int *)pr_globals + key->ofs);
897 switch (key->type & ~DEF_SAVEGLOBAL)
900 val->string = PR_SetString(ED_NewString(s));
904 while (*s && *s <= ' ')
906 val->_float = atof(s);
910 for (i = 0;i < 3;i++)
912 while (*s && *s <= ' ')
916 val->vector[i] = atof(s);
925 while (*s && *s <= ' ')
928 if (i < 0 || i >= MAX_EDICTS)
929 Con_Printf("ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i)\n", i, MAX_EDICTS);
930 while (i >= sv.max_edicts)
932 // if SV_IncreaseEdicts was called the base pointer needs to be updated
934 val = (eval_t *)((int *)ent->v + key->ofs);
935 val->edict = EDICT_TO_PROG(EDICT_NUM(i));
939 def = ED_FindField(s);
942 Con_DPrintf("ED_ParseEpair: Can't find field %s\n", s);
945 val->_int = G_INT(def->ofs);
949 func = ED_FindFunction(s);
952 Con_Printf ("ED_ParseEpair: Can't find function %s\n", s);
955 val->function = func - pr_functions;
959 Con_Printf("ED_ParseEpair: Unknown key->type %i for key \"%s\"\n", key->type, PR_GetString(key->s_name));
969 Parses an edict out of the given string, returning the new position
970 ed should be a properly initialized empty edict.
971 Used for initial level load and for savegames.
974 const char *ED_ParseEdict (const char *data, edict_t *ent)
985 if (ent != sv.edicts) // hack
986 memset (ent->v, 0, progs->entityfields * 4);
988 // go through all the dictionary pairs
992 if (!COM_ParseToken(&data, false))
993 Host_Error ("ED_ParseEntity: EOF without closing brace");
994 if (com_token[0] == '}')
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 if (!COM_ParseToken(&data, false))
1023 Host_Error ("ED_ParseEntity: EOF without closing brace");
1025 if (com_token[0] == '}')
1026 Host_Error ("ED_ParseEntity: closing brace without data");
1030 // keynames with a leading underscore are used for utility comments,
1031 // and are immediately discarded by quake
1032 if (keyname[0] == '_')
1035 key = ED_FindField (keyname);
1038 Con_DPrintf ("'%s' is not a field\n", keyname);
1045 strcpy (temp, com_token);
1046 sprintf (com_token, "0 %s 0", temp);
1049 if (!ED_ParseEpair(ent, key, com_token))
1050 Host_Error ("ED_ParseEdict: parse error");
1054 ent->e->free = true;
1064 The entities are directly placed in the array, rather than allocated with
1065 ED_Alloc, because otherwise an error loading the map would have entity
1066 number references out of order.
1068 Creates a server's entity / program execution context by
1069 parsing textual entity definitions out of an ent file.
1071 Used for both fresh maps and savegame loads. A fresh map would also need
1072 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1075 void ED_LoadFromFile (const char *data)
1078 int parsed, inhibited, spawned, died;
1086 pr_global_struct->time = sv.time;
1091 // parse the opening brace
1092 if (!COM_ParseToken(&data, false))
1094 if (com_token[0] != '{')
1095 Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1101 data = ED_ParseEdict (data, ent);
1104 // remove things from different skill levels or deathmatch
1105 if (deathmatch.integer)
1107 if (((int)ent->v->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1114 else if ((current_skill == 0 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_EASY ))
1115 || (current_skill == 1 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_MEDIUM))
1116 || (current_skill >= 2 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_HARD )))
1124 // immediately call spawn function
1126 if (!ent->v->classname)
1128 Con_Printf ("No classname for:\n");
1134 // look for the spawn function
1135 func = ED_FindFunction (PR_GetString(ent->v->classname));
1139 if (developer.integer) // don't confuse non-developers with errors
1141 Con_Printf ("No spawn function for:\n");
1148 pr_global_struct->self = EDICT_TO_PROG(ent);
1149 PR_ExecuteProgram (func - pr_functions, "");
1155 Con_DPrintf ("%i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", parsed, inhibited, spawned, died, spawned - died);
1159 typedef struct dpfield_s
1166 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1168 dpfield_t dpfields[] =
1170 {ev_float, "gravity"},
1171 {ev_float, "button3"},
1172 {ev_float, "button4"},
1173 {ev_float, "button5"},
1174 {ev_float, "button6"},
1175 {ev_float, "button7"},
1176 {ev_float, "button8"},
1177 {ev_float, "glow_size"},
1178 {ev_float, "glow_trail"},
1179 {ev_float, "glow_color"},
1180 {ev_float, "items2"},
1181 {ev_float, "scale"},
1182 {ev_float, "alpha"},
1183 {ev_float, "renderamt"},
1184 {ev_float, "rendermode"},
1185 {ev_float, "fullbright"},
1186 {ev_float, "ammo_shells1"},
1187 {ev_float, "ammo_nails1"},
1188 {ev_float, "ammo_lava_nails"},
1189 {ev_float, "ammo_rockets1"},
1190 {ev_float, "ammo_multi_rockets"},
1191 {ev_float, "ammo_cells1"},
1192 {ev_float, "ammo_plasma"},
1193 {ev_float, "idealpitch"},
1194 {ev_float, "pitch_speed"},
1195 {ev_entity, "viewmodelforclient"},
1196 {ev_entity, "nodrawtoclient"},
1197 {ev_entity, "exteriormodeltoclient"},
1198 {ev_entity, "drawonlytoclient"},
1200 {ev_vector, "movement"},
1201 {ev_float, "pmodel"},
1202 {ev_vector, "punchvector"},
1203 {ev_float, "clientcolors"},
1204 {ev_entity, "tag_entity"},
1205 {ev_float, "tag_index"}
1213 extern void PR_Cmd_Reset (void);
1214 void PR_LoadProgs (void)
1218 ddef_t *infielddefs;
1220 dfunction_t *dfunctions;
1222 // flush the non-C variable lookup cache
1223 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1224 gefvCache[i].field[0] = 0;
1226 Mem_EmptyPool(progs_mempool);
1227 Mem_EmptyPool(edictstring_mempool);
1229 temp = FS_LoadFile ("progs.dat", false);
1231 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1233 progs = (dprograms_t *)Mem_Alloc(progs_mempool, fs_filesize);
1235 memcpy(progs, temp, fs_filesize);
1238 Con_DPrintf ("Programs occupy %iK.\n", fs_filesize/1024);
1240 pr_crc = CRC_Block((qbyte *)progs, fs_filesize);
1242 // byte swap the header
1243 for (i = 0;i < (int) sizeof(*progs) / 4;i++)
1244 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1246 if (progs->version != PROG_VERSION)
1247 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1248 if (progs->crc != PROGHEADER_CRC)
1249 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1251 //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1252 dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1253 pr_strings = (char *)progs + progs->ofs_strings;
1254 pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1256 // we need to expand the fielddefs list to include all the engine fields,
1257 // so allocate a new place for it
1258 infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1259 pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1261 pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1263 // moved edict_size calculation down below field adding code
1265 pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1266 pr_globals = (float *)pr_global_struct;
1268 // byte swap the lumps
1269 for (i=0 ; i<progs->numstatements ; i++)
1271 pr_statements[i].op = LittleShort(pr_statements[i].op);
1272 pr_statements[i].a = LittleShort(pr_statements[i].a);
1273 pr_statements[i].b = LittleShort(pr_statements[i].b);
1274 pr_statements[i].c = LittleShort(pr_statements[i].c);
1277 pr_functions = Mem_Alloc(progs_mempool, sizeof(mfunction_t) * progs->numfunctions);
1278 for (i = 0;i < progs->numfunctions;i++)
1280 pr_functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1281 pr_functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1282 pr_functions[i].s_name = LittleLong (dfunctions[i].s_name);
1283 pr_functions[i].s_file = LittleLong (dfunctions[i].s_file);
1284 pr_functions[i].numparms = LittleLong (dfunctions[i].numparms);
1285 pr_functions[i].locals = LittleLong (dfunctions[i].locals);
1286 memcpy(pr_functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1289 for (i=0 ; i<progs->numglobaldefs ; i++)
1291 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1292 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1293 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1296 // copy the progs fields to the new fields list
1297 for (i = 0;i < progs->numfielddefs;i++)
1299 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1300 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1301 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1302 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1303 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1306 // append the darkplaces fields
1307 for (i = 0;i < (int) DPFIELDS;i++)
1309 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1310 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1311 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1312 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1313 progs->entityfields += 3;
1315 progs->entityfields++;
1316 progs->numfielddefs++;
1319 for (i=0 ; i<progs->numglobals ; i++)
1320 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1322 // moved edict_size calculation down here, below field adding code
1323 // LordHavoc: this no longer includes the edict_t header
1324 pr_edict_size = progs->entityfields * 4;
1325 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1327 // LordHavoc: bounds check anything static
1328 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1334 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1335 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1338 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1339 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1341 // global global global
1376 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1377 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1379 // global none global
1385 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1386 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1402 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1403 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1417 if ((unsigned short) st->a >= progs->numglobals)
1418 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1421 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1426 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1427 PR_Execute_ProgsLoaded();
1432 void PR_Fields_f (void)
1434 int i, j, ednum, used, usedamount;
1436 char tempstring[5000], tempstring2[260], *name;
1442 Con_Printf("no progs loaded\n");
1445 counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1446 for (ednum = 0;ednum < sv.max_edicts;ednum++)
1448 ed = EDICT_NUM(ednum);
1451 for (i = 1;i < progs->numfielddefs;i++)
1453 d = &pr_fielddefs[i];
1454 name = PR_GetString(d->s_name);
1455 if (name[strlen(name)-2] == '_')
1456 continue; // skip _x, _y, _z vars
1457 v = (int *)((char *)ed->v + d->ofs*4);
1458 // if the value is still all 0, skip the field
1459 for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1472 for (i = 0;i < progs->numfielddefs;i++)
1474 d = &pr_fielddefs[i];
1475 name = PR_GetString(d->s_name);
1476 if (name[strlen(name)-2] == '_')
1477 continue; // skip _x, _y, _z vars
1478 switch(d->type & ~DEF_SAVEGLOBAL)
1481 strlcat (tempstring, "string ", sizeof (tempstring));
1484 strlcat (tempstring, "entity ", sizeof (tempstring));
1487 strlcat (tempstring, "function ", sizeof (tempstring));
1490 strlcat (tempstring, "field ", sizeof (tempstring));
1493 strlcat (tempstring, "void ", sizeof (tempstring));
1496 strlcat (tempstring, "float ", sizeof (tempstring));
1499 strlcat (tempstring, "vector ", sizeof (tempstring));
1502 strlcat (tempstring, "pointer ", sizeof (tempstring));
1505 snprintf (tempstring2, sizeof (tempstring2), "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1506 strlcat (tempstring, tempstring2, sizeof (tempstring));
1509 if (strlen(name) > 256)
1511 strncpy(tempstring2, name, 256);
1512 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1513 tempstring2[259] = 0;
1516 strcat (tempstring, name);
1517 for (j = strlen(name);j < 25;j++)
1518 strcat(tempstring, " ");
1519 snprintf (tempstring2, sizeof (tempstring2), "%5d", counts[i]);
1520 strlcat (tempstring, tempstring2, sizeof (tempstring));
1521 strlcat (tempstring, "\n", sizeof (tempstring));
1522 if (strlen(tempstring) >= 4096)
1524 Con_Printf("%s", tempstring);
1530 usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1534 Con_Printf("%i entity fields (%i in use), totalling %i bytes per edict (%i in use), %i edicts allocated, %i bytes total spent on edict fields (%i needed)\n", progs->entityfields, used, progs->entityfields * 4, usedamount * 4, sv.max_edicts, progs->entityfields * 4 * sv.max_edicts, usedamount * 4 * sv.max_edicts);
1537 void PR_Globals_f (void)
1542 Con_Printf("no progs loaded\n");
1545 for (i = 0;i < progs->numglobaldefs;i++)
1546 Con_Printf("%s\n", PR_GetString(pr_globaldefs[i].s_name));
1547 Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1555 extern void PR_Cmd_Init(void);
1558 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1559 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1560 Cmd_AddCommand ("edictcount", ED_Count);
1561 Cmd_AddCommand ("profile", PR_Profile_f);
1562 Cmd_AddCommand ("pr_fields", PR_Fields_f);
1563 Cmd_AddCommand ("pr_globals", PR_Globals_f);
1564 Cvar_RegisterVariable (&pr_checkextension);
1565 Cvar_RegisterVariable (&nomonsters);
1566 Cvar_RegisterVariable (&gamecfg);
1567 Cvar_RegisterVariable (&scratch1);
1568 Cvar_RegisterVariable (&scratch2);
1569 Cvar_RegisterVariable (&scratch3);
1570 Cvar_RegisterVariable (&scratch4);
1571 Cvar_RegisterVariable (&savedgamecfg);
1572 Cvar_RegisterVariable (&saved1);
1573 Cvar_RegisterVariable (&saved2);
1574 Cvar_RegisterVariable (&saved3);
1575 Cvar_RegisterVariable (&saved4);
1576 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1577 Cvar_RegisterVariable (&decors);
1578 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1579 if (gamemode == GAME_NEHAHRA)
1581 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1582 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1583 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1584 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1585 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1586 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1587 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1588 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1589 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1590 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1592 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1593 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1594 Cvar_RegisterVariable (&pr_boundscheck);
1595 Cvar_RegisterVariable (&pr_traceqc);
1597 progs_mempool = Mem_AllocPool("progs.dat");
1598 edictstring_mempool = Mem_AllocPool("edict strings");
1603 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1604 edict_t *EDICT_NUM_ERROR(int n, char *filename, int fileline)
1606 Host_Error ("EDICT_NUM: bad number %i (called at %s:%i)", n, filename, fileline);
1611 int NUM_FOR_EDICT_ERROR(edict_t *e)
1613 Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1617 int NUM_FOR_EDICT(edict_t *e)
1621 if ((unsigned int)n >= MAX_EDICTS)
1622 Host_Error ("NUM_FOR_EDICT: bad pointer");
1626 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1628 // return e - sv.edicts;
1631 //#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1632 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1633 int EDICT_TO_PROG(edict_t *e)
1637 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1638 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1639 return n;// EXPERIMENTAL
1640 //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1642 edict_t *PROG_TO_EDICT(int n)
1644 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1645 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1646 return sv.edicts + n; // EXPERIMENTAL
1647 //return sv.edicts + ((n) / (progs->entityfields * 4));