2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // sv_edict.c -- entity dictionary
25 dfunction_t *pr_functions;
28 ddef_t *pr_globaldefs;
29 dstatement_t *pr_statements;
30 globalvars_t *pr_global_struct;
31 float *pr_globals; // same as pr_global_struct
32 int pr_edict_size; // in bytes
33 int pr_edictareasize; // LordHavoc: in bytes
35 unsigned short pr_crc;
37 mempool_t *progs_mempool;
38 mempool_t *edictstring_mempool;
40 int type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
42 ddef_t *ED_FieldAtOfs (int ofs);
43 qboolean ED_ParseEpair (void *base, ddef_t *key, char *s);
45 cvar_t pr_checkextension = {0, "pr_checkextension", "1"};
46 cvar_t nomonsters = {0, "nomonsters", "0"};
47 cvar_t gamecfg = {0, "gamecfg", "0"};
48 cvar_t scratch1 = {0, "scratch1", "0"};
49 cvar_t scratch2 = {0,"scratch2", "0"};
50 cvar_t scratch3 = {0, "scratch3", "0"};
51 cvar_t scratch4 = {0, "scratch4", "0"};
52 cvar_t savedgamecfg = {CVAR_SAVE, "savedgamecfg", "0"};
53 cvar_t saved1 = {CVAR_SAVE, "saved1", "0"};
54 cvar_t saved2 = {CVAR_SAVE, "saved2", "0"};
55 cvar_t saved3 = {CVAR_SAVE, "saved3", "0"};
56 cvar_t saved4 = {CVAR_SAVE, "saved4", "0"};
57 cvar_t decors = {0, "decors", "0"};
58 cvar_t nehx00 = {0, "nehx00", "0"};cvar_t nehx01 = {0, "nehx01", "0"};
59 cvar_t nehx02 = {0, "nehx02", "0"};cvar_t nehx03 = {0, "nehx03", "0"};
60 cvar_t nehx04 = {0, "nehx04", "0"};cvar_t nehx05 = {0, "nehx05", "0"};
61 cvar_t nehx06 = {0, "nehx06", "0"};cvar_t nehx07 = {0, "nehx07", "0"};
62 cvar_t nehx08 = {0, "nehx08", "0"};cvar_t nehx09 = {0, "nehx09", "0"};
63 cvar_t nehx10 = {0, "nehx10", "0"};cvar_t nehx11 = {0, "nehx11", "0"};
64 cvar_t nehx12 = {0, "nehx12", "0"};cvar_t nehx13 = {0, "nehx13", "0"};
65 cvar_t nehx14 = {0, "nehx14", "0"};cvar_t nehx15 = {0, "nehx15", "0"};
66 cvar_t nehx16 = {0, "nehx16", "0"};cvar_t nehx17 = {0, "nehx17", "0"};
67 cvar_t nehx18 = {0, "nehx18", "0"};cvar_t nehx19 = {0, "nehx19", "0"};
68 cvar_t cutscene = {0, "cutscene", "1"};
69 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
70 cvar_t pr_boundscheck = {0, "pr_boundscheck", "1"};
72 #define MAX_FIELD_LEN 64
73 #define GEFV_CACHESIZE 2
77 char field[MAX_FIELD_LEN];
80 static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};
82 ddef_t *ED_FindField (char *name);
83 dfunction_t *ED_FindFunction (char *name);
85 // LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue... these are defined as externs in progs.h
99 int eval_renderamt; // HalfLife support
100 int eval_rendermode; // HalfLife support
102 int eval_ammo_shells1;
103 int eval_ammo_nails1;
104 int eval_ammo_lava_nails;
105 int eval_ammo_rockets1;
106 int eval_ammo_multi_rockets;
107 int eval_ammo_cells1;
108 int eval_ammo_plasma;
110 int eval_pitch_speed;
111 int eval_viewmodelforclient;
112 int eval_nodrawtoclient;
113 int eval_exteriormodeltoclient;
114 int eval_drawonlytoclient;
118 int eval_punchvector;
121 dfunction_t *SV_PlayerPhysicsQC;
122 dfunction_t *EndFrameQC;
124 int FindFieldOffset(char *field)
127 d = ED_FindField(field);
133 void FindEdictFieldOffsets(void)
135 eval_gravity = FindFieldOffset("gravity");
136 eval_button3 = FindFieldOffset("button3");
137 eval_button4 = FindFieldOffset("button4");
138 eval_button5 = FindFieldOffset("button5");
139 eval_button6 = FindFieldOffset("button6");
140 eval_button7 = FindFieldOffset("button7");
141 eval_button8 = FindFieldOffset("button8");
142 eval_glow_size = FindFieldOffset("glow_size");
143 eval_glow_trail = FindFieldOffset("glow_trail");
144 eval_glow_color = FindFieldOffset("glow_color");
145 eval_items2 = FindFieldOffset("items2");
146 eval_scale = FindFieldOffset("scale");
147 eval_alpha = FindFieldOffset("alpha");
148 eval_renderamt = FindFieldOffset("renderamt"); // HalfLife support
149 eval_rendermode = FindFieldOffset("rendermode"); // HalfLife support
150 eval_fullbright = FindFieldOffset("fullbright");
151 eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
152 eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
153 eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
154 eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
155 eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
156 eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
157 eval_ammo_plasma = FindFieldOffset("ammo_plasma");
158 eval_idealpitch = FindFieldOffset("idealpitch");
159 eval_pitch_speed = FindFieldOffset("pitch_speed");
160 eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
161 eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
162 eval_exteriormodeltoclient = FindFieldOffset("exteriormodeltoclient");
163 eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
164 eval_ping = FindFieldOffset("ping");
165 eval_movement = FindFieldOffset("movement");
166 eval_pmodel = FindFieldOffset("pmodel");
167 eval_punchvector = FindFieldOffset("punchvector");
168 eval_viewzoom = FindFieldOffset("viewzoom");
170 // LordHavoc: allowing QuakeC to override the player movement code
171 SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
172 // LordHavoc: support for endframe
173 EndFrameQC = ED_FindFunction ("EndFrame");
180 Sets everything to NULL
183 void ED_ClearEdict (edict_t *e)
185 memset (&e->v, 0, progs->entityfields * 4);
193 Either finds a free edict, or allocates a new one.
194 Try to avoid reusing an entity that was recently freed, because it
195 can cause the client to think the entity morphed into something else
196 instead of being removed and recreated, which can cause interpolated
197 angles and bad trails.
200 edict_t *ED_Alloc (void)
205 for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
208 // the first couple seconds of server time can involve a lot of
209 // freeing and allocating, so relax the replacement policy
210 if (e->free && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) )
218 Host_Error ("ED_Alloc: no free edicts");
231 Marks the edict as free
232 FIXME: walk all entities and NULL out references to this entity
235 void ED_Free (edict_t *ed)
237 SV_UnlinkEdict (ed); // unlink from world bsp
241 ed->v.takedamage = 0;
242 ed->v.modelindex = 0;
246 VectorClear(ed->v.origin);
247 VectorClear(ed->v.angles);
248 ed->v.nextthink = -1;
251 ed->freetime = sv.time;
254 //===========================================================================
261 ddef_t *ED_GlobalAtOfs (int ofs)
266 for (i=0 ; i<progs->numglobaldefs ; i++)
268 def = &pr_globaldefs[i];
280 ddef_t *ED_FieldAtOfs (int ofs)
285 for (i=0 ; i<progs->numfielddefs ; i++)
287 def = &pr_fielddefs[i];
299 ddef_t *ED_FindField (char *name)
304 for (i=0 ; i<progs->numfielddefs ; i++)
306 def = &pr_fielddefs[i];
307 if (!strcmp(pr_strings + def->s_name,name) )
318 ddef_t *ED_FindGlobal (char *name)
323 for (i=0 ; i<progs->numglobaldefs ; i++)
325 def = &pr_globaldefs[i];
326 if (!strcmp(pr_strings + def->s_name,name) )
338 dfunction_t *ED_FindFunction (char *name)
343 for (i=0 ; i<progs->numfunctions ; i++)
345 func = &pr_functions[i];
346 if (!strcmp(pr_strings + func->s_name,name) )
354 eval_t *GetEdictFieldValue(edict_t *ed, char *field)
360 for (i=0 ; i<GEFV_CACHESIZE ; i++)
362 if (!strcmp(field, gefvCache[i].field))
364 def = gefvCache[i].pcache;
369 def = ED_FindField (field);
371 if (strlen(field) < MAX_FIELD_LEN)
373 gefvCache[rep].pcache = def;
374 strcpy (gefvCache[rep].field, field);
382 return (eval_t *)((char *)&ed->v + def->ofs*4);
390 Returns a string describing *data in a type specific manner
393 int NoCrash_NUM_FOR_EDICT(edict_t *e);
394 char *PR_ValueString (etype_t type, eval_t *val)
396 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
401 type &= ~DEF_SAVEGLOBAL;
406 sprintf (line, "%s", pr_strings + val->string);
409 n = NoCrash_NUM_FOR_EDICT(PROG_TO_EDICT(val->edict));
410 if (n < 0 || n >= MAX_EDICTS)
411 sprintf (line, "entity %i (invalid!)", n);
413 sprintf (line, "entity %i", n);
416 f = pr_functions + val->function;
417 sprintf (line, "%s()", pr_strings + f->s_name);
420 def = ED_FieldAtOfs ( val->_int );
421 sprintf (line, ".%s", pr_strings + def->s_name);
424 sprintf (line, "void");
427 // LordHavoc: changed from %5.1f to %10.4f
428 sprintf (line, "%10.4f", val->_float);
431 // LordHavoc: changed from %5.1f to %10.4f
432 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
435 sprintf (line, "pointer");
438 sprintf (line, "bad type %i", type);
449 Returns a string describing *data in a type specific manner
450 Easier to parse than PR_ValueString
453 char *PR_UglyValueString (etype_t type, eval_t *val)
455 static char line[256];
459 type &= ~DEF_SAVEGLOBAL;
464 sprintf (line, "%s", pr_strings + val->string);
467 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
470 f = pr_functions + val->function;
471 sprintf (line, "%s", pr_strings + f->s_name);
474 def = ED_FieldAtOfs ( val->_int );
475 sprintf (line, "%s", pr_strings + def->s_name);
478 sprintf (line, "void");
481 sprintf (line, "%f", val->_float);
484 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
487 sprintf (line, "bad type %i", type);
498 Returns a string with a description and the contents of a global,
499 padded to 20 field width
502 char *PR_GlobalString (int ofs)
508 static char line[128];
510 val = (void *)&pr_globals[ofs];
511 def = ED_GlobalAtOfs(ofs);
513 sprintf (line,"%i(\?\?\?)", ofs); // LordHavoc: escaping the ?s so it is not a trigraph
516 s = PR_ValueString (def->type, val);
517 sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s);
528 char *PR_GlobalStringNoContents (int ofs)
532 static char line[128];
534 def = ED_GlobalAtOfs(ofs);
536 sprintf (line,"%i(\?\?\?)", ofs); // LordHavoc: escaping the ?s so it is not a trigraph
538 sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name);
556 // LordHavoc: optimized this to print out much more quickly (tempstring)
557 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
558 void ED_Print (edict_t *ed)
566 char tempstring[8192], tempstring2[260]; // temporary string buffers
570 Con_Printf ("FREE\n");
575 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
576 for (i=1 ; i<progs->numfielddefs ; i++)
578 d = &pr_fielddefs[i];
579 name = pr_strings + d->s_name;
580 if (name[strlen(name)-2] == '_')
581 continue; // skip _x, _y, _z vars
583 v = (int *)((char *)&ed->v + d->ofs*4);
585 // if the value is still all 0, skip the field
586 type = d->type & ~DEF_SAVEGLOBAL;
588 for (j=0 ; j<type_size[type] ; j++)
591 if (j == type_size[type])
594 if (strlen(name) > 256)
596 strncpy(tempstring2, name, 256);
597 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
598 tempstring2[259] = 0;
601 strcat(tempstring, name);
602 for (l = strlen(name);l < 14;l++)
603 strcat(tempstring, " ");
604 strcat(tempstring, " ");
606 name = PR_ValueString(d->type, (eval_t *)v);
607 if (strlen(name) > 256)
609 strncpy(tempstring2, name, 256);
610 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
611 tempstring2[259] = 0;
614 strcat(tempstring, name);
615 strcat(tempstring, "\n");
616 if (strlen(tempstring) >= 4096)
618 Con_Printf("%s", tempstring);
623 Con_Printf("%s", tempstring);
633 void ED_Write (QFile *f, edict_t *ed)
649 for (i=1 ; i<progs->numfielddefs ; i++)
651 d = &pr_fielddefs[i];
652 name = pr_strings + d->s_name;
653 if (name[strlen(name)-2] == '_')
654 continue; // skip _x, _y, _z vars
656 v = (int *)((char *)&ed->v + d->ofs*4);
658 // if the value is still all 0, skip the field
659 type = d->type & ~DEF_SAVEGLOBAL;
660 for (j=0 ; j<type_size[type] ; j++)
663 if (j == type_size[type])
666 Qprintf (f,"\"%s\" ",name);
667 Qprintf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
673 void ED_PrintNum (int ent)
675 ED_Print (EDICT_NUM(ent));
682 For debugging, prints all the entities in the current server
685 void ED_PrintEdicts (void)
689 Con_Printf ("%i entities\n", sv.num_edicts);
690 for (i=0 ; i<sv.num_edicts ; i++)
698 For debugging, prints a single edicy
701 void ED_PrintEdict_f (void)
705 i = atoi (Cmd_Argv(1));
706 if (i >= sv.num_edicts)
708 Con_Printf("Bad edict number\n");
725 int active, models, solid, step;
727 active = models = solid = step = 0;
728 for (i=0 ; i<sv.num_edicts ; i++)
738 if (ent->v.movetype == MOVETYPE_STEP)
742 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
743 Con_Printf ("active :%3i\n", active);
744 Con_Printf ("view :%3i\n", models);
745 Con_Printf ("touch :%3i\n", solid);
746 Con_Printf ("step :%3i\n", step);
751 ==============================================================================
755 FIXME: need to tag constants, doesn't really work
756 ==============================================================================
764 void ED_WriteGlobals (QFile *f)
772 for (i=0 ; i<progs->numglobaldefs ; i++)
774 def = &pr_globaldefs[i];
776 if ( !(def->type & DEF_SAVEGLOBAL) )
778 type &= ~DEF_SAVEGLOBAL;
780 if (type != ev_string && type != ev_float && type != ev_entity)
783 name = pr_strings + def->s_name;
784 Qprintf (f,"\"%s\" ", name);
785 Qprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
795 void ED_ParseGlobals (char *data)
797 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
803 data = COM_Parse (data);
804 if (com_token[0] == '}')
807 Host_Error ("ED_ParseEntity: EOF without closing brace");
809 strcpy (keyname, com_token);
812 data = COM_Parse (data);
814 Host_Error ("ED_ParseEntity: EOF without closing brace");
816 if (com_token[0] == '}')
817 Host_Error ("ED_ParseEntity: closing brace without data");
819 key = ED_FindGlobal (keyname);
822 Con_DPrintf ("'%s' is not a global\n", keyname);
826 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
827 Host_Error ("ED_ParseGlobals: parse error");
831 //============================================================================
839 char *ED_NewString (char *string)
844 l = strlen(string) + 1;
845 new = Mem_Alloc(edictstring_mempool, l);
848 for (i=0 ; i< l ; i++)
850 if (string[i] == '\\' && i < l-1)
853 if (string[i] == 'n')
859 *new_p++ = string[i];
870 Can parse either fields or globals
871 returns false if error
874 qboolean ED_ParseEpair (void *base, ddef_t *key, char *s)
883 d = (void *)((int *)base + key->ofs);
885 switch (key->type & ~DEF_SAVEGLOBAL)
888 *(string_t *)d = ED_NewString (s) - pr_strings;
892 *(float *)d = atof (s);
899 for (i=0 ; i<3 ; i++)
901 while (*v && *v != ' ')
904 ((float *)d)[i] = atof (w);
910 *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
914 def = ED_FindField (s);
917 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
918 if (strcmp(s, "sky") && strcmp(s, "fog") && strncmp(s, "fog_", 4) && strcmp(s, "farclip"))
919 Con_DPrintf ("Can't find field %s\n", s);
922 *(int *)d = G_INT(def->ofs);
926 func = ED_FindFunction (s);
929 Con_DPrintf ("Can't find function %s\n", s);
932 *(func_t *)d = func - pr_functions;
945 Parses an edict out of the given string, returning the new position
946 ed should be a properly initialized empty edict.
947 Used for initial level load and for savegames.
950 char *ED_ParseEdict (char *data, edict_t *ent)
961 if (ent != sv.edicts) // hack
962 memset (&ent->v, 0, progs->entityfields * 4);
964 // go through all the dictionary pairs
968 data = COM_Parse (data);
969 if (com_token[0] == '}')
972 Host_Error ("ED_ParseEntity: EOF without closing brace");
974 // anglehack is to allow QuakeEd to write single scalar angles
975 // and allow them to be turned into vectors. (FIXME...)
976 if (!strcmp(com_token, "angle"))
978 strcpy (com_token, "angles");
984 // FIXME: change light to _light to get rid of this hack
985 if (!strcmp(com_token, "light"))
986 strcpy (com_token, "light_lev"); // hack for single light def
988 strcpy (keyname, com_token);
990 // another hack to fix heynames with trailing spaces
992 while (n && keyname[n-1] == ' ')
999 data = COM_Parse (data);
1001 Host_Error ("ED_ParseEntity: EOF without closing brace");
1003 if (com_token[0] == '}')
1004 Host_Error ("ED_ParseEntity: closing brace without data");
1008 // keynames with a leading underscore are used for utility comments,
1009 // and are immediately discarded by quake
1010 if (keyname[0] == '_')
1013 key = ED_FindField (keyname);
1016 Con_DPrintf ("'%s' is not a field\n", keyname);
1023 strcpy (temp, com_token);
1024 sprintf (com_token, "0 %s 0", temp);
1027 if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
1028 Host_Error ("ED_ParseEdict: parse error");
1042 The entities are directly placed in the array, rather than allocated with
1043 ED_Alloc, because otherwise an error loading the map would have entity
1044 number references out of order.
1046 Creates a server's entity / program execution context by
1047 parsing textual entity definitions out of an ent file.
1049 Used for both fresh maps and savegame loads. A fresh map would also need
1050 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1053 void ED_LoadFromFile (char *data)
1061 pr_global_struct->time = sv.time;
1066 // parse the opening brace
1067 data = COM_Parse (data);
1070 if (com_token[0] != '{')
1071 Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1077 data = ED_ParseEdict (data, ent);
1079 // remove things from different skill levels or deathmatch
1080 if (deathmatch.integer)
1082 if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1089 else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY ))
1090 || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
1091 || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD )))
1099 // immediately call spawn function
1101 if (!ent->v.classname)
1103 Con_Printf ("No classname for:\n");
1109 // look for the spawn function
1110 func = ED_FindFunction ( pr_strings + ent->v.classname );
1114 if (developer.integer) // don't confuse non-developers with errors
1116 Con_Printf ("No spawn function for:\n");
1123 pr_global_struct->self = EDICT_TO_PROG(ent);
1124 PR_ExecuteProgram (func - pr_functions, "");
1127 Con_DPrintf ("%i entities inhibited\n", inhibit);
1131 typedef struct dpfield_s
1138 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1140 dpfield_t dpfields[] =
1142 {ev_float, "gravity"},
1143 {ev_float, "button3"},
1144 {ev_float, "button4"},
1145 {ev_float, "button5"},
1146 {ev_float, "button6"},
1147 {ev_float, "button7"},
1148 {ev_float, "button8"},
1149 {ev_float, "glow_size"},
1150 {ev_float, "glow_trail"},
1151 {ev_float, "glow_color"},
1152 {ev_float, "items2"},
1153 {ev_float, "scale"},
1154 {ev_float, "alpha"},
1155 {ev_float, "renderamt"},
1156 {ev_float, "rendermode"},
1157 {ev_float, "fullbright"},
1158 {ev_float, "ammo_shells1"},
1159 {ev_float, "ammo_nails1"},
1160 {ev_float, "ammo_lava_nails"},
1161 {ev_float, "ammo_rockets1"},
1162 {ev_float, "ammo_multi_rockets"},
1163 {ev_float, "ammo_cells1"},
1164 {ev_float, "ammo_plasma"},
1165 {ev_float, "idealpitch"},
1166 {ev_float, "pitch_speed"},
1167 {ev_entity, "viewmodelforclient"},
1168 {ev_entity, "nodrawtoclient"},
1169 {ev_entity, "exteriormodeltoclient"},
1170 {ev_entity, "drawonlytoclient"},
1172 {ev_vector, "movement"},
1173 {ev_float, "pmodel"},
1174 {ev_vector, "punchvector"}
1182 void PR_LoadProgs (void)
1186 ddef_t *infielddefs;
1189 // flush the non-C variable lookup cache
1190 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1191 gefvCache[i].field[0] = 0;
1193 Mem_EmptyPool(progs_mempool);
1194 Mem_EmptyPool(edictstring_mempool);
1196 temp = COM_LoadFile ("progs.dat", false);
1198 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1200 progs = (dprograms_t *)Mem_Alloc(progs_mempool, com_filesize);
1202 memcpy(progs, temp, com_filesize);
1205 Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024);
1207 pr_crc = CRC_Block((byte *)progs, com_filesize);
1209 // byte swap the header
1210 for (i=0 ; i<sizeof(*progs)/4 ; i++)
1211 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1213 if (progs->version != PROG_VERSION)
1214 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1215 if (progs->crc != PROGHEADER_CRC)
1216 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1218 pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
1219 pr_strings = (char *)progs + progs->ofs_strings;
1220 pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
1222 // we need to expand the fielddefs list to include all the engine fields,
1223 // so allocate a new place for it
1224 infielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
1225 pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1227 pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
1229 // moved edict_size calculation down below field adding code
1231 pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);
1232 pr_globals = (float *)pr_global_struct;
1234 // byte swap the lumps
1235 for (i=0 ; i<progs->numstatements ; i++)
1237 pr_statements[i].op = LittleShort(pr_statements[i].op);
1238 pr_statements[i].a = LittleShort(pr_statements[i].a);
1239 pr_statements[i].b = LittleShort(pr_statements[i].b);
1240 pr_statements[i].c = LittleShort(pr_statements[i].c);
1243 for (i=0 ; i<progs->numfunctions; i++)
1245 pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
1246 pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
1247 pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
1248 pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
1249 pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
1250 pr_functions[i].locals = LittleLong (pr_functions[i].locals);
1253 for (i=0 ; i<progs->numglobaldefs ; i++)
1255 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1256 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1257 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1260 // copy the progs fields to the new fields list
1261 for (i = 0;i < progs->numfielddefs;i++)
1263 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1264 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1265 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1266 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1267 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1270 // append the darkplaces fields
1271 for (i = 0;i < DPFIELDS;i++)
1273 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1274 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1275 pr_fielddefs[progs->numfielddefs].s_name = dpfields[i].string - pr_strings;
1276 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1277 progs->entityfields += 3;
1279 progs->entityfields++;
1280 progs->numfielddefs++;
1283 for (i=0 ; i<progs->numglobals ; i++)
1284 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1286 // moved edict_size calculation down here, below field adding code
1287 pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
1289 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1291 // LordHavoc: bounds check anything static
1292 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1298 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1299 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1302 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1303 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1305 // global global global
1340 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1341 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1343 // global none global
1349 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1350 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1366 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1367 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1381 if ((unsigned short) st->a >= progs->numglobals)
1382 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1385 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1390 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1394 void PR_Fields_f (void)
1399 Con_Printf("no progs loaded\n");
1402 for (i = 0;i < progs->numfielddefs;i++)
1403 Con_Printf("%s\n", (pr_strings + pr_fielddefs[i].s_name));
1404 Con_Printf("%i entity fields, totalling %i bytes per edict, %i edicts, %i bytes total spent on edict fields\n", progs->entityfields, progs->entityfields * 4, MAX_EDICTS, progs->entityfields * 4 * MAX_EDICTS);
1407 void PR_Globals_f (void)
1412 Con_Printf("no progs loaded\n");
1415 for (i = 0;i < progs->numglobaldefs;i++)
1416 Con_Printf("%s\n", (pr_strings + pr_globaldefs[i].s_name));
1417 Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1427 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1428 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1429 Cmd_AddCommand ("edictcount", ED_Count);
1430 Cmd_AddCommand ("profile", PR_Profile_f);
1431 Cmd_AddCommand ("pr_fields", PR_Fields_f);
1432 Cmd_AddCommand ("pr_globals", PR_Globals_f);
1433 Cvar_RegisterVariable (&pr_checkextension);
1434 Cvar_RegisterVariable (&nomonsters);
1435 Cvar_RegisterVariable (&gamecfg);
1436 Cvar_RegisterVariable (&scratch1);
1437 Cvar_RegisterVariable (&scratch2);
1438 Cvar_RegisterVariable (&scratch3);
1439 Cvar_RegisterVariable (&scratch4);
1440 Cvar_RegisterVariable (&savedgamecfg);
1441 Cvar_RegisterVariable (&saved1);
1442 Cvar_RegisterVariable (&saved2);
1443 Cvar_RegisterVariable (&saved3);
1444 Cvar_RegisterVariable (&saved4);
1445 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1446 Cvar_RegisterVariable (&decors);
1447 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1448 if (gamemode == GAME_NEHAHRA)
1450 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1451 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1452 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1453 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1454 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1455 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1456 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1457 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1458 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1459 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1461 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1462 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1463 Cvar_RegisterVariable (&pr_boundscheck);
1465 progs_mempool = Mem_AllocPool("progs.dat");
1466 edictstring_mempool = Mem_AllocPool("edict strings");
1469 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1470 edict_t *EDICT_NUM_ERROR(int n)
1472 Host_Error ("EDICT_NUM: bad number %i", n);
1476 edict_t *EDICT_NUM(int n)
1478 if (n < 0 || n >= sv.max_edicts)
1479 Sys_Error ("EDICT_NUM: bad number %i", n);
1480 return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size);
1484 int NUM_FOR_EDICT(edict_t *e)
1488 b = (byte *)e - (byte *)sv.edicts;
1489 b = b / pr_edict_size;
1491 if (b < 0 || b >= sv.num_edicts)
1492 Host_Error ("NUM_FOR_EDICT: bad pointer");
1496 int NoCrash_NUM_FOR_EDICT(edict_t *e)
1500 b = (byte *)e - (byte *)sv.edicts;
1501 b = b / pr_edict_size;