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)
193 memset (e->v, 0, progs->entityfields * 4);
201 Either finds a free edict, or allocates a new one.
202 Try to avoid reusing an entity that was recently freed, because it
203 can cause the client to think the entity morphed into something else
204 instead of being removed and recreated, which can cause interpolated
205 angles and bad trails.
208 edict_t *ED_Alloc (void)
213 for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
216 // the first couple seconds of server time can involve a lot of
217 // freeing and allocating, so relax the replacement policy
218 if (e->e->free && ( e->e->freetime < 2 || sv.time - e->e->freetime > 0.5 ) )
226 Host_Error ("ED_Alloc: no free edicts");
229 if (sv.num_edicts >= sv.max_edicts)
241 Marks the edict as free
242 FIXME: walk all entities and NULL out references to this entity
245 void ED_Free (edict_t *ed)
247 SV_UnlinkEdict (ed); // unlink from world bsp
251 ed->v->takedamage = 0;
252 ed->v->modelindex = 0;
256 VectorClear(ed->v->origin);
257 VectorClear(ed->v->angles);
258 ed->v->nextthink = -1;
261 ed->e->freetime = sv.time;
264 //===========================================================================
271 ddef_t *ED_GlobalAtOfs (int ofs)
276 for (i=0 ; i<progs->numglobaldefs ; i++)
278 def = &pr_globaldefs[i];
290 ddef_t *ED_FieldAtOfs (int ofs)
295 for (i=0 ; i<progs->numfielddefs ; i++)
297 def = &pr_fielddefs[i];
309 ddef_t *ED_FindField (const char *name)
314 for (i=0 ; i<progs->numfielddefs ; i++)
316 def = &pr_fielddefs[i];
317 if (!strcmp(PR_GetString(def->s_name), name))
328 ddef_t *ED_FindGlobal (const char *name)
333 for (i=0 ; i<progs->numglobaldefs ; i++)
335 def = &pr_globaldefs[i];
336 if (!strcmp(PR_GetString(def->s_name), name))
348 mfunction_t *ED_FindFunction (const char *name)
353 for (i=0 ; i<progs->numfunctions ; i++)
355 func = &pr_functions[i];
356 if (!strcmp(PR_GetString(func->s_name), name))
367 Returns a string describing *data in a type specific manner
370 int NoCrash_NUM_FOR_EDICT(edict_t *e);
371 char *PR_ValueString (etype_t type, eval_t *val)
373 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
378 type &= ~DEF_SAVEGLOBAL;
383 sprintf (line, "%s", PR_GetString(val->string));
386 //n = NoCrash_NUM_FOR_EDICT(PROG_TO_EDICT(val->edict));
388 if (n < 0 || n >= MAX_EDICTS)
389 sprintf (line, "entity %i (invalid!)", n);
391 sprintf (line, "entity %i", n);
394 f = pr_functions + val->function;
395 sprintf (line, "%s()", PR_GetString(f->s_name));
398 def = ED_FieldAtOfs ( val->_int );
399 sprintf (line, ".%s", PR_GetString(def->s_name));
402 sprintf (line, "void");
405 // LordHavoc: changed from %5.1f to %10.4f
406 sprintf (line, "%10.4f", val->_float);
409 // LordHavoc: changed from %5.1f to %10.4f
410 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
413 sprintf (line, "pointer");
416 sprintf (line, "bad type %i", type);
427 Returns a string describing *data in a type specific manner
428 Easier to parse than PR_ValueString
431 char *PR_UglyValueString (etype_t type, eval_t *val)
433 static char line[4096];
439 type &= ~DEF_SAVEGLOBAL;
444 sprintf (line, "%s", PR_GetString(val->string));
447 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
450 f = pr_functions + val->function;
451 sprintf (line, "%s", PR_GetString(f->s_name));
454 def = ED_FieldAtOfs ( val->_int );
455 // LordHavoc: parse the string a bit to turn special characters
456 // (like newline, specifically) into escape codes,
457 // this fixes saving games from various mods
458 //sprintf (line, "%s", PR_GetString(def->s_name));
459 s = PR_GetString(def->s_name);
460 for (i = 0;i < 4095 && *s;)
479 sprintf (line, "void");
482 sprintf (line, "%f", val->_float);
485 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
488 sprintf (line, "bad type %i", type);
499 Returns a string with a description and the contents of a global,
500 padded to 20 field width
503 char *PR_GlobalString (int ofs)
509 static char line[128];
511 val = (void *)&pr_globals[ofs];
512 def = ED_GlobalAtOfs(ofs);
514 sprintf (line,"%i(?)", ofs);
517 s = PR_ValueString (def->type, val);
518 sprintf (line,"%i(%s)%s", ofs, PR_GetString(def->s_name), s);
529 char *PR_GlobalStringNoContents (int ofs)
533 static char line[128];
535 def = ED_GlobalAtOfs(ofs);
537 sprintf (line,"%i(?)", ofs);
539 sprintf (line,"%i(%s)", ofs, PR_GetString(def->s_name));
557 // LordHavoc: optimized this to print out much more quickly (tempstring)
558 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
559 void ED_Print (edict_t *ed)
567 char tempstring[8192], tempstring2[260]; // temporary string buffers
571 Con_Printf ("FREE\n");
576 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
577 for (i=1 ; i<progs->numfielddefs ; i++)
579 d = &pr_fielddefs[i];
580 name = PR_GetString(d->s_name);
581 if (name[strlen(name)-2] == '_')
582 continue; // skip _x, _y, _z vars
584 v = (int *)((char *)ed->v + d->ofs*4);
586 // if the value is still all 0, skip the field
587 type = d->type & ~DEF_SAVEGLOBAL;
589 for (j=0 ; j<type_size[type] ; j++)
592 if (j == type_size[type])
595 if (strlen(name) > 256)
597 strncpy(tempstring2, name, 256);
598 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
599 tempstring2[259] = 0;
602 strcat(tempstring, name);
603 for (l = strlen(name);l < 14;l++)
604 strcat(tempstring, " ");
605 strcat(tempstring, " ");
607 name = PR_ValueString(d->type, (eval_t *)v);
608 if (strlen(name) > 256)
610 strncpy(tempstring2, name, 256);
611 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
612 tempstring2[259] = 0;
615 strcat(tempstring, name);
616 strcat(tempstring, "\n");
617 if (strlen(tempstring) >= 4096)
619 Con_Printf("%s", tempstring);
624 Con_Printf("%s", tempstring);
634 void ED_Write (qfile_t *f, edict_t *ed)
642 FS_Printf (f, "{\n");
646 FS_Printf (f, "}\n");
650 for (i=1 ; i<progs->numfielddefs ; i++)
652 d = &pr_fielddefs[i];
653 name = PR_GetString(d->s_name);
654 if (name[strlen(name)-2] == '_')
655 continue; // skip _x, _y, _z vars
657 v = (int *)((char *)ed->v + d->ofs*4);
659 // if the value is still all 0, skip the field
660 type = d->type & ~DEF_SAVEGLOBAL;
661 for (j=0 ; j<type_size[type] ; j++)
664 if (j == type_size[type])
667 FS_Printf (f,"\"%s\" ",name);
668 FS_Printf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
671 FS_Printf (f, "}\n");
674 void ED_PrintNum (int ent)
676 ED_Print (EDICT_NUM(ent));
683 For debugging, prints all the entities in the current server
686 void ED_PrintEdicts (void)
690 Con_Printf ("%i entities\n", sv.num_edicts);
691 for (i=0 ; i<sv.num_edicts ; i++)
699 For debugging, prints a single edict
702 void ED_PrintEdict_f (void)
706 i = atoi (Cmd_Argv(1));
707 if (i >= sv.num_edicts)
709 Con_Printf("Bad edict number\n");
726 int active, models, solid, step;
728 active = models = solid = step = 0;
729 for (i=0 ; i<sv.num_edicts ; i++)
739 if (ent->v->movetype == MOVETYPE_STEP)
743 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
744 Con_Printf ("active :%3i\n", active);
745 Con_Printf ("view :%3i\n", models);
746 Con_Printf ("touch :%3i\n", solid);
747 Con_Printf ("step :%3i\n", step);
752 ==============================================================================
756 FIXME: need to tag constants, doesn't really work
757 ==============================================================================
765 void ED_WriteGlobals (qfile_t *f)
773 for (i=0 ; i<progs->numglobaldefs ; i++)
775 def = &pr_globaldefs[i];
777 if ( !(def->type & DEF_SAVEGLOBAL) )
779 type &= ~DEF_SAVEGLOBAL;
781 if (type != ev_string && type != ev_float && type != ev_entity)
784 name = PR_GetString(def->s_name);
785 FS_Printf (f,"\"%s\" ", name);
786 FS_Printf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
796 void ED_ParseGlobals (const char *data)
798 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
804 if (!COM_ParseToken (&data))
805 Host_Error ("ED_ParseEntity: EOF without closing brace");
806 if (com_token[0] == '}')
809 strcpy (keyname, com_token);
812 if (!COM_ParseToken (&data))
813 Host_Error ("ED_ParseEntity: EOF without closing brace");
815 if (com_token[0] == '}')
816 Host_Error ("ED_ParseEntity: closing brace without data");
818 key = ED_FindGlobal (keyname);
821 Con_DPrintf ("'%s' is not a global\n", keyname);
825 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
826 Host_Error ("ED_ParseGlobals: parse error");
830 //============================================================================
838 char *ED_NewString (const char *string)
843 l = strlen(string) + 1;
844 new = Mem_Alloc(edictstring_mempool, l);
847 for (i=0 ; i< l ; i++)
849 if (string[i] == '\\' && i < l-1)
852 if (string[i] == 'n')
858 *new_p++ = string[i];
869 Can parse either fields or globals
870 returns false if error
873 qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s)
882 d = (void *)((int *)base + key->ofs);
884 switch (key->type & ~DEF_SAVEGLOBAL)
887 *(string_t *)d = PR_SetString(ED_NewString(s));
891 *(float *)d = atof (s);
898 for (i=0 ; i<3 ; i++)
900 while (*v && *v != ' ')
903 ((float *)d)[i] = atof (w);
910 if (i < 0 || i >= MAX_EDICTS)
911 Con_DPrintf("ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i)\n", i, MAX_EDICTS);
912 while (i >= sv.max_edicts)
914 *(int *)d = EDICT_TO_PROG(EDICT_NUM(i));
918 def = ED_FindField (s);
921 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
922 if (strcmp(s, "sky") && strcmp(s, "fog") && strncmp(s, "fog_", 4) && strcmp(s, "farclip"))
923 Con_DPrintf ("Can't find field %s\n", s);
926 *(int *)d = G_INT(def->ofs);
930 func = ED_FindFunction (s);
933 Con_DPrintf ("Can't find function %s\n", s);
936 *(func_t *)d = func - pr_functions;
949 Parses an edict out of the given string, returning the new position
950 ed should be a properly initialized empty edict.
951 Used for initial level load and for savegames.
954 const char *ED_ParseEdict (const char *data, edict_t *ent)
965 if (ent != sv.edicts) // hack
966 memset (ent->v, 0, progs->entityfields * 4);
968 // go through all the dictionary pairs
972 if (!COM_ParseToken (&data))
973 Host_Error ("ED_ParseEntity: EOF without closing brace");
974 if (com_token[0] == '}')
977 // anglehack is to allow QuakeEd to write single scalar angles
978 // and allow them to be turned into vectors. (FIXME...)
979 if (!strcmp(com_token, "angle"))
981 strcpy (com_token, "angles");
987 // FIXME: change light to _light to get rid of this hack
988 if (!strcmp(com_token, "light"))
989 strcpy (com_token, "light_lev"); // hack for single light def
991 strcpy (keyname, com_token);
993 // another hack to fix heynames with trailing spaces
995 while (n && keyname[n-1] == ' ')
1002 if (!COM_ParseToken (&data))
1003 Host_Error ("ED_ParseEntity: EOF without closing brace");
1005 if (com_token[0] == '}')
1006 Host_Error ("ED_ParseEntity: closing brace without data");
1010 // keynames with a leading underscore are used for utility comments,
1011 // and are immediately discarded by quake
1012 if (keyname[0] == '_')
1015 key = ED_FindField (keyname);
1018 Con_DPrintf ("'%s' is not a field\n", keyname);
1025 strcpy (temp, com_token);
1026 sprintf (com_token, "0 %s 0", temp);
1029 if (!ED_ParseEpair ((void *)ent->v, key, com_token))
1030 Host_Error ("ED_ParseEdict: parse error");
1034 ent->e->free = true;
1044 The entities are directly placed in the array, rather than allocated with
1045 ED_Alloc, because otherwise an error loading the map would have entity
1046 number references out of order.
1048 Creates a server's entity / program execution context by
1049 parsing textual entity definitions out of an ent file.
1051 Used for both fresh maps and savegame loads. A fresh map would also need
1052 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1055 void ED_LoadFromFile (const char *data)
1058 int parsed, inhibited, spawned, died;
1066 pr_global_struct->time = sv.time;
1071 // parse the opening brace
1072 if (!COM_ParseToken (&data))
1074 if (com_token[0] != '{')
1075 Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1081 data = ED_ParseEdict (data, ent);
1084 // remove things from different skill levels or deathmatch
1085 if (deathmatch.integer)
1087 if (((int)ent->v->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1094 else if ((current_skill == 0 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_EASY ))
1095 || (current_skill == 1 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_MEDIUM))
1096 || (current_skill >= 2 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_HARD )))
1104 // immediately call spawn function
1106 if (!ent->v->classname)
1108 Con_Printf ("No classname for:\n");
1114 // look for the spawn function
1115 func = ED_FindFunction (PR_GetString(ent->v->classname));
1119 if (developer.integer) // don't confuse non-developers with errors
1121 Con_Printf ("No spawn function for:\n");
1128 pr_global_struct->self = EDICT_TO_PROG(ent);
1129 PR_ExecuteProgram (func - pr_functions, "");
1135 Con_DPrintf ("%i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", parsed, inhibited, spawned, died, spawned - died);
1139 typedef struct dpfield_s
1146 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1148 dpfield_t dpfields[] =
1150 {ev_float, "gravity"},
1151 {ev_float, "button3"},
1152 {ev_float, "button4"},
1153 {ev_float, "button5"},
1154 {ev_float, "button6"},
1155 {ev_float, "button7"},
1156 {ev_float, "button8"},
1157 {ev_float, "glow_size"},
1158 {ev_float, "glow_trail"},
1159 {ev_float, "glow_color"},
1160 {ev_float, "items2"},
1161 {ev_float, "scale"},
1162 {ev_float, "alpha"},
1163 {ev_float, "renderamt"},
1164 {ev_float, "rendermode"},
1165 {ev_float, "fullbright"},
1166 {ev_float, "ammo_shells1"},
1167 {ev_float, "ammo_nails1"},
1168 {ev_float, "ammo_lava_nails"},
1169 {ev_float, "ammo_rockets1"},
1170 {ev_float, "ammo_multi_rockets"},
1171 {ev_float, "ammo_cells1"},
1172 {ev_float, "ammo_plasma"},
1173 {ev_float, "idealpitch"},
1174 {ev_float, "pitch_speed"},
1175 {ev_entity, "viewmodelforclient"},
1176 {ev_entity, "nodrawtoclient"},
1177 {ev_entity, "exteriormodeltoclient"},
1178 {ev_entity, "drawonlytoclient"},
1180 {ev_vector, "movement"},
1181 {ev_float, "pmodel"},
1182 {ev_vector, "punchvector"},
1183 {ev_float, "clientcolors"}
1191 extern void PR_Cmd_Reset (void);
1192 void PR_LoadProgs (void)
1196 ddef_t *infielddefs;
1198 dfunction_t *dfunctions;
1200 // flush the non-C variable lookup cache
1201 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1202 gefvCache[i].field[0] = 0;
1204 Mem_EmptyPool(progs_mempool);
1205 Mem_EmptyPool(edictstring_mempool);
1207 temp = FS_LoadFile ("progs.dat", false);
1209 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1211 progs = (dprograms_t *)Mem_Alloc(progs_mempool, fs_filesize);
1213 memcpy(progs, temp, fs_filesize);
1216 Con_DPrintf ("Programs occupy %iK.\n", fs_filesize/1024);
1218 pr_crc = CRC_Block((qbyte *)progs, fs_filesize);
1220 // byte swap the header
1221 for (i = 0;i < (int) sizeof(*progs) / 4;i++)
1222 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1224 if (progs->version != PROG_VERSION)
1225 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1226 if (progs->crc != PROGHEADER_CRC)
1227 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1229 //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1230 dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1231 pr_strings = (char *)progs + progs->ofs_strings;
1232 pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1234 // we need to expand the fielddefs list to include all the engine fields,
1235 // so allocate a new place for it
1236 infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1237 pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1239 pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1241 // moved edict_size calculation down below field adding code
1243 pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1244 pr_globals = (float *)pr_global_struct;
1246 // byte swap the lumps
1247 for (i=0 ; i<progs->numstatements ; i++)
1249 pr_statements[i].op = LittleShort(pr_statements[i].op);
1250 pr_statements[i].a = LittleShort(pr_statements[i].a);
1251 pr_statements[i].b = LittleShort(pr_statements[i].b);
1252 pr_statements[i].c = LittleShort(pr_statements[i].c);
1255 pr_functions = Mem_Alloc(progs_mempool, sizeof(mfunction_t) * progs->numfunctions);
1256 for (i = 0;i < progs->numfunctions;i++)
1258 pr_functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1259 pr_functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1260 pr_functions[i].s_name = LittleLong (dfunctions[i].s_name);
1261 pr_functions[i].s_file = LittleLong (dfunctions[i].s_file);
1262 pr_functions[i].numparms = LittleLong (dfunctions[i].numparms);
1263 pr_functions[i].locals = LittleLong (dfunctions[i].locals);
1264 memcpy(pr_functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1267 for (i=0 ; i<progs->numglobaldefs ; i++)
1269 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1270 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1271 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1274 // copy the progs fields to the new fields list
1275 for (i = 0;i < progs->numfielddefs;i++)
1277 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1278 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1279 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1280 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1281 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1284 // append the darkplaces fields
1285 for (i = 0;i < (int) DPFIELDS;i++)
1287 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1288 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1289 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1290 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1291 progs->entityfields += 3;
1293 progs->entityfields++;
1294 progs->numfielddefs++;
1297 for (i=0 ; i<progs->numglobals ; i++)
1298 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1300 // moved edict_size calculation down here, below field adding code
1301 // LordHavoc: this no longer includes the edict_t header
1302 pr_edict_size = progs->entityfields * 4;
1303 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1305 // LordHavoc: bounds check anything static
1306 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1312 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1313 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1316 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1317 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1319 // global global global
1354 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1355 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1357 // global none global
1363 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1364 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1380 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1381 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1395 if ((unsigned short) st->a >= progs->numglobals)
1396 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1399 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1404 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1405 PR_Execute_ProgsLoaded();
1410 void PR_Fields_f (void)
1412 int i, j, ednum, used, usedamount;
1414 char tempstring[5000], tempstring2[260], *name;
1420 Con_Printf("no progs loaded\n");
1423 counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1424 for (ednum = 0;ednum < MAX_EDICTS;ednum++)
1426 ed = EDICT_NUM(ednum);
1429 for (i = 1;i < progs->numfielddefs;i++)
1431 d = &pr_fielddefs[i];
1432 name = PR_GetString(d->s_name);
1433 if (name[strlen(name)-2] == '_')
1434 continue; // skip _x, _y, _z vars
1435 v = (int *)((char *)ed->v + d->ofs*4);
1436 // if the value is still all 0, skip the field
1437 for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1450 for (i = 0;i < progs->numfielddefs;i++)
1452 d = &pr_fielddefs[i];
1453 name = PR_GetString(d->s_name);
1454 if (name[strlen(name)-2] == '_')
1455 continue; // skip _x, _y, _z vars
1456 switch(d->type & ~DEF_SAVEGLOBAL)
1459 strcat(tempstring, "string ");
1462 strcat(tempstring, "entity ");
1465 strcat(tempstring, "function ");
1468 strcat(tempstring, "field ");
1471 strcat(tempstring, "void ");
1474 strcat(tempstring, "float ");
1477 strcat(tempstring, "vector ");
1480 strcat(tempstring, "pointer ");
1483 sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1484 strcat(tempstring, tempstring2);
1487 if (strlen(name) > 256)
1489 strncpy(tempstring2, name, 256);
1490 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1491 tempstring2[259] = 0;
1494 strcat(tempstring, name);
1495 for (j = strlen(name);j < 25;j++)
1496 strcat(tempstring, " ");
1497 sprintf(tempstring2, "%5d", counts[i]);
1498 strcat(tempstring, tempstring2);
1499 strcat(tempstring, "\n");
1500 if (strlen(tempstring) >= 4096)
1502 Con_Printf("%s", tempstring);
1508 usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1512 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);
1515 void PR_Globals_f (void)
1520 Con_Printf("no progs loaded\n");
1523 for (i = 0;i < progs->numglobaldefs;i++)
1524 Con_Printf("%s\n", PR_GetString(pr_globaldefs[i].s_name));
1525 Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1533 extern void PR_Cmd_Init(void);
1536 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1537 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1538 Cmd_AddCommand ("edictcount", ED_Count);
1539 Cmd_AddCommand ("profile", PR_Profile_f);
1540 Cmd_AddCommand ("pr_fields", PR_Fields_f);
1541 Cmd_AddCommand ("pr_globals", PR_Globals_f);
1542 Cvar_RegisterVariable (&pr_checkextension);
1543 Cvar_RegisterVariable (&nomonsters);
1544 Cvar_RegisterVariable (&gamecfg);
1545 Cvar_RegisterVariable (&scratch1);
1546 Cvar_RegisterVariable (&scratch2);
1547 Cvar_RegisterVariable (&scratch3);
1548 Cvar_RegisterVariable (&scratch4);
1549 Cvar_RegisterVariable (&savedgamecfg);
1550 Cvar_RegisterVariable (&saved1);
1551 Cvar_RegisterVariable (&saved2);
1552 Cvar_RegisterVariable (&saved3);
1553 Cvar_RegisterVariable (&saved4);
1554 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1555 Cvar_RegisterVariable (&decors);
1556 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1557 if (gamemode == GAME_NEHAHRA)
1559 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1560 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1561 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1562 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1563 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1564 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1565 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1566 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1567 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1568 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1570 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1571 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1572 Cvar_RegisterVariable (&pr_boundscheck);
1573 Cvar_RegisterVariable (&pr_traceqc);
1575 progs_mempool = Mem_AllocPool("progs.dat");
1576 edictstring_mempool = Mem_AllocPool("edict strings");
1581 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1582 edict_t *EDICT_NUM_ERROR(int n, char *filename, int fileline)
1584 Host_Error ("EDICT_NUM: bad number %i (called at %s:%i)", n, filename, fileline);
1589 int NUM_FOR_EDICT_ERROR(edict_t *e)
1591 Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1595 int NUM_FOR_EDICT(edict_t *e)
1599 if ((unsigned int)n >= MAX_EDICTS)
1600 Host_Error ("NUM_FOR_EDICT: bad pointer");
1604 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1606 // return e - sv.edicts;
1609 //#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1610 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1611 int EDICT_TO_PROG(edict_t *e)
1615 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1616 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1617 return n;// EXPERIMENTAL
1618 //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1620 edict_t *PROG_TO_EDICT(int n)
1622 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1623 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1624 return sv.edicts + n; // EXPERIMENTAL
1625 //return sv.edicts + ((n) / (progs->entityfields * 4));