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;
125 //KrimZon - SERVER COMMANDS IN QUAKEC
126 mfunction_t *SV_ParseClientCommandQC;
128 int FindFieldOffset(const char *field)
131 d = ED_FindField(field);
137 void FindEdictFieldOffsets(void)
139 eval_gravity = FindFieldOffset("gravity");
140 eval_button3 = FindFieldOffset("button3");
141 eval_button4 = FindFieldOffset("button4");
142 eval_button5 = FindFieldOffset("button5");
143 eval_button6 = FindFieldOffset("button6");
144 eval_button7 = FindFieldOffset("button7");
145 eval_button8 = FindFieldOffset("button8");
146 eval_glow_size = FindFieldOffset("glow_size");
147 eval_glow_trail = FindFieldOffset("glow_trail");
148 eval_glow_color = FindFieldOffset("glow_color");
149 eval_items2 = FindFieldOffset("items2");
150 eval_scale = FindFieldOffset("scale");
151 eval_alpha = FindFieldOffset("alpha");
152 eval_renderamt = FindFieldOffset("renderamt"); // HalfLife support
153 eval_rendermode = FindFieldOffset("rendermode"); // HalfLife support
154 eval_fullbright = FindFieldOffset("fullbright");
155 eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
156 eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
157 eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
158 eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
159 eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
160 eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
161 eval_ammo_plasma = FindFieldOffset("ammo_plasma");
162 eval_idealpitch = FindFieldOffset("idealpitch");
163 eval_pitch_speed = FindFieldOffset("pitch_speed");
164 eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
165 eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
166 eval_exteriormodeltoclient = FindFieldOffset("exteriormodeltoclient");
167 eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
168 eval_ping = FindFieldOffset("ping");
169 eval_movement = FindFieldOffset("movement");
170 eval_pmodel = FindFieldOffset("pmodel");
171 eval_punchvector = FindFieldOffset("punchvector");
172 eval_viewzoom = FindFieldOffset("viewzoom");
174 // LordHavoc: allowing QuakeC to override the player movement code
175 SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
176 // LordHavoc: support for endframe
177 EndFrameQC = ED_FindFunction ("EndFrame");
178 //KrimZon - SERVER COMMANDS IN QUAKEC
179 SV_ParseClientCommandQC = ED_FindFunction ("SV_ParseClientCommand");
186 Sets everything to NULL
189 void ED_ClearEdict (edict_t *e)
191 memset (e->v, 0, progs->entityfields * 4);
199 Either finds a free edict, or allocates a new one.
200 Try to avoid reusing an entity that was recently freed, because it
201 can cause the client to think the entity morphed into something else
202 instead of being removed and recreated, which can cause interpolated
203 angles and bad trails.
206 edict_t *ED_Alloc (void)
211 for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
214 // the first couple seconds of server time can involve a lot of
215 // freeing and allocating, so relax the replacement policy
216 if (e->e->free && ( e->e->freetime < 2 || sv.time - e->e->freetime > 0.5 ) )
224 Host_Error ("ED_Alloc: no free edicts");
227 if (sv.num_edicts >= sv.max_edicts)
239 Marks the edict as free
240 FIXME: walk all entities and NULL out references to this entity
243 void ED_Free (edict_t *ed)
245 SV_UnlinkEdict (ed); // unlink from world bsp
249 ed->v->takedamage = 0;
250 ed->v->modelindex = 0;
254 VectorClear(ed->v->origin);
255 VectorClear(ed->v->angles);
256 ed->v->nextthink = -1;
259 ed->e->freetime = sv.time;
262 //===========================================================================
269 ddef_t *ED_GlobalAtOfs (int ofs)
274 for (i=0 ; i<progs->numglobaldefs ; i++)
276 def = &pr_globaldefs[i];
288 ddef_t *ED_FieldAtOfs (int ofs)
293 for (i=0 ; i<progs->numfielddefs ; i++)
295 def = &pr_fielddefs[i];
307 ddef_t *ED_FindField (const char *name)
312 for (i=0 ; i<progs->numfielddefs ; i++)
314 def = &pr_fielddefs[i];
315 if (!strcmp(PR_GetString(def->s_name), name))
326 ddef_t *ED_FindGlobal (const char *name)
331 for (i=0 ; i<progs->numglobaldefs ; i++)
333 def = &pr_globaldefs[i];
334 if (!strcmp(PR_GetString(def->s_name), name))
346 mfunction_t *ED_FindFunction (const char *name)
351 for (i=0 ; i<progs->numfunctions ; i++)
353 func = &pr_functions[i];
354 if (!strcmp(PR_GetString(func->s_name), name))
365 Returns a string describing *data in a type specific manner
368 int NoCrash_NUM_FOR_EDICT(edict_t *e);
369 char *PR_ValueString (etype_t type, eval_t *val)
371 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
376 type &= ~DEF_SAVEGLOBAL;
381 sprintf (line, "%s", PR_GetString(val->string));
384 //n = NoCrash_NUM_FOR_EDICT(PROG_TO_EDICT(val->edict));
386 if (n < 0 || n >= MAX_EDICTS)
387 sprintf (line, "entity %i (invalid!)", n);
389 sprintf (line, "entity %i", n);
392 f = pr_functions + val->function;
393 sprintf (line, "%s()", PR_GetString(f->s_name));
396 def = ED_FieldAtOfs ( val->_int );
397 sprintf (line, ".%s", PR_GetString(def->s_name));
400 sprintf (line, "void");
403 // LordHavoc: changed from %5.1f to %10.4f
404 sprintf (line, "%10.4f", val->_float);
407 // LordHavoc: changed from %5.1f to %10.4f
408 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
411 sprintf (line, "pointer");
414 sprintf (line, "bad type %i", type);
425 Returns a string describing *data in a type specific manner
426 Easier to parse than PR_ValueString
429 char *PR_UglyValueString (etype_t type, eval_t *val)
431 static char line[4096];
437 type &= ~DEF_SAVEGLOBAL;
442 sprintf (line, "%s", PR_GetString(val->string));
445 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
448 f = pr_functions + val->function;
449 sprintf (line, "%s", PR_GetString(f->s_name));
452 def = ED_FieldAtOfs ( val->_int );
453 // LordHavoc: parse the string a bit to turn special characters
454 // (like newline, specifically) into escape codes,
455 // this fixes saving games from various mods
456 //sprintf (line, "%s", PR_GetString(def->s_name));
457 s = PR_GetString(def->s_name);
458 for (i = 0;i < 4095 && *s;)
477 sprintf (line, "void");
480 sprintf (line, "%f", val->_float);
483 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
486 sprintf (line, "bad type %i", type);
497 Returns a string with a description and the contents of a global,
498 padded to 20 field width
501 char *PR_GlobalString (int ofs)
507 static char line[128];
509 val = (void *)&pr_globals[ofs];
510 def = ED_GlobalAtOfs(ofs);
512 sprintf (line,"%i(?)", ofs);
515 s = PR_ValueString (def->type, val);
516 sprintf (line,"%i(%s)%s", ofs, PR_GetString(def->s_name), s);
527 char *PR_GlobalStringNoContents (int ofs)
531 static char line[128];
533 def = ED_GlobalAtOfs(ofs);
535 sprintf (line,"%i(?)", ofs);
537 sprintf (line,"%i(%s)", ofs, PR_GetString(def->s_name));
555 // LordHavoc: optimized this to print out much more quickly (tempstring)
556 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
557 void ED_Print (edict_t *ed)
565 char tempstring[8192], tempstring2[260]; // temporary string buffers
569 Con_Printf ("FREE\n");
574 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
575 for (i=1 ; i<progs->numfielddefs ; i++)
577 d = &pr_fielddefs[i];
578 name = PR_GetString(d->s_name);
579 if (name[strlen(name)-2] == '_')
580 continue; // skip _x, _y, _z vars
582 v = (int *)((char *)ed->v + d->ofs*4);
584 // if the value is still all 0, skip the field
585 type = d->type & ~DEF_SAVEGLOBAL;
587 for (j=0 ; j<type_size[type] ; j++)
590 if (j == type_size[type])
593 if (strlen(name) > 256)
595 strncpy(tempstring2, name, 256);
596 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
597 tempstring2[259] = 0;
600 strcat(tempstring, name);
601 for (l = strlen(name);l < 14;l++)
602 strcat(tempstring, " ");
603 strcat(tempstring, " ");
605 name = PR_ValueString(d->type, (eval_t *)v);
606 if (strlen(name) > 256)
608 strncpy(tempstring2, name, 256);
609 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
610 tempstring2[259] = 0;
613 strcat(tempstring, name);
614 strcat(tempstring, "\n");
615 if (strlen(tempstring) >= 4096)
617 Con_Printf("%s", tempstring);
622 Con_Printf("%s", tempstring);
632 void ED_Write (qfile_t *f, edict_t *ed)
640 FS_Printf (f, "{\n");
644 FS_Printf (f, "}\n");
648 for (i=1 ; i<progs->numfielddefs ; i++)
650 d = &pr_fielddefs[i];
651 name = PR_GetString(d->s_name);
652 if (name[strlen(name)-2] == '_')
653 continue; // skip _x, _y, _z vars
655 v = (int *)((char *)ed->v + d->ofs*4);
657 // if the value is still all 0, skip the field
658 type = d->type & ~DEF_SAVEGLOBAL;
659 for (j=0 ; j<type_size[type] ; j++)
662 if (j == type_size[type])
665 FS_Printf (f,"\"%s\" ",name);
666 FS_Printf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
669 FS_Printf (f, "}\n");
672 void ED_PrintNum (int ent)
674 ED_Print (EDICT_NUM(ent));
681 For debugging, prints all the entities in the current server
684 void ED_PrintEdicts (void)
688 Con_Printf ("%i entities\n", sv.num_edicts);
689 for (i=0 ; i<sv.num_edicts ; i++)
697 For debugging, prints a single edict
700 void ED_PrintEdict_f (void)
704 i = atoi (Cmd_Argv(1));
705 if (i >= sv.num_edicts)
707 Con_Printf("Bad edict number\n");
724 int active, models, solid, step;
726 active = models = solid = step = 0;
727 for (i=0 ; i<sv.num_edicts ; i++)
737 if (ent->v->movetype == MOVETYPE_STEP)
741 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
742 Con_Printf ("active :%3i\n", active);
743 Con_Printf ("view :%3i\n", models);
744 Con_Printf ("touch :%3i\n", solid);
745 Con_Printf ("step :%3i\n", step);
750 ==============================================================================
754 FIXME: need to tag constants, doesn't really work
755 ==============================================================================
763 void ED_WriteGlobals (qfile_t *f)
771 for (i=0 ; i<progs->numglobaldefs ; i++)
773 def = &pr_globaldefs[i];
775 if ( !(def->type & DEF_SAVEGLOBAL) )
777 type &= ~DEF_SAVEGLOBAL;
779 if (type != ev_string && type != ev_float && type != ev_entity)
782 name = PR_GetString(def->s_name);
783 FS_Printf (f,"\"%s\" ", name);
784 FS_Printf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
794 void ED_ParseGlobals (const char *data)
796 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
802 if (!COM_ParseToken (&data))
803 Host_Error ("ED_ParseEntity: EOF without closing brace");
804 if (com_token[0] == '}')
807 strcpy (keyname, com_token);
810 if (!COM_ParseToken (&data))
811 Host_Error ("ED_ParseEntity: EOF without closing brace");
813 if (com_token[0] == '}')
814 Host_Error ("ED_ParseEntity: closing brace without data");
816 key = ED_FindGlobal (keyname);
819 Con_DPrintf ("'%s' is not a global\n", keyname);
823 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
824 Host_Error ("ED_ParseGlobals: parse error");
828 //============================================================================
836 char *ED_NewString (const char *string)
841 l = strlen(string) + 1;
842 new = Mem_Alloc(edictstring_mempool, l);
845 for (i=0 ; i< l ; i++)
847 if (string[i] == '\\' && i < l-1)
850 if (string[i] == 'n')
856 *new_p++ = string[i];
867 Can parse either fields or globals
868 returns false if error
871 qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s)
880 d = (void *)((int *)base + key->ofs);
882 switch (key->type & ~DEF_SAVEGLOBAL)
885 *(string_t *)d = PR_SetString(ED_NewString(s));
889 *(float *)d = atof (s);
896 for (i=0 ; i<3 ; i++)
898 while (*v && *v != ' ')
901 ((float *)d)[i] = atof (w);
908 if (i < 0 || i >= MAX_EDICTS)
909 Con_DPrintf("ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i)\n", i, MAX_EDICTS);
910 while (i >= sv.max_edicts)
912 *(int *)d = EDICT_TO_PROG(EDICT_NUM(i));
916 def = ED_FindField (s);
919 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
920 if (strcmp(s, "sky") && strcmp(s, "fog") && strncmp(s, "fog_", 4) && strcmp(s, "farclip"))
921 Con_DPrintf ("Can't find field %s\n", s);
924 *(int *)d = G_INT(def->ofs);
928 func = ED_FindFunction (s);
931 Con_DPrintf ("Can't find function %s\n", s);
934 *(func_t *)d = func - pr_functions;
947 Parses an edict out of the given string, returning the new position
948 ed should be a properly initialized empty edict.
949 Used for initial level load and for savegames.
952 const char *ED_ParseEdict (const char *data, edict_t *ent)
963 if (ent != sv.edicts) // hack
964 memset (ent->v, 0, progs->entityfields * 4);
966 // go through all the dictionary pairs
970 if (!COM_ParseToken (&data))
971 Host_Error ("ED_ParseEntity: EOF without closing brace");
972 if (com_token[0] == '}')
975 // anglehack is to allow QuakeEd to write single scalar angles
976 // and allow them to be turned into vectors. (FIXME...)
977 if (!strcmp(com_token, "angle"))
979 strcpy (com_token, "angles");
985 // FIXME: change light to _light to get rid of this hack
986 if (!strcmp(com_token, "light"))
987 strcpy (com_token, "light_lev"); // hack for single light def
989 strcpy (keyname, com_token);
991 // another hack to fix heynames with trailing spaces
993 while (n && keyname[n-1] == ' ')
1000 if (!COM_ParseToken (&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");
1032 ent->e->free = true;
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 (const char *data)
1056 int parsed, inhibited, spawned, died;
1064 pr_global_struct->time = sv.time;
1069 // parse the opening brace
1070 if (!COM_ParseToken (&data))
1072 if (com_token[0] != '{')
1073 Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1079 data = ED_ParseEdict (data, ent);
1082 // remove things from different skill levels or deathmatch
1083 if (deathmatch.integer)
1085 if (((int)ent->v->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1092 else if ((current_skill == 0 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_EASY ))
1093 || (current_skill == 1 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_MEDIUM))
1094 || (current_skill >= 2 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_HARD )))
1102 // immediately call spawn function
1104 if (!ent->v->classname)
1106 Con_Printf ("No classname for:\n");
1112 // look for the spawn function
1113 func = ED_FindFunction (PR_GetString(ent->v->classname));
1117 if (developer.integer) // don't confuse non-developers with errors
1119 Con_Printf ("No spawn function for:\n");
1126 pr_global_struct->self = EDICT_TO_PROG(ent);
1127 PR_ExecuteProgram (func - pr_functions, "");
1133 Con_DPrintf ("%i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", parsed, inhibited, spawned, died, spawned - died);
1137 typedef struct dpfield_s
1144 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1146 dpfield_t dpfields[] =
1148 {ev_float, "gravity"},
1149 {ev_float, "button3"},
1150 {ev_float, "button4"},
1151 {ev_float, "button5"},
1152 {ev_float, "button6"},
1153 {ev_float, "button7"},
1154 {ev_float, "button8"},
1155 {ev_float, "glow_size"},
1156 {ev_float, "glow_trail"},
1157 {ev_float, "glow_color"},
1158 {ev_float, "items2"},
1159 {ev_float, "scale"},
1160 {ev_float, "alpha"},
1161 {ev_float, "renderamt"},
1162 {ev_float, "rendermode"},
1163 {ev_float, "fullbright"},
1164 {ev_float, "ammo_shells1"},
1165 {ev_float, "ammo_nails1"},
1166 {ev_float, "ammo_lava_nails"},
1167 {ev_float, "ammo_rockets1"},
1168 {ev_float, "ammo_multi_rockets"},
1169 {ev_float, "ammo_cells1"},
1170 {ev_float, "ammo_plasma"},
1171 {ev_float, "idealpitch"},
1172 {ev_float, "pitch_speed"},
1173 {ev_entity, "viewmodelforclient"},
1174 {ev_entity, "nodrawtoclient"},
1175 {ev_entity, "exteriormodeltoclient"},
1176 {ev_entity, "drawonlytoclient"},
1178 {ev_vector, "movement"},
1179 {ev_float, "pmodel"},
1180 {ev_vector, "punchvector"}
1188 extern void PR_Cmd_Reset (void);
1189 void PR_LoadProgs (void)
1193 ddef_t *infielddefs;
1195 dfunction_t *dfunctions;
1197 // flush the non-C variable lookup cache
1198 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1199 gefvCache[i].field[0] = 0;
1201 Mem_EmptyPool(progs_mempool);
1202 Mem_EmptyPool(edictstring_mempool);
1204 temp = FS_LoadFile ("progs.dat", false);
1206 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1208 progs = (dprograms_t *)Mem_Alloc(progs_mempool, fs_filesize);
1210 memcpy(progs, temp, fs_filesize);
1213 Con_DPrintf ("Programs occupy %iK.\n", fs_filesize/1024);
1215 pr_crc = CRC_Block((qbyte *)progs, fs_filesize);
1217 // byte swap the header
1218 for (i = 0;i < (int) sizeof(*progs) / 4;i++)
1219 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1221 if (progs->version != PROG_VERSION)
1222 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1223 if (progs->crc != PROGHEADER_CRC)
1224 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1226 //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1227 dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1228 pr_strings = (char *)progs + progs->ofs_strings;
1229 pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1231 // we need to expand the fielddefs list to include all the engine fields,
1232 // so allocate a new place for it
1233 infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1234 pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1236 pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1238 // moved edict_size calculation down below field adding code
1240 pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1241 pr_globals = (float *)pr_global_struct;
1243 // byte swap the lumps
1244 for (i=0 ; i<progs->numstatements ; i++)
1246 pr_statements[i].op = LittleShort(pr_statements[i].op);
1247 pr_statements[i].a = LittleShort(pr_statements[i].a);
1248 pr_statements[i].b = LittleShort(pr_statements[i].b);
1249 pr_statements[i].c = LittleShort(pr_statements[i].c);
1252 pr_functions = Mem_Alloc(progs_mempool, sizeof(mfunction_t) * progs->numfunctions);
1253 for (i = 0;i < progs->numfunctions;i++)
1255 pr_functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1256 pr_functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1257 pr_functions[i].s_name = LittleLong (dfunctions[i].s_name);
1258 pr_functions[i].s_file = LittleLong (dfunctions[i].s_file);
1259 pr_functions[i].numparms = LittleLong (dfunctions[i].numparms);
1260 pr_functions[i].locals = LittleLong (dfunctions[i].locals);
1261 memcpy(pr_functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1264 for (i=0 ; i<progs->numglobaldefs ; i++)
1266 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1267 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1268 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1271 // copy the progs fields to the new fields list
1272 for (i = 0;i < progs->numfielddefs;i++)
1274 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1275 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1276 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1277 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1278 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1281 // append the darkplaces fields
1282 for (i = 0;i < (int) DPFIELDS;i++)
1284 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1285 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1286 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1287 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1288 progs->entityfields += 3;
1290 progs->entityfields++;
1291 progs->numfielddefs++;
1294 for (i=0 ; i<progs->numglobals ; i++)
1295 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1297 // moved edict_size calculation down here, below field adding code
1298 // LordHavoc: this no longer includes the edict_t header
1299 pr_edict_size = progs->entityfields * 4;
1300 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1302 // LordHavoc: bounds check anything static
1303 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1309 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1310 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1313 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1314 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1316 // global global global
1351 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1352 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1354 // global none global
1360 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1361 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1377 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1378 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1392 if ((unsigned short) st->a >= progs->numglobals)
1393 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1396 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1401 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1402 PR_Execute_ProgsLoaded();
1407 void PR_Fields_f (void)
1409 int i, j, ednum, used, usedamount;
1411 char tempstring[5000], tempstring2[260], *name;
1417 Con_Printf("no progs loaded\n");
1420 counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1421 for (ednum = 0;ednum < MAX_EDICTS;ednum++)
1423 ed = EDICT_NUM(ednum);
1426 for (i = 1;i < progs->numfielddefs;i++)
1428 d = &pr_fielddefs[i];
1429 name = PR_GetString(d->s_name);
1430 if (name[strlen(name)-2] == '_')
1431 continue; // skip _x, _y, _z vars
1432 v = (int *)((char *)ed->v + d->ofs*4);
1433 // if the value is still all 0, skip the field
1434 for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1447 for (i = 0;i < progs->numfielddefs;i++)
1449 d = &pr_fielddefs[i];
1450 name = PR_GetString(d->s_name);
1451 if (name[strlen(name)-2] == '_')
1452 continue; // skip _x, _y, _z vars
1453 switch(d->type & ~DEF_SAVEGLOBAL)
1456 strcat(tempstring, "string ");
1459 strcat(tempstring, "entity ");
1462 strcat(tempstring, "function ");
1465 strcat(tempstring, "field ");
1468 strcat(tempstring, "void ");
1471 strcat(tempstring, "float ");
1474 strcat(tempstring, "vector ");
1477 strcat(tempstring, "pointer ");
1480 sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1481 strcat(tempstring, tempstring2);
1484 if (strlen(name) > 256)
1486 strncpy(tempstring2, name, 256);
1487 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1488 tempstring2[259] = 0;
1491 strcat(tempstring, name);
1492 for (j = strlen(name);j < 25;j++)
1493 strcat(tempstring, " ");
1494 sprintf(tempstring2, "%5d", counts[i]);
1495 strcat(tempstring, tempstring2);
1496 strcat(tempstring, "\n");
1497 if (strlen(tempstring) >= 4096)
1499 Con_Printf("%s", tempstring);
1505 usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1509 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);
1512 void PR_Globals_f (void)
1517 Con_Printf("no progs loaded\n");
1520 for (i = 0;i < progs->numglobaldefs;i++)
1521 Con_Printf("%s\n", PR_GetString(pr_globaldefs[i].s_name));
1522 Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1530 extern void PR_Cmd_Init(void);
1533 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1534 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1535 Cmd_AddCommand ("edictcount", ED_Count);
1536 Cmd_AddCommand ("profile", PR_Profile_f);
1537 Cmd_AddCommand ("pr_fields", PR_Fields_f);
1538 Cmd_AddCommand ("pr_globals", PR_Globals_f);
1539 Cvar_RegisterVariable (&pr_checkextension);
1540 Cvar_RegisterVariable (&nomonsters);
1541 Cvar_RegisterVariable (&gamecfg);
1542 Cvar_RegisterVariable (&scratch1);
1543 Cvar_RegisterVariable (&scratch2);
1544 Cvar_RegisterVariable (&scratch3);
1545 Cvar_RegisterVariable (&scratch4);
1546 Cvar_RegisterVariable (&savedgamecfg);
1547 Cvar_RegisterVariable (&saved1);
1548 Cvar_RegisterVariable (&saved2);
1549 Cvar_RegisterVariable (&saved3);
1550 Cvar_RegisterVariable (&saved4);
1551 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1552 Cvar_RegisterVariable (&decors);
1553 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1554 if (gamemode == GAME_NEHAHRA)
1556 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1557 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1558 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1559 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1560 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1561 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1562 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1563 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1564 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1565 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1567 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1568 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1569 Cvar_RegisterVariable (&pr_boundscheck);
1570 Cvar_RegisterVariable (&pr_traceqc);
1572 progs_mempool = Mem_AllocPool("progs.dat");
1573 edictstring_mempool = Mem_AllocPool("edict strings");
1578 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1579 edict_t *EDICT_NUM_ERROR(int n, char *filename, int fileline)
1581 Host_Error ("EDICT_NUM: bad number %i (called at %s:%i)", n, filename, fileline);
1586 int NUM_FOR_EDICT_ERROR(edict_t *e)
1588 Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1592 int NUM_FOR_EDICT(edict_t *e)
1596 if ((unsigned int)n >= MAX_EDICTS)
1597 Host_Error ("NUM_FOR_EDICT: bad pointer");
1601 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1603 // return e - sv.edicts;
1606 //#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1607 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1608 int EDICT_TO_PROG(edict_t *e)
1612 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1613 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1614 return n;// EXPERIMENTAL
1615 //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1617 edict_t *PROG_TO_EDICT(int n)
1619 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1620 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1621 return sv.edicts + n; // EXPERIMENTAL
1622 //return sv.edicts + ((n) / (progs->entityfields * 4));