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;
122 int eval_clientcolors;
124 mfunction_t *SV_PlayerPhysicsQC;
125 mfunction_t *EndFrameQC;
126 //KrimZon - SERVER COMMANDS IN QUAKEC
127 mfunction_t *SV_ParseClientCommandQC;
129 int FindFieldOffset(const char *field)
132 d = ED_FindField(field);
138 void FindEdictFieldOffsets(void)
140 eval_gravity = FindFieldOffset("gravity");
141 eval_button3 = FindFieldOffset("button3");
142 eval_button4 = FindFieldOffset("button4");
143 eval_button5 = FindFieldOffset("button5");
144 eval_button6 = FindFieldOffset("button6");
145 eval_button7 = FindFieldOffset("button7");
146 eval_button8 = FindFieldOffset("button8");
147 eval_glow_size = FindFieldOffset("glow_size");
148 eval_glow_trail = FindFieldOffset("glow_trail");
149 eval_glow_color = FindFieldOffset("glow_color");
150 eval_items2 = FindFieldOffset("items2");
151 eval_scale = FindFieldOffset("scale");
152 eval_alpha = FindFieldOffset("alpha");
153 eval_renderamt = FindFieldOffset("renderamt"); // HalfLife support
154 eval_rendermode = FindFieldOffset("rendermode"); // HalfLife support
155 eval_fullbright = FindFieldOffset("fullbright");
156 eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
157 eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
158 eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
159 eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
160 eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
161 eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
162 eval_ammo_plasma = FindFieldOffset("ammo_plasma");
163 eval_idealpitch = FindFieldOffset("idealpitch");
164 eval_pitch_speed = FindFieldOffset("pitch_speed");
165 eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
166 eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
167 eval_exteriormodeltoclient = FindFieldOffset("exteriormodeltoclient");
168 eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
169 eval_ping = FindFieldOffset("ping");
170 eval_movement = FindFieldOffset("movement");
171 eval_pmodel = FindFieldOffset("pmodel");
172 eval_punchvector = FindFieldOffset("punchvector");
173 eval_viewzoom = FindFieldOffset("viewzoom");
174 eval_clientcolors = FindFieldOffset("clientcolors");
176 // LordHavoc: allowing QuakeC to override the player movement code
177 SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
178 // LordHavoc: support for endframe
179 EndFrameQC = ED_FindFunction ("EndFrame");
180 //KrimZon - SERVER COMMANDS IN QUAKEC
181 SV_ParseClientCommandQC = ED_FindFunction ("SV_ParseClientCommand");
188 Sets everything to NULL
191 void ED_ClearEdict (edict_t *e)
194 memset (e->v, 0, progs->entityfields * 4);
196 // LordHavoc: for consistency set these here
197 num = NUM_FOR_EDICT(e) - 1;
198 if (num >= 0 && num < svs.maxclients)
200 e->v->colormap = num + 1;
201 e->v->team = (svs.clients[num].colors & 15) + 1;
202 e->v->netname = PR_SetString(svs.clients[num].name);
210 Either finds a free edict, or allocates a new one.
211 Try to avoid reusing an entity that was recently freed, because it
212 can cause the client to think the entity morphed into something else
213 instead of being removed and recreated, which can cause interpolated
214 angles and bad trails.
217 edict_t *ED_Alloc (void)
222 for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
225 // the first couple seconds of server time can involve a lot of
226 // freeing and allocating, so relax the replacement policy
227 if (e->e->free && ( e->e->freetime < 2 || sv.time - e->e->freetime > 0.5 ) )
235 Host_Error ("ED_Alloc: no free edicts");
238 if (sv.num_edicts >= sv.max_edicts)
250 Marks the edict as free
251 FIXME: walk all entities and NULL out references to this entity
254 void ED_Free (edict_t *ed)
256 SV_UnlinkEdict (ed); // unlink from world bsp
260 ed->v->takedamage = 0;
261 ed->v->modelindex = 0;
265 VectorClear(ed->v->origin);
266 VectorClear(ed->v->angles);
267 ed->v->nextthink = -1;
270 ed->e->freetime = sv.time;
273 //===========================================================================
280 ddef_t *ED_GlobalAtOfs (int ofs)
285 for (i=0 ; i<progs->numglobaldefs ; i++)
287 def = &pr_globaldefs[i];
299 ddef_t *ED_FieldAtOfs (int ofs)
304 for (i=0 ; i<progs->numfielddefs ; i++)
306 def = &pr_fielddefs[i];
318 ddef_t *ED_FindField (const char *name)
323 for (i=0 ; i<progs->numfielddefs ; i++)
325 def = &pr_fielddefs[i];
326 if (!strcmp(PR_GetString(def->s_name), name))
337 ddef_t *ED_FindGlobal (const char *name)
342 for (i=0 ; i<progs->numglobaldefs ; i++)
344 def = &pr_globaldefs[i];
345 if (!strcmp(PR_GetString(def->s_name), name))
357 mfunction_t *ED_FindFunction (const char *name)
362 for (i=0 ; i<progs->numfunctions ; i++)
364 func = &pr_functions[i];
365 if (!strcmp(PR_GetString(func->s_name), name))
376 Returns a string describing *data in a type specific manner
379 int NoCrash_NUM_FOR_EDICT(edict_t *e);
380 char *PR_ValueString (etype_t type, eval_t *val)
382 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
387 type &= ~DEF_SAVEGLOBAL;
392 sprintf (line, "%s", PR_GetString(val->string));
395 //n = NoCrash_NUM_FOR_EDICT(PROG_TO_EDICT(val->edict));
397 if (n < 0 || n >= MAX_EDICTS)
398 sprintf (line, "entity %i (invalid!)", n);
400 sprintf (line, "entity %i", n);
403 f = pr_functions + val->function;
404 sprintf (line, "%s()", PR_GetString(f->s_name));
407 def = ED_FieldAtOfs ( val->_int );
408 sprintf (line, ".%s", PR_GetString(def->s_name));
411 sprintf (line, "void");
414 // LordHavoc: changed from %5.1f to %10.4f
415 sprintf (line, "%10.4f", val->_float);
418 // LordHavoc: changed from %5.1f to %10.4f
419 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
422 sprintf (line, "pointer");
425 sprintf (line, "bad type %i", type);
436 Returns a string describing *data in a type specific manner
437 Easier to parse than PR_ValueString
440 char *PR_UglyValueString (etype_t type, eval_t *val)
442 static char line[4096];
448 type &= ~DEF_SAVEGLOBAL;
453 sprintf (line, "%s", PR_GetString(val->string));
456 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
459 f = pr_functions + val->function;
460 sprintf (line, "%s", PR_GetString(f->s_name));
463 def = ED_FieldAtOfs ( val->_int );
464 // LordHavoc: parse the string a bit to turn special characters
465 // (like newline, specifically) into escape codes,
466 // this fixes saving games from various mods
467 //sprintf (line, "%s", PR_GetString(def->s_name));
468 s = PR_GetString(def->s_name);
469 for (i = 0;i < 4095 && *s;)
488 sprintf (line, "void");
491 sprintf (line, "%f", val->_float);
494 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
497 sprintf (line, "bad type %i", type);
508 Returns a string with a description and the contents of a global,
509 padded to 20 field width
512 char *PR_GlobalString (int ofs)
518 static char line[128];
520 val = (void *)&pr_globals[ofs];
521 def = ED_GlobalAtOfs(ofs);
523 sprintf (line,"%i(?)", ofs);
526 s = PR_ValueString (def->type, val);
527 sprintf (line,"%i(%s)%s", ofs, PR_GetString(def->s_name), s);
538 char *PR_GlobalStringNoContents (int ofs)
542 static char line[128];
544 def = ED_GlobalAtOfs(ofs);
546 sprintf (line,"%i(?)", ofs);
548 sprintf (line,"%i(%s)", ofs, PR_GetString(def->s_name));
566 // LordHavoc: optimized this to print out much more quickly (tempstring)
567 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
568 void ED_Print (edict_t *ed)
576 char tempstring[8192], tempstring2[260]; // temporary string buffers
580 Con_Printf ("FREE\n");
585 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
586 for (i=1 ; i<progs->numfielddefs ; i++)
588 d = &pr_fielddefs[i];
589 name = PR_GetString(d->s_name);
590 if (name[strlen(name)-2] == '_')
591 continue; // skip _x, _y, _z vars
593 v = (int *)((char *)ed->v + d->ofs*4);
595 // if the value is still all 0, skip the field
596 type = d->type & ~DEF_SAVEGLOBAL;
598 for (j=0 ; j<type_size[type] ; j++)
601 if (j == type_size[type])
604 if (strlen(name) > 256)
606 strncpy(tempstring2, name, 256);
607 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
608 tempstring2[259] = 0;
611 strcat(tempstring, name);
612 for (l = strlen(name);l < 14;l++)
613 strcat(tempstring, " ");
614 strcat(tempstring, " ");
616 name = PR_ValueString(d->type, (eval_t *)v);
617 if (strlen(name) > 256)
619 strncpy(tempstring2, name, 256);
620 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
621 tempstring2[259] = 0;
624 strcat(tempstring, name);
625 strcat(tempstring, "\n");
626 if (strlen(tempstring) >= 4096)
628 Con_Printf("%s", tempstring);
633 Con_Printf("%s", tempstring);
643 void ED_Write (qfile_t *f, edict_t *ed)
651 FS_Printf (f, "{\n");
655 FS_Printf (f, "}\n");
659 for (i=1 ; i<progs->numfielddefs ; i++)
661 d = &pr_fielddefs[i];
662 name = PR_GetString(d->s_name);
663 if (name[strlen(name)-2] == '_')
664 continue; // skip _x, _y, _z vars
666 v = (int *)((char *)ed->v + d->ofs*4);
668 // if the value is still all 0, skip the field
669 type = d->type & ~DEF_SAVEGLOBAL;
670 for (j=0 ; j<type_size[type] ; j++)
673 if (j == type_size[type])
676 FS_Printf (f,"\"%s\" ",name);
677 FS_Printf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
680 FS_Printf (f, "}\n");
683 void ED_PrintNum (int ent)
685 ED_Print (EDICT_NUM(ent));
692 For debugging, prints all the entities in the current server
695 void ED_PrintEdicts (void)
699 Con_Printf ("%i entities\n", sv.num_edicts);
700 for (i=0 ; i<sv.num_edicts ; i++)
708 For debugging, prints a single edict
711 void ED_PrintEdict_f (void)
715 i = atoi (Cmd_Argv(1));
716 if (i >= sv.num_edicts)
718 Con_Printf("Bad edict number\n");
735 int active, models, solid, step;
737 active = models = solid = step = 0;
738 for (i=0 ; i<sv.num_edicts ; i++)
748 if (ent->v->movetype == MOVETYPE_STEP)
752 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
753 Con_Printf ("active :%3i\n", active);
754 Con_Printf ("view :%3i\n", models);
755 Con_Printf ("touch :%3i\n", solid);
756 Con_Printf ("step :%3i\n", step);
761 ==============================================================================
765 FIXME: need to tag constants, doesn't really work
766 ==============================================================================
774 void ED_WriteGlobals (qfile_t *f)
782 for (i=0 ; i<progs->numglobaldefs ; i++)
784 def = &pr_globaldefs[i];
786 if ( !(def->type & DEF_SAVEGLOBAL) )
788 type &= ~DEF_SAVEGLOBAL;
790 if (type != ev_string && type != ev_float && type != ev_entity)
793 name = PR_GetString(def->s_name);
794 FS_Printf (f,"\"%s\" ", name);
795 FS_Printf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
805 void ED_ParseGlobals (const char *data)
807 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
813 if (!COM_ParseToken (&data))
814 Host_Error ("ED_ParseEntity: EOF without closing brace");
815 if (com_token[0] == '}')
818 strcpy (keyname, com_token);
821 if (!COM_ParseToken (&data))
822 Host_Error ("ED_ParseEntity: EOF without closing brace");
824 if (com_token[0] == '}')
825 Host_Error ("ED_ParseEntity: closing brace without data");
827 key = ED_FindGlobal (keyname);
830 Con_DPrintf ("'%s' is not a global\n", keyname);
834 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
835 Host_Error ("ED_ParseGlobals: parse error");
839 //============================================================================
847 char *ED_NewString (const char *string)
852 l = strlen(string) + 1;
853 new = Mem_Alloc(edictstring_mempool, l);
856 for (i=0 ; i< l ; i++)
858 if (string[i] == '\\' && i < l-1)
861 if (string[i] == 'n')
867 *new_p++ = string[i];
878 Can parse either fields or globals
879 returns false if error
882 qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s)
891 d = (void *)((int *)base + key->ofs);
893 switch (key->type & ~DEF_SAVEGLOBAL)
896 *(string_t *)d = PR_SetString(ED_NewString(s));
900 *(float *)d = atof (s);
907 for (i=0 ; i<3 ; i++)
909 while (*v && *v != ' ')
912 ((float *)d)[i] = atof (w);
919 if (i < 0 || i >= MAX_EDICTS)
920 Con_DPrintf("ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i)\n", i, MAX_EDICTS);
921 while (i >= sv.max_edicts)
923 *(int *)d = EDICT_TO_PROG(EDICT_NUM(i));
927 def = ED_FindField (s);
930 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
931 if (strcmp(s, "sky") && strcmp(s, "fog") && strncmp(s, "fog_", 4) && strcmp(s, "farclip"))
932 Con_DPrintf ("Can't find field %s\n", s);
935 *(int *)d = G_INT(def->ofs);
939 func = ED_FindFunction (s);
942 Con_DPrintf ("Can't find function %s\n", s);
945 *(func_t *)d = func - pr_functions;
958 Parses an edict out of the given string, returning the new position
959 ed should be a properly initialized empty edict.
960 Used for initial level load and for savegames.
963 const char *ED_ParseEdict (const char *data, edict_t *ent)
974 if (ent != sv.edicts) // hack
975 memset (ent->v, 0, progs->entityfields * 4);
977 // go through all the dictionary pairs
981 if (!COM_ParseToken (&data))
982 Host_Error ("ED_ParseEntity: EOF without closing brace");
983 if (com_token[0] == '}')
986 // anglehack is to allow QuakeEd to write single scalar angles
987 // and allow them to be turned into vectors. (FIXME...)
988 if (!strcmp(com_token, "angle"))
990 strcpy (com_token, "angles");
996 // FIXME: change light to _light to get rid of this hack
997 if (!strcmp(com_token, "light"))
998 strcpy (com_token, "light_lev"); // hack for single light def
1000 strcpy (keyname, com_token);
1002 // another hack to fix heynames with trailing spaces
1003 n = strlen(keyname);
1004 while (n && keyname[n-1] == ' ')
1011 if (!COM_ParseToken (&data))
1012 Host_Error ("ED_ParseEntity: EOF without closing brace");
1014 if (com_token[0] == '}')
1015 Host_Error ("ED_ParseEntity: closing brace without data");
1019 // keynames with a leading underscore are used for utility comments,
1020 // and are immediately discarded by quake
1021 if (keyname[0] == '_')
1024 key = ED_FindField (keyname);
1027 Con_DPrintf ("'%s' is not a field\n", keyname);
1034 strcpy (temp, com_token);
1035 sprintf (com_token, "0 %s 0", temp);
1038 if (!ED_ParseEpair ((void *)ent->v, key, com_token))
1039 Host_Error ("ED_ParseEdict: parse error");
1043 ent->e->free = true;
1053 The entities are directly placed in the array, rather than allocated with
1054 ED_Alloc, because otherwise an error loading the map would have entity
1055 number references out of order.
1057 Creates a server's entity / program execution context by
1058 parsing textual entity definitions out of an ent file.
1060 Used for both fresh maps and savegame loads. A fresh map would also need
1061 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1064 void ED_LoadFromFile (const char *data)
1067 int parsed, inhibited, spawned, died;
1075 pr_global_struct->time = sv.time;
1080 // parse the opening brace
1081 if (!COM_ParseToken (&data))
1083 if (com_token[0] != '{')
1084 Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1090 data = ED_ParseEdict (data, ent);
1093 // remove things from different skill levels or deathmatch
1094 if (deathmatch.integer)
1096 if (((int)ent->v->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1103 else if ((current_skill == 0 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_EASY ))
1104 || (current_skill == 1 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_MEDIUM))
1105 || (current_skill >= 2 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_HARD )))
1113 // immediately call spawn function
1115 if (!ent->v->classname)
1117 Con_Printf ("No classname for:\n");
1123 // look for the spawn function
1124 func = ED_FindFunction (PR_GetString(ent->v->classname));
1128 if (developer.integer) // don't confuse non-developers with errors
1130 Con_Printf ("No spawn function for:\n");
1137 pr_global_struct->self = EDICT_TO_PROG(ent);
1138 PR_ExecuteProgram (func - pr_functions, "");
1144 Con_DPrintf ("%i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", parsed, inhibited, spawned, died, spawned - died);
1148 typedef struct dpfield_s
1155 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1157 dpfield_t dpfields[] =
1159 {ev_float, "gravity"},
1160 {ev_float, "button3"},
1161 {ev_float, "button4"},
1162 {ev_float, "button5"},
1163 {ev_float, "button6"},
1164 {ev_float, "button7"},
1165 {ev_float, "button8"},
1166 {ev_float, "glow_size"},
1167 {ev_float, "glow_trail"},
1168 {ev_float, "glow_color"},
1169 {ev_float, "items2"},
1170 {ev_float, "scale"},
1171 {ev_float, "alpha"},
1172 {ev_float, "renderamt"},
1173 {ev_float, "rendermode"},
1174 {ev_float, "fullbright"},
1175 {ev_float, "ammo_shells1"},
1176 {ev_float, "ammo_nails1"},
1177 {ev_float, "ammo_lava_nails"},
1178 {ev_float, "ammo_rockets1"},
1179 {ev_float, "ammo_multi_rockets"},
1180 {ev_float, "ammo_cells1"},
1181 {ev_float, "ammo_plasma"},
1182 {ev_float, "idealpitch"},
1183 {ev_float, "pitch_speed"},
1184 {ev_entity, "viewmodelforclient"},
1185 {ev_entity, "nodrawtoclient"},
1186 {ev_entity, "exteriormodeltoclient"},
1187 {ev_entity, "drawonlytoclient"},
1189 {ev_vector, "movement"},
1190 {ev_float, "pmodel"},
1191 {ev_vector, "punchvector"},
1192 {ev_float, "clientcolors"}
1200 extern void PR_Cmd_Reset (void);
1201 void PR_LoadProgs (void)
1205 ddef_t *infielddefs;
1207 dfunction_t *dfunctions;
1209 // flush the non-C variable lookup cache
1210 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1211 gefvCache[i].field[0] = 0;
1213 Mem_EmptyPool(progs_mempool);
1214 Mem_EmptyPool(edictstring_mempool);
1216 temp = FS_LoadFile ("progs.dat", false);
1218 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1220 progs = (dprograms_t *)Mem_Alloc(progs_mempool, fs_filesize);
1222 memcpy(progs, temp, fs_filesize);
1225 Con_DPrintf ("Programs occupy %iK.\n", fs_filesize/1024);
1227 pr_crc = CRC_Block((qbyte *)progs, fs_filesize);
1229 // byte swap the header
1230 for (i = 0;i < (int) sizeof(*progs) / 4;i++)
1231 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1233 if (progs->version != PROG_VERSION)
1234 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1235 if (progs->crc != PROGHEADER_CRC)
1236 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1238 //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1239 dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1240 pr_strings = (char *)progs + progs->ofs_strings;
1241 pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1243 // we need to expand the fielddefs list to include all the engine fields,
1244 // so allocate a new place for it
1245 infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1246 pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1248 pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1250 // moved edict_size calculation down below field adding code
1252 pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1253 pr_globals = (float *)pr_global_struct;
1255 // byte swap the lumps
1256 for (i=0 ; i<progs->numstatements ; i++)
1258 pr_statements[i].op = LittleShort(pr_statements[i].op);
1259 pr_statements[i].a = LittleShort(pr_statements[i].a);
1260 pr_statements[i].b = LittleShort(pr_statements[i].b);
1261 pr_statements[i].c = LittleShort(pr_statements[i].c);
1264 pr_functions = Mem_Alloc(progs_mempool, sizeof(mfunction_t) * progs->numfunctions);
1265 for (i = 0;i < progs->numfunctions;i++)
1267 pr_functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1268 pr_functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1269 pr_functions[i].s_name = LittleLong (dfunctions[i].s_name);
1270 pr_functions[i].s_file = LittleLong (dfunctions[i].s_file);
1271 pr_functions[i].numparms = LittleLong (dfunctions[i].numparms);
1272 pr_functions[i].locals = LittleLong (dfunctions[i].locals);
1273 memcpy(pr_functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1276 for (i=0 ; i<progs->numglobaldefs ; i++)
1278 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1279 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1280 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1283 // copy the progs fields to the new fields list
1284 for (i = 0;i < progs->numfielddefs;i++)
1286 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1287 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1288 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1289 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1290 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1293 // append the darkplaces fields
1294 for (i = 0;i < (int) DPFIELDS;i++)
1296 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1297 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1298 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1299 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1300 progs->entityfields += 3;
1302 progs->entityfields++;
1303 progs->numfielddefs++;
1306 for (i=0 ; i<progs->numglobals ; i++)
1307 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1309 // moved edict_size calculation down here, below field adding code
1310 // LordHavoc: this no longer includes the edict_t header
1311 pr_edict_size = progs->entityfields * 4;
1312 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1314 // LordHavoc: bounds check anything static
1315 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1321 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1322 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1325 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1326 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1328 // global global global
1363 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1364 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1366 // global none global
1372 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1373 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1389 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1390 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1404 if ((unsigned short) st->a >= progs->numglobals)
1405 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1408 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1413 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1414 PR_Execute_ProgsLoaded();
1419 void PR_Fields_f (void)
1421 int i, j, ednum, used, usedamount;
1423 char tempstring[5000], tempstring2[260], *name;
1429 Con_Printf("no progs loaded\n");
1432 counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1433 for (ednum = 0;ednum < MAX_EDICTS;ednum++)
1435 ed = EDICT_NUM(ednum);
1438 for (i = 1;i < progs->numfielddefs;i++)
1440 d = &pr_fielddefs[i];
1441 name = PR_GetString(d->s_name);
1442 if (name[strlen(name)-2] == '_')
1443 continue; // skip _x, _y, _z vars
1444 v = (int *)((char *)ed->v + d->ofs*4);
1445 // if the value is still all 0, skip the field
1446 for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1459 for (i = 0;i < progs->numfielddefs;i++)
1461 d = &pr_fielddefs[i];
1462 name = PR_GetString(d->s_name);
1463 if (name[strlen(name)-2] == '_')
1464 continue; // skip _x, _y, _z vars
1465 switch(d->type & ~DEF_SAVEGLOBAL)
1468 strcat(tempstring, "string ");
1471 strcat(tempstring, "entity ");
1474 strcat(tempstring, "function ");
1477 strcat(tempstring, "field ");
1480 strcat(tempstring, "void ");
1483 strcat(tempstring, "float ");
1486 strcat(tempstring, "vector ");
1489 strcat(tempstring, "pointer ");
1492 sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1493 strcat(tempstring, tempstring2);
1496 if (strlen(name) > 256)
1498 strncpy(tempstring2, name, 256);
1499 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1500 tempstring2[259] = 0;
1503 strcat(tempstring, name);
1504 for (j = strlen(name);j < 25;j++)
1505 strcat(tempstring, " ");
1506 sprintf(tempstring2, "%5d", counts[i]);
1507 strcat(tempstring, tempstring2);
1508 strcat(tempstring, "\n");
1509 if (strlen(tempstring) >= 4096)
1511 Con_Printf("%s", tempstring);
1517 usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1521 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);
1524 void PR_Globals_f (void)
1529 Con_Printf("no progs loaded\n");
1532 for (i = 0;i < progs->numglobaldefs;i++)
1533 Con_Printf("%s\n", PR_GetString(pr_globaldefs[i].s_name));
1534 Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1542 extern void PR_Cmd_Init(void);
1545 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1546 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1547 Cmd_AddCommand ("edictcount", ED_Count);
1548 Cmd_AddCommand ("profile", PR_Profile_f);
1549 Cmd_AddCommand ("pr_fields", PR_Fields_f);
1550 Cmd_AddCommand ("pr_globals", PR_Globals_f);
1551 Cvar_RegisterVariable (&pr_checkextension);
1552 Cvar_RegisterVariable (&nomonsters);
1553 Cvar_RegisterVariable (&gamecfg);
1554 Cvar_RegisterVariable (&scratch1);
1555 Cvar_RegisterVariable (&scratch2);
1556 Cvar_RegisterVariable (&scratch3);
1557 Cvar_RegisterVariable (&scratch4);
1558 Cvar_RegisterVariable (&savedgamecfg);
1559 Cvar_RegisterVariable (&saved1);
1560 Cvar_RegisterVariable (&saved2);
1561 Cvar_RegisterVariable (&saved3);
1562 Cvar_RegisterVariable (&saved4);
1563 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1564 Cvar_RegisterVariable (&decors);
1565 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1566 if (gamemode == GAME_NEHAHRA)
1568 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1569 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1570 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1571 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1572 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1573 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1574 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1575 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1576 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1577 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1579 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1580 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1581 Cvar_RegisterVariable (&pr_boundscheck);
1582 Cvar_RegisterVariable (&pr_traceqc);
1584 progs_mempool = Mem_AllocPool("progs.dat");
1585 edictstring_mempool = Mem_AllocPool("edict strings");
1590 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1591 edict_t *EDICT_NUM_ERROR(int n, char *filename, int fileline)
1593 Host_Error ("EDICT_NUM: bad number %i (called at %s:%i)", n, filename, fileline);
1598 int NUM_FOR_EDICT_ERROR(edict_t *e)
1600 Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1604 int NUM_FOR_EDICT(edict_t *e)
1608 if ((unsigned int)n >= MAX_EDICTS)
1609 Host_Error ("NUM_FOR_EDICT: bad pointer");
1613 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1615 // return e - sv.edicts;
1618 //#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1619 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1620 int EDICT_TO_PROG(edict_t *e)
1624 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1625 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1626 return n;// EXPERIMENTAL
1627 //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1629 edict_t *PROG_TO_EDICT(int n)
1631 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1632 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1633 return sv.edicts + n; // EXPERIMENTAL
1634 //return sv.edicts + ((n) / (progs->entityfields * 4));