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 extern void SV_IncreaseEdicts(void);
207 edict_t *ED_Alloc (void)
212 for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
215 // the first couple seconds of server time can involve a lot of
216 // freeing and allocating, so relax the replacement policy
217 if (e->e->free && ( e->e->freetime < 2 || sv.time - e->e->freetime > 0.5 ) )
225 Host_Error ("ED_Alloc: no free edicts");
228 if (sv.num_edicts >= sv.max_edicts)
240 Marks the edict as free
241 FIXME: walk all entities and NULL out references to this entity
244 void ED_Free (edict_t *ed)
246 SV_UnlinkEdict (ed); // unlink from world bsp
250 ed->v->takedamage = 0;
251 ed->v->modelindex = 0;
255 VectorClear(ed->v->origin);
256 VectorClear(ed->v->angles);
257 ed->v->nextthink = -1;
260 ed->e->freetime = sv.time;
263 //===========================================================================
270 ddef_t *ED_GlobalAtOfs (int ofs)
275 for (i=0 ; i<progs->numglobaldefs ; i++)
277 def = &pr_globaldefs[i];
289 ddef_t *ED_FieldAtOfs (int ofs)
294 for (i=0 ; i<progs->numfielddefs ; i++)
296 def = &pr_fielddefs[i];
308 ddef_t *ED_FindField (const char *name)
313 for (i=0 ; i<progs->numfielddefs ; i++)
315 def = &pr_fielddefs[i];
316 if (!strcmp(PR_GetString(def->s_name), name))
327 ddef_t *ED_FindGlobal (const char *name)
332 for (i=0 ; i<progs->numglobaldefs ; i++)
334 def = &pr_globaldefs[i];
335 if (!strcmp(PR_GetString(def->s_name), name))
347 mfunction_t *ED_FindFunction (const char *name)
352 for (i=0 ; i<progs->numfunctions ; i++)
354 func = &pr_functions[i];
355 if (!strcmp(PR_GetString(func->s_name), name))
366 Returns a string describing *data in a type specific manner
369 int NoCrash_NUM_FOR_EDICT(edict_t *e);
370 char *PR_ValueString (etype_t type, eval_t *val)
372 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
377 type &= ~DEF_SAVEGLOBAL;
382 sprintf (line, "%s", PR_GetString(val->string));
385 //n = NoCrash_NUM_FOR_EDICT(PROG_TO_EDICT(val->edict));
387 if (n < 0 || n >= MAX_EDICTS)
388 sprintf (line, "entity %i (invalid!)", n);
390 sprintf (line, "entity %i", n);
393 f = pr_functions + val->function;
394 sprintf (line, "%s()", PR_GetString(f->s_name));
397 def = ED_FieldAtOfs ( val->_int );
398 sprintf (line, ".%s", PR_GetString(def->s_name));
401 sprintf (line, "void");
404 // LordHavoc: changed from %5.1f to %10.4f
405 sprintf (line, "%10.4f", val->_float);
408 // LordHavoc: changed from %5.1f to %10.4f
409 sprintf (line, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
412 sprintf (line, "pointer");
415 sprintf (line, "bad type %i", type);
426 Returns a string describing *data in a type specific manner
427 Easier to parse than PR_ValueString
430 char *PR_UglyValueString (etype_t type, eval_t *val)
432 static char line[4096];
438 type &= ~DEF_SAVEGLOBAL;
443 sprintf (line, "%s", PR_GetString(val->string));
446 sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
449 f = pr_functions + val->function;
450 sprintf (line, "%s", PR_GetString(f->s_name));
453 def = ED_FieldAtOfs ( val->_int );
454 // LordHavoc: parse the string a bit to turn special characters
455 // (like newline, specifically) into escape codes,
456 // this fixes saving games from various mods
457 //sprintf (line, "%s", PR_GetString(def->s_name));
458 s = PR_GetString(def->s_name);
459 for (i = 0;i < 4095 && *s;)
478 sprintf (line, "void");
481 sprintf (line, "%f", val->_float);
484 sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
487 sprintf (line, "bad type %i", type);
498 Returns a string with a description and the contents of a global,
499 padded to 20 field width
502 char *PR_GlobalString (int ofs)
508 static char line[128];
510 val = (void *)&pr_globals[ofs];
511 def = ED_GlobalAtOfs(ofs);
513 sprintf (line,"%i(?)", ofs);
516 s = PR_ValueString (def->type, val);
517 sprintf (line,"%i(%s)%s", ofs, PR_GetString(def->s_name), s);
528 char *PR_GlobalStringNoContents (int ofs)
532 static char line[128];
534 def = ED_GlobalAtOfs(ofs);
536 sprintf (line,"%i(?)", ofs);
538 sprintf (line,"%i(%s)", ofs, PR_GetString(def->s_name));
556 // LordHavoc: optimized this to print out much more quickly (tempstring)
557 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
558 void ED_Print (edict_t *ed)
566 char tempstring[8192], tempstring2[260]; // temporary string buffers
570 Con_Printf ("FREE\n");
575 sprintf(tempstring, "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
576 for (i=1 ; i<progs->numfielddefs ; i++)
578 d = &pr_fielddefs[i];
579 name = PR_GetString(d->s_name);
580 if (name[strlen(name)-2] == '_')
581 continue; // skip _x, _y, _z vars
583 v = (int *)((char *)ed->v + d->ofs*4);
585 // if the value is still all 0, skip the field
586 type = d->type & ~DEF_SAVEGLOBAL;
588 for (j=0 ; j<type_size[type] ; j++)
591 if (j == type_size[type])
594 if (strlen(name) > 256)
596 strncpy(tempstring2, name, 256);
597 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
598 tempstring2[259] = 0;
601 strcat(tempstring, name);
602 for (l = strlen(name);l < 14;l++)
603 strcat(tempstring, " ");
604 strcat(tempstring, " ");
606 name = PR_ValueString(d->type, (eval_t *)v);
607 if (strlen(name) > 256)
609 strncpy(tempstring2, name, 256);
610 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
611 tempstring2[259] = 0;
614 strcat(tempstring, name);
615 strcat(tempstring, "\n");
616 if (strlen(tempstring) >= 4096)
618 Con_Printf("%s", tempstring);
623 Con_Printf("%s", tempstring);
633 void ED_Write (qfile_t *f, edict_t *ed)
641 FS_Printf (f, "{\n");
645 FS_Printf (f, "}\n");
649 for (i=1 ; i<progs->numfielddefs ; i++)
651 d = &pr_fielddefs[i];
652 name = PR_GetString(d->s_name);
653 if (name[strlen(name)-2] == '_')
654 continue; // skip _x, _y, _z vars
656 v = (int *)((char *)ed->v + d->ofs*4);
658 // if the value is still all 0, skip the field
659 type = d->type & ~DEF_SAVEGLOBAL;
660 for (j=0 ; j<type_size[type] ; j++)
663 if (j == type_size[type])
666 FS_Printf (f,"\"%s\" ",name);
667 FS_Printf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
670 FS_Printf (f, "}\n");
673 void ED_PrintNum (int ent)
675 ED_Print (EDICT_NUM(ent));
682 For debugging, prints all the entities in the current server
685 void ED_PrintEdicts (void)
689 Con_Printf ("%i entities\n", sv.num_edicts);
690 for (i=0 ; i<sv.num_edicts ; i++)
698 For debugging, prints a single edict
701 void ED_PrintEdict_f (void)
705 i = atoi (Cmd_Argv(1));
706 if (i >= sv.num_edicts)
708 Con_Printf("Bad edict number\n");
725 int active, models, solid, step;
727 active = models = solid = step = 0;
728 for (i=0 ; i<sv.num_edicts ; i++)
738 if (ent->v->movetype == MOVETYPE_STEP)
742 Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
743 Con_Printf ("active :%3i\n", active);
744 Con_Printf ("view :%3i\n", models);
745 Con_Printf ("touch :%3i\n", solid);
746 Con_Printf ("step :%3i\n", step);
751 ==============================================================================
755 FIXME: need to tag constants, doesn't really work
756 ==============================================================================
764 void ED_WriteGlobals (qfile_t *f)
772 for (i=0 ; i<progs->numglobaldefs ; i++)
774 def = &pr_globaldefs[i];
776 if ( !(def->type & DEF_SAVEGLOBAL) )
778 type &= ~DEF_SAVEGLOBAL;
780 if (type != ev_string && type != ev_float && type != ev_entity)
783 name = PR_GetString(def->s_name);
784 FS_Printf (f,"\"%s\" ", name);
785 FS_Printf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
795 void ED_ParseGlobals (const char *data)
797 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
803 if (!COM_ParseToken (&data))
804 Host_Error ("ED_ParseEntity: EOF without closing brace");
805 if (com_token[0] == '}')
808 strcpy (keyname, com_token);
811 if (!COM_ParseToken (&data))
812 Host_Error ("ED_ParseEntity: EOF without closing brace");
814 if (com_token[0] == '}')
815 Host_Error ("ED_ParseEntity: closing brace without data");
817 key = ED_FindGlobal (keyname);
820 Con_DPrintf ("'%s' is not a global\n", keyname);
824 if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
825 Host_Error ("ED_ParseGlobals: parse error");
829 //============================================================================
837 char *ED_NewString (const char *string)
842 l = strlen(string) + 1;
843 new = Mem_Alloc(edictstring_mempool, l);
846 for (i=0 ; i< l ; i++)
848 if (string[i] == '\\' && i < l-1)
851 if (string[i] == 'n')
857 *new_p++ = string[i];
868 Can parse either fields or globals
869 returns false if error
872 qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s)
881 d = (void *)((int *)base + key->ofs);
883 switch (key->type & ~DEF_SAVEGLOBAL)
886 *(string_t *)d = PR_SetString(ED_NewString(s));
890 *(float *)d = atof (s);
897 for (i=0 ; i<3 ; i++)
899 while (*v && *v != ' ')
902 ((float *)d)[i] = atof (w);
908 *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
912 def = ED_FindField (s);
915 // LordHavoc: don't warn about worldspawn sky/fog fields because they don't require mod support
916 if (strcmp(s, "sky") && strcmp(s, "fog") && strncmp(s, "fog_", 4) && strcmp(s, "farclip"))
917 Con_DPrintf ("Can't find field %s\n", s);
920 *(int *)d = G_INT(def->ofs);
924 func = ED_FindFunction (s);
927 Con_DPrintf ("Can't find function %s\n", s);
930 *(func_t *)d = func - pr_functions;
943 Parses an edict out of the given string, returning the new position
944 ed should be a properly initialized empty edict.
945 Used for initial level load and for savegames.
948 const char *ED_ParseEdict (const char *data, edict_t *ent)
959 if (ent != sv.edicts) // hack
960 memset (ent->v, 0, progs->entityfields * 4);
962 // go through all the dictionary pairs
966 if (!COM_ParseToken (&data))
967 Host_Error ("ED_ParseEntity: EOF without closing brace");
968 if (com_token[0] == '}')
971 // anglehack is to allow QuakeEd to write single scalar angles
972 // and allow them to be turned into vectors. (FIXME...)
973 if (!strcmp(com_token, "angle"))
975 strcpy (com_token, "angles");
981 // FIXME: change light to _light to get rid of this hack
982 if (!strcmp(com_token, "light"))
983 strcpy (com_token, "light_lev"); // hack for single light def
985 strcpy (keyname, com_token);
987 // another hack to fix heynames with trailing spaces
989 while (n && keyname[n-1] == ' ')
996 if (!COM_ParseToken (&data))
997 Host_Error ("ED_ParseEntity: EOF without closing brace");
999 if (com_token[0] == '}')
1000 Host_Error ("ED_ParseEntity: closing brace without data");
1004 // keynames with a leading underscore are used for utility comments,
1005 // and are immediately discarded by quake
1006 if (keyname[0] == '_')
1009 key = ED_FindField (keyname);
1012 Con_DPrintf ("'%s' is not a field\n", keyname);
1019 strcpy (temp, com_token);
1020 sprintf (com_token, "0 %s 0", temp);
1023 if (!ED_ParseEpair ((void *)ent->v, key, com_token))
1024 Host_Error ("ED_ParseEdict: parse error");
1028 ent->e->free = true;
1038 The entities are directly placed in the array, rather than allocated with
1039 ED_Alloc, because otherwise an error loading the map would have entity
1040 number references out of order.
1042 Creates a server's entity / program execution context by
1043 parsing textual entity definitions out of an ent file.
1045 Used for both fresh maps and savegame loads. A fresh map would also need
1046 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1049 void ED_LoadFromFile (const char *data)
1052 int parsed, inhibited, spawned, died;
1060 pr_global_struct->time = sv.time;
1065 // parse the opening brace
1066 if (!COM_ParseToken (&data))
1068 if (com_token[0] != '{')
1069 Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1075 data = ED_ParseEdict (data, ent);
1078 // remove things from different skill levels or deathmatch
1079 if (deathmatch.integer)
1081 if (((int)ent->v->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1088 else if ((current_skill == 0 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_EASY ))
1089 || (current_skill == 1 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_MEDIUM))
1090 || (current_skill >= 2 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_HARD )))
1098 // immediately call spawn function
1100 if (!ent->v->classname)
1102 Con_Printf ("No classname for:\n");
1108 // look for the spawn function
1109 func = ED_FindFunction (PR_GetString(ent->v->classname));
1113 if (developer.integer) // don't confuse non-developers with errors
1115 Con_Printf ("No spawn function for:\n");
1122 pr_global_struct->self = EDICT_TO_PROG(ent);
1123 PR_ExecuteProgram (func - pr_functions, "");
1129 Con_DPrintf ("%i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", parsed, inhibited, spawned, died, spawned - died);
1133 typedef struct dpfield_s
1140 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1142 dpfield_t dpfields[] =
1144 {ev_float, "gravity"},
1145 {ev_float, "button3"},
1146 {ev_float, "button4"},
1147 {ev_float, "button5"},
1148 {ev_float, "button6"},
1149 {ev_float, "button7"},
1150 {ev_float, "button8"},
1151 {ev_float, "glow_size"},
1152 {ev_float, "glow_trail"},
1153 {ev_float, "glow_color"},
1154 {ev_float, "items2"},
1155 {ev_float, "scale"},
1156 {ev_float, "alpha"},
1157 {ev_float, "renderamt"},
1158 {ev_float, "rendermode"},
1159 {ev_float, "fullbright"},
1160 {ev_float, "ammo_shells1"},
1161 {ev_float, "ammo_nails1"},
1162 {ev_float, "ammo_lava_nails"},
1163 {ev_float, "ammo_rockets1"},
1164 {ev_float, "ammo_multi_rockets"},
1165 {ev_float, "ammo_cells1"},
1166 {ev_float, "ammo_plasma"},
1167 {ev_float, "idealpitch"},
1168 {ev_float, "pitch_speed"},
1169 {ev_entity, "viewmodelforclient"},
1170 {ev_entity, "nodrawtoclient"},
1171 {ev_entity, "exteriormodeltoclient"},
1172 {ev_entity, "drawonlytoclient"},
1174 {ev_vector, "movement"},
1175 {ev_float, "pmodel"},
1176 {ev_vector, "punchvector"}
1184 extern void PR_Cmd_Reset (void);
1185 void PR_LoadProgs (void)
1189 ddef_t *infielddefs;
1191 dfunction_t *dfunctions;
1193 // flush the non-C variable lookup cache
1194 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1195 gefvCache[i].field[0] = 0;
1197 Mem_EmptyPool(progs_mempool);
1198 Mem_EmptyPool(edictstring_mempool);
1200 temp = FS_LoadFile ("progs.dat", false);
1202 Host_Error ("PR_LoadProgs: couldn't load progs.dat");
1204 progs = (dprograms_t *)Mem_Alloc(progs_mempool, fs_filesize);
1206 memcpy(progs, temp, fs_filesize);
1209 Con_DPrintf ("Programs occupy %iK.\n", fs_filesize/1024);
1211 pr_crc = CRC_Block((qbyte *)progs, fs_filesize);
1213 // byte swap the header
1214 for (i = 0;i < (int) sizeof(*progs) / 4;i++)
1215 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1217 if (progs->version != PROG_VERSION)
1218 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1219 if (progs->crc != PROGHEADER_CRC)
1220 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1222 //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1223 dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1224 pr_strings = (char *)progs + progs->ofs_strings;
1225 pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1227 // we need to expand the fielddefs list to include all the engine fields,
1228 // so allocate a new place for it
1229 infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1230 pr_fielddefs = Mem_Alloc(progs_mempool, (progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1232 pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1234 // moved edict_size calculation down below field adding code
1236 pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1237 pr_globals = (float *)pr_global_struct;
1239 // byte swap the lumps
1240 for (i=0 ; i<progs->numstatements ; i++)
1242 pr_statements[i].op = LittleShort(pr_statements[i].op);
1243 pr_statements[i].a = LittleShort(pr_statements[i].a);
1244 pr_statements[i].b = LittleShort(pr_statements[i].b);
1245 pr_statements[i].c = LittleShort(pr_statements[i].c);
1248 pr_functions = Mem_Alloc(progs_mempool, sizeof(mfunction_t) * progs->numfunctions);
1249 for (i = 0;i < progs->numfunctions;i++)
1251 pr_functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1252 pr_functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1253 pr_functions[i].s_name = LittleLong (dfunctions[i].s_name);
1254 pr_functions[i].s_file = LittleLong (dfunctions[i].s_file);
1255 pr_functions[i].numparms = LittleLong (dfunctions[i].numparms);
1256 pr_functions[i].locals = LittleLong (dfunctions[i].locals);
1257 memcpy(pr_functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1260 for (i=0 ; i<progs->numglobaldefs ; i++)
1262 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1263 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1264 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1267 // copy the progs fields to the new fields list
1268 for (i = 0;i < progs->numfielddefs;i++)
1270 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1271 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1272 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1273 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1274 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1277 // append the darkplaces fields
1278 for (i = 0;i < (int) DPFIELDS;i++)
1280 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1281 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1282 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1283 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1284 progs->entityfields += 3;
1286 progs->entityfields++;
1287 progs->numfielddefs++;
1290 for (i=0 ; i<progs->numglobals ; i++)
1291 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1293 // moved edict_size calculation down here, below field adding code
1294 // LordHavoc: this no longer includes the edict_t header
1295 pr_edict_size = progs->entityfields * 4;
1296 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1298 // LordHavoc: bounds check anything static
1299 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1305 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1306 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1309 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1310 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1312 // global global global
1347 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1348 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1350 // global none global
1356 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1357 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1373 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1374 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1388 if ((unsigned short) st->a >= progs->numglobals)
1389 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1392 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1397 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1398 PR_Execute_ProgsLoaded();
1403 void PR_Fields_f (void)
1405 int i, j, ednum, used, usedamount;
1407 char tempstring[5000], tempstring2[260], *name;
1413 Con_Printf("no progs loaded\n");
1416 counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1417 for (ednum = 0;ednum < MAX_EDICTS;ednum++)
1419 ed = EDICT_NUM(ednum);
1422 for (i = 1;i < progs->numfielddefs;i++)
1424 d = &pr_fielddefs[i];
1425 name = PR_GetString(d->s_name);
1426 if (name[strlen(name)-2] == '_')
1427 continue; // skip _x, _y, _z vars
1428 v = (int *)((char *)ed->v + d->ofs*4);
1429 // if the value is still all 0, skip the field
1430 for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1443 for (i = 0;i < progs->numfielddefs;i++)
1445 d = &pr_fielddefs[i];
1446 name = PR_GetString(d->s_name);
1447 if (name[strlen(name)-2] == '_')
1448 continue; // skip _x, _y, _z vars
1449 switch(d->type & ~DEF_SAVEGLOBAL)
1452 strcat(tempstring, "string ");
1455 strcat(tempstring, "entity ");
1458 strcat(tempstring, "function ");
1461 strcat(tempstring, "field ");
1464 strcat(tempstring, "void ");
1467 strcat(tempstring, "float ");
1470 strcat(tempstring, "vector ");
1473 strcat(tempstring, "pointer ");
1476 sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1477 strcat(tempstring, tempstring2);
1480 if (strlen(name) > 256)
1482 strncpy(tempstring2, name, 256);
1483 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1484 tempstring2[259] = 0;
1487 strcat(tempstring, name);
1488 for (j = strlen(name);j < 25;j++)
1489 strcat(tempstring, " ");
1490 sprintf(tempstring2, "%5d", counts[i]);
1491 strcat(tempstring, tempstring2);
1492 strcat(tempstring, "\n");
1493 if (strlen(tempstring) >= 4096)
1495 Con_Printf("%s", tempstring);
1501 usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1505 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);
1508 void PR_Globals_f (void)
1513 Con_Printf("no progs loaded\n");
1516 for (i = 0;i < progs->numglobaldefs;i++)
1517 Con_Printf("%s\n", PR_GetString(pr_globaldefs[i].s_name));
1518 Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1526 extern void PR_Cmd_Init(void);
1529 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1530 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1531 Cmd_AddCommand ("edictcount", ED_Count);
1532 Cmd_AddCommand ("profile", PR_Profile_f);
1533 Cmd_AddCommand ("pr_fields", PR_Fields_f);
1534 Cmd_AddCommand ("pr_globals", PR_Globals_f);
1535 Cvar_RegisterVariable (&pr_checkextension);
1536 Cvar_RegisterVariable (&nomonsters);
1537 Cvar_RegisterVariable (&gamecfg);
1538 Cvar_RegisterVariable (&scratch1);
1539 Cvar_RegisterVariable (&scratch2);
1540 Cvar_RegisterVariable (&scratch3);
1541 Cvar_RegisterVariable (&scratch4);
1542 Cvar_RegisterVariable (&savedgamecfg);
1543 Cvar_RegisterVariable (&saved1);
1544 Cvar_RegisterVariable (&saved2);
1545 Cvar_RegisterVariable (&saved3);
1546 Cvar_RegisterVariable (&saved4);
1547 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1548 Cvar_RegisterVariable (&decors);
1549 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1550 if (gamemode == GAME_NEHAHRA)
1552 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1553 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1554 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1555 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1556 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1557 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1558 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1559 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1560 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1561 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1563 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1564 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1565 Cvar_RegisterVariable (&pr_boundscheck);
1566 Cvar_RegisterVariable (&pr_traceqc);
1568 progs_mempool = Mem_AllocPool("progs.dat");
1569 edictstring_mempool = Mem_AllocPool("edict strings");
1574 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1575 edict_t *EDICT_NUM_ERROR(int n, char *filename, int fileline)
1577 Host_Error ("EDICT_NUM: bad number %i (called at %f:%i)", n, filename, fileline);
1582 int NUM_FOR_EDICT_ERROR(edict_t *e)
1584 Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1588 int NUM_FOR_EDICT(edict_t *e)
1592 if ((unsigned int)n >= MAX_EDICTS)
1593 Host_Error ("NUM_FOR_EDICT: bad pointer");
1597 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1599 // return e - sv.edicts;
1602 //#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1603 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1604 int EDICT_TO_PROG(edict_t *e)
1608 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1609 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1610 return n;// EXPERIMENTAL
1611 //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1613 edict_t *PROG_TO_EDICT(int n)
1615 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1616 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1617 return sv.edicts + n; // EXPERIMENTAL
1618 //return sv.edicts + ((n) / (progs->entityfields * 4));