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 extern void SV_IncreaseEdicts(void);
203 edict_t *ED_Alloc (void)
208 for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
211 // the first couple seconds of server time can involve a lot of
212 // freeing and allocating, so relax the replacement policy
213 if (e->e->free && ( e->e->freetime < 2 || sv.time - e->e->freetime > 0.5 ) )
221 Host_Error ("ED_Alloc: no free edicts");
224 if (sv.num_edicts >= sv.max_edicts)
236 Marks the edict as free
237 FIXME: walk all entities and NULL out references to this entity
240 void ED_Free (edict_t *ed)
242 SV_UnlinkEdict (ed); // unlink from world bsp
246 ed->v->takedamage = 0;
247 ed->v->modelindex = 0;
251 VectorClear(ed->v->origin);
252 VectorClear(ed->v->angles);
253 ed->v->nextthink = -1;
256 ed->e->freetime = sv.time;
259 //===========================================================================
266 ddef_t *ED_GlobalAtOfs (int ofs)
271 for (i=0 ; i<progs->numglobaldefs ; i++)
273 def = &pr_globaldefs[i];
285 ddef_t *ED_FieldAtOfs (int ofs)
290 for (i=0 ; i<progs->numfielddefs ; i++)
292 def = &pr_fielddefs[i];
304 ddef_t *ED_FindField (const char *name)
309 for (i=0 ; i<progs->numfielddefs ; i++)
311 def = &pr_fielddefs[i];
312 if (!strcmp(PR_GetString(def->s_name), name))
323 ddef_t *ED_FindGlobal (const char *name)
328 for (i=0 ; i<progs->numglobaldefs ; i++)
330 def = &pr_globaldefs[i];
331 if (!strcmp(PR_GetString(def->s_name), name))
343 mfunction_t *ED_FindFunction (const char *name)
348 for (i=0 ; i<progs->numfunctions ; i++)
350 func = &pr_functions[i];
351 if (!strcmp(PR_GetString(func->s_name), name))
362 Returns a string describing *data in a type specific manner
365 int NoCrash_NUM_FOR_EDICT(edict_t *e);
366 char *PR_ValueString (etype_t type, eval_t *val)
368 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
373 type &= ~DEF_SAVEGLOBAL;
378 sprintf (line, "%s", PR_GetString(val->string));
381 //n = NoCrash_NUM_FOR_EDICT(PROG_TO_EDICT(val->edict));
383 if (n < 0 || n >= MAX_EDICTS)
384 sprintf (line, "entity %i (invalid!)", n);
386 sprintf (line, "entity %i", n);
389 f = pr_functions + val->function;
390 sprintf (line, "%s()", PR_GetString(f->s_name));
393 def = ED_FieldAtOfs ( val->_int );
394 sprintf (line, ".%s", PR_GetString(def->s_name));
397 sprintf (line, "void");
400 // LordHavoc: changed from %5.1f to %10.4f
401 sprintf (line, "%10.4f", val->_float);
404 // LordHavoc: changed from %5.1f to %10.4f
405 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
408 sprintf (line, "pointer");
411 sprintf (line, "bad type %i", type);
422 Returns a string describing *data in a type specific manner
423 Easier to parse than PR_ValueString
426 char *PR_UglyValueString (etype_t type, eval_t *val)
428 static char line[4096];
434 type &= ~DEF_SAVEGLOBAL;
439 sprintf (line, "%s", PR_GetString(val->string));
442 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
445 f = pr_functions + val->function;
446 sprintf (line, "%s", PR_GetString(f->s_name));
449 def = ED_FieldAtOfs ( val->_int );
450 // LordHavoc: parse the string a bit to turn special characters
451 // (like newline, specifically) into escape codes,
452 // this fixes saving games from various mods
453 //sprintf (line, "%s", PR_GetString(def->s_name));
454 s = PR_GetString(def->s_name);
455 for (i = 0;i < 4095 && *s;)
474 sprintf (line, "void");
477 sprintf (line, "%f", val->_float);
480 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
483 sprintf (line, "bad type %i", type);
494 Returns a string with a description and the contents of a global,
495 padded to 20 field width
498 char *PR_GlobalString (int ofs)
504 static char line[128];
506 val = (void *)&pr_globals[ofs];
507 def = ED_GlobalAtOfs(ofs);
509 sprintf (line,"%i(?)", ofs);
512 s = PR_ValueString (def->type, val);
513 sprintf (line,"%i(%s)%s", ofs, PR_GetString(def->s_name), s);
524 char *PR_GlobalStringNoContents (int ofs)
528 static char line[128];
530 def = ED_GlobalAtOfs(ofs);
532 sprintf (line,"%i(?)", ofs);
534 sprintf (line,"%i(%s)", ofs, PR_GetString(def->s_name));
552 // LordHavoc: optimized this to print out much more quickly (tempstring)
553 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
554 void ED_Print (edict_t *ed)
562 char tempstring[8192], tempstring2[260]; // temporary string buffers
566 Con_Printf ("FREE\n");
571 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
572 for (i=1 ; i<progs->numfielddefs ; i++)
574 d = &pr_fielddefs[i];
575 name = PR_GetString(d->s_name);
576 if (name[strlen(name)-2] == '_')
577 continue; // skip _x, _y, _z vars
579 v = (int *)((char *)ed->v + d->ofs*4);
581 // if the value is still all 0, skip the field
582 type = d->type & ~DEF_SAVEGLOBAL;
584 for (j=0 ; j<type_size[type] ; j++)
587 if (j == type_size[type])
590 if (strlen(name) > 256)
592 strncpy(tempstring2, name, 256);
593 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
594 tempstring2[259] = 0;
597 strcat(tempstring, name);
598 for (l = strlen(name);l < 14;l++)
599 strcat(tempstring, " ");
600 strcat(tempstring, " ");
602 name = PR_ValueString(d->type, (eval_t *)v);
603 if (strlen(name) > 256)
605 strncpy(tempstring2, name, 256);
606 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
607 tempstring2[259] = 0;
610 strcat(tempstring, name);
611 strcat(tempstring, "\n");
612 if (strlen(tempstring) >= 4096)
614 Con_Printf("%s", tempstring);
619 Con_Printf("%s", tempstring);
629 void ED_Write (qfile_t *f, edict_t *ed)
637 FS_Printf (f, "{\n");
641 FS_Printf (f, "}\n");
645 for (i=1 ; i<progs->numfielddefs ; i++)
647 d = &pr_fielddefs[i];
648 name = PR_GetString(d->s_name);
649 if (name[strlen(name)-2] == '_')
650 continue; // skip _x, _y, _z vars
652 v = (int *)((char *)ed->v + d->ofs*4);
654 // if the value is still all 0, skip the field
655 type = d->type & ~DEF_SAVEGLOBAL;
656 for (j=0 ; j<type_size[type] ; j++)
659 if (j == type_size[type])
662 FS_Printf (f,"\"%s\" ",name);
663 FS_Printf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
666 FS_Printf (f, "}\n");
669 void ED_PrintNum (int ent)
671 ED_Print (EDICT_NUM(ent));
678 For debugging, prints all the entities in the current server
681 void ED_PrintEdicts (void)
685 Con_Printf ("%i entities\n", sv.num_edicts);
686 for (i=0 ; i<sv.num_edicts ; i++)
694 For debugging, prints a single edict
697 void ED_PrintEdict_f (void)
701 i = atoi (Cmd_Argv(1));
702 if (i >= sv.num_edicts)
704 Con_Printf("Bad edict number\n");
721 int active, models, solid, step;
723 active = models = solid = step = 0;
724 for (i=0 ; i<sv.num_edicts ; i++)
734 if (ent->v->movetype == MOVETYPE_STEP)
738 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
739 Con_Printf ("active :%3i\n", active);
740 Con_Printf ("view :%3i\n", models);
741 Con_Printf ("touch :%3i\n", solid);
742 Con_Printf ("step :%3i\n", step);
747 ==============================================================================
751 FIXME: need to tag constants, doesn't really work
752 ==============================================================================
760 void ED_WriteGlobals (qfile_t *f)
768 for (i=0 ; i<progs->numglobaldefs ; i++)
770 def = &pr_globaldefs[i];
772 if ( !(def->type & DEF_SAVEGLOBAL) )
774 type &= ~DEF_SAVEGLOBAL;
776 if (type != ev_string && type != ev_float && type != ev_entity)
779 name = PR_GetString(def->s_name);
780 FS_Printf (f,"\"%s\" ", name);
781 FS_Printf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
791 void ED_ParseGlobals (const char *data)
793 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
799 if (!COM_ParseToken (&data))
800 Host_Error ("ED_ParseEntity: EOF without closing brace");
801 if (com_token[0] == '}')
804 strcpy (keyname, com_token);
807 if (!COM_ParseToken (&data))
808 Host_Error ("ED_ParseEntity: EOF without closing brace");
810 if (com_token[0] == '}')
811 Host_Error ("ED_ParseEntity: closing brace without data");
813 key = ED_FindGlobal (keyname);
816 Con_DPrintf ("'%s' is not a global\n", keyname);
820 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
821 Host_Error ("ED_ParseGlobals: parse error");
825 //============================================================================
833 char *ED_NewString (const char *string)
838 l = strlen(string) + 1;
839 new = Mem_Alloc(edictstring_mempool, l);
842 for (i=0 ; i< l ; i++)
844 if (string[i] == '\\' && i < l-1)
847 if (string[i] == 'n')
853 *new_p++ = string[i];
864 Can parse either fields or globals
865 returns false if error
868 qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s)
877 d = (void *)((int *)base + key->ofs);
879 switch (key->type & ~DEF_SAVEGLOBAL)
882 *(string_t *)d = PR_SetString(ED_NewString(s));
886 *(float *)d = atof (s);
893 for (i=0 ; i<3 ; i++)
895 while (*v && *v != ' ')
898 ((float *)d)[i] = atof (w);
904 *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
908 def = ED_FindField (s);
911 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
912 if (strcmp(s, "sky") && strcmp(s, "fog") && strncmp(s, "fog_", 4) && strcmp(s, "farclip"))
913 Con_DPrintf ("Can't find field %s\n", s);
916 *(int *)d = G_INT(def->ofs);
920 func = ED_FindFunction (s);
923 Con_DPrintf ("Can't find function %s\n", s);
926 *(func_t *)d = func - pr_functions;
939 Parses an edict out of the given string, returning the new position
940 ed should be a properly initialized empty edict.
941 Used for initial level load and for savegames.
944 const char *ED_ParseEdict (const char *data, edict_t *ent)
955 if (ent != sv.edicts) // hack
956 memset (ent->v, 0, progs->entityfields * 4);
958 // go through all the dictionary pairs
962 if (!COM_ParseToken (&data))
963 Host_Error ("ED_ParseEntity: EOF without closing brace");
964 if (com_token[0] == '}')
967 // anglehack is to allow QuakeEd to write single scalar angles
968 // and allow them to be turned into vectors. (FIXME...)
969 if (!strcmp(com_token, "angle"))
971 strcpy (com_token, "angles");
977 // FIXME: change light to _light to get rid of this hack
978 if (!strcmp(com_token, "light"))
979 strcpy (com_token, "light_lev"); // hack for single light def
981 strcpy (keyname, com_token);
983 // another hack to fix heynames with trailing spaces
985 while (n && keyname[n-1] == ' ')
992 if (!COM_ParseToken (&data))
993 Host_Error ("ED_ParseEntity: EOF without closing brace");
995 if (com_token[0] == '}')
996 Host_Error ("ED_ParseEntity: closing brace without data");
1000 // keynames with a leading underscore are used for utility comments,
1001 // and are immediately discarded by quake
1002 if (keyname[0] == '_')
1005 key = ED_FindField (keyname);
1008 Con_DPrintf ("'%s' is not a field\n", keyname);
1015 strcpy (temp, com_token);
1016 sprintf (com_token, "0 %s 0", temp);
1019 if (!ED_ParseEpair ((void *)ent->v, key, com_token))
1020 Host_Error ("ED_ParseEdict: parse error");
1024 ent->e->free = true;
1034 The entities are directly placed in the array, rather than allocated with
1035 ED_Alloc, because otherwise an error loading the map would have entity
1036 number references out of order.
1038 Creates a server's entity / program execution context by
1039 parsing textual entity definitions out of an ent file.
1041 Used for both fresh maps and savegame loads. A fresh map would also need
1042 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1045 void ED_LoadFromFile (const char *data)
1048 int parsed, inhibited, spawned, died;
1056 pr_global_struct->time = sv.time;
1061 // parse the opening brace
1062 if (!COM_ParseToken (&data))
1064 if (com_token[0] != '{')
1065 Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1071 data = ED_ParseEdict (data, ent);
1074 // remove things from different skill levels or deathmatch
1075 if (deathmatch.integer)
1077 if (((int)ent->v->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1084 else if ((current_skill == 0 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_EASY ))
1085 || (current_skill == 1 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_MEDIUM))
1086 || (current_skill >= 2 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_HARD )))
1094 // immediately call spawn function
1096 if (!ent->v->classname)
1098 Con_Printf ("No classname for:\n");
1104 // look for the spawn function
1105 func = ED_FindFunction (PR_GetString(ent->v->classname));
1109 if (developer.integer) // don't confuse non-developers with errors
1111 Con_Printf ("No spawn function for:\n");
1118 pr_global_struct->self = EDICT_TO_PROG(ent);
1119 PR_ExecuteProgram (func - pr_functions, "");
1125 Con_DPrintf ("%i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", parsed, inhibited, spawned, died, spawned - died);
1129 typedef struct dpfield_s
1136 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1138 dpfield_t dpfields[] =
1140 {ev_float, "gravity"},
1141 {ev_float, "button3"},
1142 {ev_float, "button4"},
1143 {ev_float, "button5"},
1144 {ev_float, "button6"},
1145 {ev_float, "button7"},
1146 {ev_float, "button8"},
1147 {ev_float, "glow_size"},
1148 {ev_float, "glow_trail"},
1149 {ev_float, "glow_color"},
1150 {ev_float, "items2"},
1151 {ev_float, "scale"},
1152 {ev_float, "alpha"},
1153 {ev_float, "renderamt"},
1154 {ev_float, "rendermode"},
1155 {ev_float, "fullbright"},
1156 {ev_float, "ammo_shells1"},
1157 {ev_float, "ammo_nails1"},
1158 {ev_float, "ammo_lava_nails"},
1159 {ev_float, "ammo_rockets1"},
1160 {ev_float, "ammo_multi_rockets"},
1161 {ev_float, "ammo_cells1"},
1162 {ev_float, "ammo_plasma"},
1163 {ev_float, "idealpitch"},
1164 {ev_float, "pitch_speed"},
1165 {ev_entity, "viewmodelforclient"},
1166 {ev_entity, "nodrawtoclient"},
1167 {ev_entity, "exteriormodeltoclient"},
1168 {ev_entity, "drawonlytoclient"},
1170 {ev_vector, "movement"},
1171 {ev_float, "pmodel"},
1172 {ev_vector, "punchvector"}
1180 extern void PR_Cmd_Reset (void);
1181 void PR_LoadProgs (void)
1185 ddef_t *infielddefs;
1187 dfunction_t *dfunctions;
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 = FS_LoadFile ("progs.dat", false);
1198 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1200 progs = (dprograms_t *)Mem_Alloc(progs_mempool, fs_filesize);
1202 memcpy(progs, temp, fs_filesize);
1205 Con_DPrintf ("Programs occupy %iK.\n", fs_filesize/1024);
1207 pr_crc = CRC_Block((qbyte *)progs, fs_filesize);
1209 // byte swap the header
1210 for (i = 0;i < (int) 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 *)((qbyte *)progs + progs->ofs_functions);
1219 dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1220 pr_strings = (char *)progs + progs->ofs_strings;
1221 pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1223 // we need to expand the fielddefs list to include all the engine fields,
1224 // so allocate a new place for it
1225 infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1226 pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1228 pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1230 // moved edict_size calculation down below field adding code
1232 pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1233 pr_globals = (float *)pr_global_struct;
1235 // byte swap the lumps
1236 for (i=0 ; i<progs->numstatements ; i++)
1238 pr_statements[i].op = LittleShort(pr_statements[i].op);
1239 pr_statements[i].a = LittleShort(pr_statements[i].a);
1240 pr_statements[i].b = LittleShort(pr_statements[i].b);
1241 pr_statements[i].c = LittleShort(pr_statements[i].c);
1244 pr_functions = Mem_Alloc(progs_mempool, sizeof(mfunction_t) * progs->numfunctions);
1245 for (i = 0;i < progs->numfunctions;i++)
1247 pr_functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1248 pr_functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1249 pr_functions[i].s_name = LittleLong (dfunctions[i].s_name);
1250 pr_functions[i].s_file = LittleLong (dfunctions[i].s_file);
1251 pr_functions[i].numparms = LittleLong (dfunctions[i].numparms);
1252 pr_functions[i].locals = LittleLong (dfunctions[i].locals);
1253 memcpy(pr_functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1256 for (i=0 ; i<progs->numglobaldefs ; i++)
1258 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1259 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1260 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1263 // copy the progs fields to the new fields list
1264 for (i = 0;i < progs->numfielddefs;i++)
1266 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1267 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1268 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1269 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1270 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1273 // append the darkplaces fields
1274 for (i = 0;i < (int) DPFIELDS;i++)
1276 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1277 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1278 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1279 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1280 progs->entityfields += 3;
1282 progs->entityfields++;
1283 progs->numfielddefs++;
1286 for (i=0 ; i<progs->numglobals ; i++)
1287 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1289 // moved edict_size calculation down here, below field adding code
1290 // LordHavoc: this no longer includes the edict_t header
1291 pr_edict_size = progs->entityfields * 4;
1292 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1294 // LordHavoc: bounds check anything static
1295 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1301 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1302 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1305 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1306 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1308 // global global global
1343 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1344 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1346 // global none global
1352 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1353 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1369 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1370 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1384 if ((unsigned short) st->a >= progs->numglobals)
1385 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1388 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1393 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1394 PR_Execute_ProgsLoaded();
1399 void PR_Fields_f (void)
1401 int i, j, ednum, used, usedamount;
1403 char tempstring[5000], tempstring2[260], *name;
1409 Con_Printf("no progs loaded\n");
1412 counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1413 for (ednum = 0;ednum < MAX_EDICTS;ednum++)
1415 ed = EDICT_NUM(ednum);
1418 for (i = 1;i < progs->numfielddefs;i++)
1420 d = &pr_fielddefs[i];
1421 name = PR_GetString(d->s_name);
1422 if (name[strlen(name)-2] == '_')
1423 continue; // skip _x, _y, _z vars
1424 v = (int *)((char *)ed->v + d->ofs*4);
1425 // if the value is still all 0, skip the field
1426 for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1439 for (i = 0;i < progs->numfielddefs;i++)
1441 d = &pr_fielddefs[i];
1442 name = PR_GetString(d->s_name);
1443 if (name[strlen(name)-2] == '_')
1444 continue; // skip _x, _y, _z vars
1445 switch(d->type & ~DEF_SAVEGLOBAL)
1448 strcat(tempstring, "string ");
1451 strcat(tempstring, "entity ");
1454 strcat(tempstring, "function ");
1457 strcat(tempstring, "field ");
1460 strcat(tempstring, "void ");
1463 strcat(tempstring, "float ");
1466 strcat(tempstring, "vector ");
1469 strcat(tempstring, "pointer ");
1472 sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1473 strcat(tempstring, tempstring2);
1476 if (strlen(name) > 256)
1478 strncpy(tempstring2, name, 256);
1479 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1480 tempstring2[259] = 0;
1483 strcat(tempstring, name);
1484 for (j = strlen(name);j < 25;j++)
1485 strcat(tempstring, " ");
1486 sprintf(tempstring2, "%5d", counts[i]);
1487 strcat(tempstring, tempstring2);
1488 strcat(tempstring, "\n");
1489 if (strlen(tempstring) >= 4096)
1491 Con_Printf("%s", tempstring);
1497 usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1501 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);
1504 void PR_Globals_f (void)
1509 Con_Printf("no progs loaded\n");
1512 for (i = 0;i < progs->numglobaldefs;i++)
1513 Con_Printf("%s\n", PR_GetString(pr_globaldefs[i].s_name));
1514 Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1522 extern void PR_Cmd_Init(void);
1525 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1526 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1527 Cmd_AddCommand ("edictcount", ED_Count);
1528 Cmd_AddCommand ("profile", PR_Profile_f);
1529 Cmd_AddCommand ("pr_fields", PR_Fields_f);
1530 Cmd_AddCommand ("pr_globals", PR_Globals_f);
1531 Cvar_RegisterVariable (&pr_checkextension);
1532 Cvar_RegisterVariable (&nomonsters);
1533 Cvar_RegisterVariable (&gamecfg);
1534 Cvar_RegisterVariable (&scratch1);
1535 Cvar_RegisterVariable (&scratch2);
1536 Cvar_RegisterVariable (&scratch3);
1537 Cvar_RegisterVariable (&scratch4);
1538 Cvar_RegisterVariable (&savedgamecfg);
1539 Cvar_RegisterVariable (&saved1);
1540 Cvar_RegisterVariable (&saved2);
1541 Cvar_RegisterVariable (&saved3);
1542 Cvar_RegisterVariable (&saved4);
1543 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1544 Cvar_RegisterVariable (&decors);
1545 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1546 if (gamemode == GAME_NEHAHRA)
1548 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1549 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1550 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1551 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1552 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1553 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1554 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1555 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1556 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1557 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1559 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1560 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1561 Cvar_RegisterVariable (&pr_boundscheck);
1562 Cvar_RegisterVariable (&pr_traceqc);
1564 progs_mempool = Mem_AllocPool("progs.dat");
1565 edictstring_mempool = Mem_AllocPool("edict strings");
1570 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1571 edict_t *EDICT_NUM_ERROR(int n, char *filename, int fileline)
1573 Host_Error ("EDICT_NUM: bad number %i (called at %f:%i)", n, filename, fileline);
1578 int NUM_FOR_EDICT_ERROR(edict_t *e)
1580 Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1584 int NUM_FOR_EDICT(edict_t *e)
1588 if ((unsigned int)n >= MAX_EDICTS)
1589 Host_Error ("NUM_FOR_EDICT: bad pointer");
1593 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1595 // return e - sv.edicts;
1598 //#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1599 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1600 int EDICT_TO_PROG(edict_t *e)
1604 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1605 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1606 return n;// EXPERIMENTAL
1607 //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1609 edict_t *PROG_TO_EDICT(int n)
1611 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1612 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1613 return sv.edicts + n; // EXPERIMENTAL
1614 //return sv.edicts + ((n) / (progs->entityfields * 4));