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 *serverprogs_mempool;
39 int type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
41 ddef_t *ED_FieldAtOfs(int ofs);
42 qboolean ED_ParseEpair(edict_t *ent, ddef_t *key, const char *s);
44 cvar_t pr_checkextension = {CVAR_READONLY, "pr_checkextension", "1"};
45 cvar_t nomonsters = {0, "nomonsters", "0"};
46 cvar_t gamecfg = {0, "gamecfg", "0"};
47 cvar_t scratch1 = {0, "scratch1", "0"};
48 cvar_t scratch2 = {0,"scratch2", "0"};
49 cvar_t scratch3 = {0, "scratch3", "0"};
50 cvar_t scratch4 = {0, "scratch4", "0"};
51 cvar_t savedgamecfg = {CVAR_SAVE, "savedgamecfg", "0"};
52 cvar_t saved1 = {CVAR_SAVE, "saved1", "0"};
53 cvar_t saved2 = {CVAR_SAVE, "saved2", "0"};
54 cvar_t saved3 = {CVAR_SAVE, "saved3", "0"};
55 cvar_t saved4 = {CVAR_SAVE, "saved4", "0"};
56 cvar_t decors = {0, "decors", "0"};
57 cvar_t nehx00 = {0, "nehx00", "0"};cvar_t nehx01 = {0, "nehx01", "0"};
58 cvar_t nehx02 = {0, "nehx02", "0"};cvar_t nehx03 = {0, "nehx03", "0"};
59 cvar_t nehx04 = {0, "nehx04", "0"};cvar_t nehx05 = {0, "nehx05", "0"};
60 cvar_t nehx06 = {0, "nehx06", "0"};cvar_t nehx07 = {0, "nehx07", "0"};
61 cvar_t nehx08 = {0, "nehx08", "0"};cvar_t nehx09 = {0, "nehx09", "0"};
62 cvar_t nehx10 = {0, "nehx10", "0"};cvar_t nehx11 = {0, "nehx11", "0"};
63 cvar_t nehx12 = {0, "nehx12", "0"};cvar_t nehx13 = {0, "nehx13", "0"};
64 cvar_t nehx14 = {0, "nehx14", "0"};cvar_t nehx15 = {0, "nehx15", "0"};
65 cvar_t nehx16 = {0, "nehx16", "0"};cvar_t nehx17 = {0, "nehx17", "0"};
66 cvar_t nehx18 = {0, "nehx18", "0"};cvar_t nehx19 = {0, "nehx19", "0"};
67 cvar_t cutscene = {0, "cutscene", "1"};
68 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
69 cvar_t pr_boundscheck = {0, "pr_boundscheck", "1"};
70 // LordHavoc: prints every opcode as it executes - warning: this is significant spew
71 cvar_t pr_traceqc = {0, "pr_traceqc", "0"};
73 #define MAX_FIELD_LEN 64
74 #define GEFV_CACHESIZE 2
78 char field[MAX_FIELD_LEN];
81 static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};
83 ddef_t *ED_FindField (const char *name);
84 mfunction_t *ED_FindFunction (const char *name);
86 // LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue... these are defined as externs in progs.h
102 int eval_renderamt; // HalfLife support
103 int eval_rendermode; // HalfLife support
105 int eval_ammo_shells1;
106 int eval_ammo_nails1;
107 int eval_ammo_lava_nails;
108 int eval_ammo_rockets1;
109 int eval_ammo_multi_rockets;
110 int eval_ammo_cells1;
111 int eval_ammo_plasma;
113 int eval_pitch_speed;
114 int eval_viewmodelforclient;
115 int eval_nodrawtoclient;
116 int eval_exteriormodeltoclient;
117 int eval_drawonlytoclient;
121 int eval_punchvector;
123 int eval_clientcolors;
130 int eval_cursor_active;
131 int eval_cursor_screen;
132 int eval_cursor_trace_start;
133 int eval_cursor_trace_endpos;
134 int eval_cursor_trace_ent;
136 int eval_playermodel;
139 mfunction_t *SV_PlayerPhysicsQC;
140 mfunction_t *EndFrameQC;
141 //KrimZon - SERVER COMMANDS IN QUAKEC
142 mfunction_t *SV_ParseClientCommandQC;
144 int FindFieldOffset(const char *field)
147 d = ED_FindField(field);
153 void FindEdictFieldOffsets(void)
155 eval_gravity = FindFieldOffset("gravity");
156 eval_button3 = FindFieldOffset("button3");
157 eval_button4 = FindFieldOffset("button4");
158 eval_button5 = FindFieldOffset("button5");
159 eval_button6 = FindFieldOffset("button6");
160 eval_button7 = FindFieldOffset("button7");
161 eval_button8 = FindFieldOffset("button8");
162 eval_buttonuse = FindFieldOffset("buttonuse");
163 eval_buttonchat = FindFieldOffset("buttonchat");
164 eval_glow_size = FindFieldOffset("glow_size");
165 eval_glow_trail = FindFieldOffset("glow_trail");
166 eval_glow_color = FindFieldOffset("glow_color");
167 eval_items2 = FindFieldOffset("items2");
168 eval_scale = FindFieldOffset("scale");
169 eval_alpha = FindFieldOffset("alpha");
170 eval_renderamt = FindFieldOffset("renderamt"); // HalfLife support
171 eval_rendermode = FindFieldOffset("rendermode"); // HalfLife support
172 eval_fullbright = FindFieldOffset("fullbright");
173 eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
174 eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
175 eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
176 eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
177 eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
178 eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
179 eval_ammo_plasma = FindFieldOffset("ammo_plasma");
180 eval_idealpitch = FindFieldOffset("idealpitch");
181 eval_pitch_speed = FindFieldOffset("pitch_speed");
182 eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
183 eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
184 eval_exteriormodeltoclient = FindFieldOffset("exteriormodeltoclient");
185 eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
186 eval_ping = FindFieldOffset("ping");
187 eval_movement = FindFieldOffset("movement");
188 eval_pmodel = FindFieldOffset("pmodel");
189 eval_punchvector = FindFieldOffset("punchvector");
190 eval_viewzoom = FindFieldOffset("viewzoom");
191 eval_clientcolors = FindFieldOffset("clientcolors");
192 eval_tag_entity = FindFieldOffset("tag_entity");
193 eval_tag_index = FindFieldOffset("tag_index");
194 eval_light_lev = FindFieldOffset("light_lev");
195 eval_color = FindFieldOffset("color");
196 eval_style = FindFieldOffset("style");
197 eval_pflags = FindFieldOffset("pflags");
198 eval_cursor_active = FindFieldOffset("cursor_active");
199 eval_cursor_screen = FindFieldOffset("cursor_screen");
200 eval_cursor_trace_start = FindFieldOffset("cursor_trace_start");
201 eval_cursor_trace_endpos = FindFieldOffset("cursor_trace_endpos");
202 eval_cursor_trace_ent = FindFieldOffset("cursor_trace_ent");
203 eval_colormod = FindFieldOffset("colormod");
204 eval_playermodel = FindFieldOffset("playermodel");
205 eval_playerskin = FindFieldOffset("playerskin");
207 // LordHavoc: allowing QuakeC to override the player movement code
208 SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
209 // LordHavoc: support for endframe
210 EndFrameQC = ED_FindFunction ("EndFrame");
211 //KrimZon - SERVER COMMANDS IN QUAKEC
212 SV_ParseClientCommandQC = ED_FindFunction ("SV_ParseClientCommand");
219 Sets everything to NULL
222 void ED_ClearEdict (edict_t *e)
225 memset (e->v, 0, progs->entityfields * 4);
227 // LordHavoc: for consistency set these here
228 num = NUM_FOR_EDICT(e) - 1;
229 if (num >= 0 && num < svs.maxclients)
232 // set colormap and team on newly created player entity
233 e->v->colormap = num + 1;
234 e->v->team = (svs.clients[num].colors & 15) + 1;
235 // set netname/clientcolors back to client values so that
236 // DP_SV_CLIENTNAME and DPV_SV_CLIENTCOLORS will not immediately
238 e->v->netname = PR_SetString(svs.clients[num].name);
239 if ((val = GETEDICTFIELDVALUE(e, eval_clientcolors)))
240 val->_float = svs.clients[num].colors;
241 // NEXUIZ_PLAYERMODEL and NEXUIZ_PLAYERSKIN
242 if( eval_playermodel )
243 GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PR_SetString(svs.clients[num].playermodel);
244 if( eval_playerskin )
245 GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PR_SetString(svs.clients[num].playerskin);
253 Either finds a free edict, or allocates a new one.
254 Try to avoid reusing an entity that was recently freed, because it
255 can cause the client to think the entity morphed into something else
256 instead of being removed and recreated, which can cause interpolated
257 angles and bad trails.
260 edict_t *ED_Alloc (void)
265 for (i = svs.maxclients + 1;i < sv.num_edicts;i++)
268 // the first couple seconds of server time can involve a lot of
269 // freeing and allocating, so relax the replacement policy
270 if (e->e->free && ( e->e->freetime < 2 || sv.time - e->e->freetime > 0.5 ) )
278 Host_Error ("ED_Alloc: no free edicts");
281 if (sv.num_edicts >= sv.max_edicts)
293 Marks the edict as free
294 FIXME: walk all entities and NULL out references to this entity
297 void ED_Free (edict_t *ed)
299 SV_UnlinkEdict (ed); // unlink from world bsp
303 ed->v->takedamage = 0;
304 ed->v->modelindex = 0;
308 VectorClear(ed->v->origin);
309 VectorClear(ed->v->angles);
310 ed->v->nextthink = -1;
313 ed->e->freetime = sv.time;
316 //===========================================================================
323 ddef_t *ED_GlobalAtOfs (int ofs)
328 for (i=0 ; i<progs->numglobaldefs ; i++)
330 def = &pr_globaldefs[i];
342 ddef_t *ED_FieldAtOfs (int ofs)
347 for (i=0 ; i<progs->numfielddefs ; i++)
349 def = &pr_fielddefs[i];
361 ddef_t *ED_FindField (const char *name)
366 for (i=0 ; i<progs->numfielddefs ; i++)
368 def = &pr_fielddefs[i];
369 if (!strcmp(PR_GetString(def->s_name), name))
380 ddef_t *ED_FindGlobal (const char *name)
385 for (i=0 ; i<progs->numglobaldefs ; i++)
387 def = &pr_globaldefs[i];
388 if (!strcmp(PR_GetString(def->s_name), name))
400 mfunction_t *ED_FindFunction (const char *name)
405 for (i=0 ; i<progs->numfunctions ; i++)
407 func = &pr_functions[i];
408 if (!strcmp(PR_GetString(func->s_name), name))
419 Returns a string describing *data in a type specific manner
422 //int NoCrash_NUM_FOR_EDICT(edict_t *e);
423 char *PR_ValueString (etype_t type, eval_t *val)
425 static char line[1024]; // LordHavoc: enlarged a bit (was 256)
430 type &= ~DEF_SAVEGLOBAL;
435 strlcpy (line, PR_GetString (val->string), sizeof (line));
438 //n = NoCrash_NUM_FOR_EDICT(PROG_TO_EDICT(val->edict));
440 if (n < 0 || n >= MAX_EDICTS)
441 dpsnprintf (line, sizeof (line), "entity %i (invalid!)", n);
443 dpsnprintf (line, sizeof (line), "entity %i", n);
446 f = pr_functions + val->function;
447 dpsnprintf (line, sizeof (line), "%s()", PR_GetString(f->s_name));
450 def = ED_FieldAtOfs ( val->_int );
451 dpsnprintf (line, sizeof (line), ".%s", PR_GetString(def->s_name));
454 dpsnprintf (line, sizeof (line), "void");
457 // LordHavoc: changed from %5.1f to %10.4f
458 dpsnprintf (line, sizeof (line), "%10.4f", val->_float);
461 // LordHavoc: changed from %5.1f to %10.4f
462 dpsnprintf (line, sizeof (line), "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
465 dpsnprintf (line, sizeof (line), "pointer");
468 dpsnprintf (line, sizeof (line), "bad type %i", type);
479 Returns a string describing *data in a type specific manner
480 Easier to parse than PR_ValueString
483 char *PR_UglyValueString (etype_t type, eval_t *val)
485 static char line[4096];
491 type &= ~DEF_SAVEGLOBAL;
496 // Parse the string a bit to turn special characters
497 // (like newline, specifically) into escape codes,
498 // this fixes saving games from various mods
499 s = PR_GetString (val->string);
500 for (i = 0;i < (int)sizeof(line) - 2 && *s;)
519 dpsnprintf (line, sizeof (line), "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
522 f = pr_functions + val->function;
523 strlcpy (line, PR_GetString (f->s_name), sizeof (line));
526 def = ED_FieldAtOfs ( val->_int );
527 dpsnprintf (line, sizeof (line), ".%s", PR_GetString(def->s_name));
530 dpsnprintf (line, sizeof (line), "void");
533 dpsnprintf (line, sizeof (line), "%f", val->_float);
536 dpsnprintf (line, sizeof (line), "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
539 dpsnprintf (line, sizeof (line), "bad type %i", type);
550 Returns a string with a description and the contents of a global,
551 padded to 20 field width
554 char *PR_GlobalString (int ofs)
560 static char line[128];
562 val = (void *)&pr_globals[ofs];
563 def = ED_GlobalAtOfs(ofs);
565 dpsnprintf (line, sizeof (line), "%i(?)", ofs);
568 s = PR_ValueString (def->type, val);
569 dpsnprintf (line, sizeof (line), "%i(%s)%s", ofs, PR_GetString(def->s_name), s);
574 strlcat (line, " ", sizeof (line));
575 strlcat (line, " ", sizeof (line));
580 char *PR_GlobalStringNoContents (int ofs)
584 static char line[128];
586 def = ED_GlobalAtOfs(ofs);
588 dpsnprintf (line, sizeof (line), "%i(?)", ofs);
590 dpsnprintf (line, sizeof (line), "%i(%s)", ofs, PR_GetString(def->s_name));
594 strlcat (line, " ", sizeof (line));
595 strlcat (line, " ", sizeof (line));
608 // LordHavoc: optimized this to print out much more quickly (tempstring)
609 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
610 void ED_Print(edict_t *ed)
618 char tempstring[8192], tempstring2[260]; // temporary string buffers
627 dpsnprintf (tempstring, sizeof (tempstring), "\nEDICT %i:\n", NUM_FOR_EDICT(ed));
628 for (i=1 ; i<progs->numfielddefs ; i++)
630 d = &pr_fielddefs[i];
631 name = PR_GetString(d->s_name);
632 if (name[strlen(name)-2] == '_')
633 continue; // skip _x, _y, _z vars
635 v = (int *)((char *)ed->v + d->ofs*4);
637 // if the value is still all 0, skip the field
638 type = d->type & ~DEF_SAVEGLOBAL;
640 for (j=0 ; j<type_size[type] ; j++)
643 if (j == type_size[type])
646 if (strlen(name) > 256)
648 memcpy (tempstring2, name, 256);
649 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
650 tempstring2[259] = 0;
653 strlcat (tempstring, name, sizeof (tempstring));
654 for (l = strlen(name);l < 14;l++)
655 strcat(tempstring, " ");
656 strcat(tempstring, " ");
658 name = PR_ValueString(d->type, (eval_t *)v);
659 if (strlen(name) > 256)
661 memcpy(tempstring2, name, 256);
662 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
663 tempstring2[259] = 0;
666 strlcat (tempstring, name, sizeof (tempstring));
667 strlcat (tempstring, "\n", sizeof (tempstring));
668 if (strlen(tempstring) >= 4096)
670 Con_Print(tempstring);
675 Con_Print(tempstring);
685 void ED_Write (qfile_t *f, edict_t *ed)
701 for (i=1 ; i<progs->numfielddefs ; i++)
703 d = &pr_fielddefs[i];
704 name = PR_GetString(d->s_name);
705 if (name[strlen(name)-2] == '_')
706 continue; // skip _x, _y, _z vars
708 v = (int *)((char *)ed->v + d->ofs*4);
710 // if the value is still all 0, skip the field
711 type = d->type & ~DEF_SAVEGLOBAL;
712 for (j=0 ; j<type_size[type] ; j++)
715 if (j == type_size[type])
718 FS_Printf(f,"\"%s\" ",name);
719 FS_Printf(f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
725 void ED_PrintNum (int ent)
727 ED_Print(EDICT_NUM(ent));
734 For debugging, prints all the entities in the current server
737 void ED_PrintEdicts (void)
741 Con_Printf("%i entities\n", sv.num_edicts);
742 for (i=0 ; i<sv.num_edicts ; i++)
750 For debugging, prints a single edict
753 void ED_PrintEdict_f (void)
757 i = atoi (Cmd_Argv(1));
758 if (i < 0 || i >= sv.num_edicts)
760 Con_Print("Bad edict number\n");
777 int active, models, solid, step;
779 active = models = solid = step = 0;
780 for (i=0 ; i<sv.num_edicts ; i++)
790 if (ent->v->movetype == MOVETYPE_STEP)
794 Con_Printf("num_edicts:%3i\n", sv.num_edicts);
795 Con_Printf("active :%3i\n", active);
796 Con_Printf("view :%3i\n", models);
797 Con_Printf("touch :%3i\n", solid);
798 Con_Printf("step :%3i\n", step);
803 ==============================================================================
807 FIXME: need to tag constants, doesn't really work
808 ==============================================================================
816 void ED_WriteGlobals (qfile_t *f)
824 for (i=0 ; i<progs->numglobaldefs ; i++)
826 def = &pr_globaldefs[i];
828 if ( !(def->type & DEF_SAVEGLOBAL) )
830 type &= ~DEF_SAVEGLOBAL;
832 if (type != ev_string && type != ev_float && type != ev_entity)
835 name = PR_GetString(def->s_name);
836 FS_Printf(f,"\"%s\" ", name);
837 FS_Printf(f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
846 Console command to set a field of a specified edict
849 void ED_EdictSet_f(void)
856 Con_Print("edictset <edict number> <field> <value>\n");
859 ed = EDICT_NUM(atoi(Cmd_Argv(1)));
861 if((key = ED_FindField(Cmd_Argv(2))) == 0)
863 Con_Printf("Key %s not found !\n", Cmd_Argv(2));
867 ED_ParseEpair(ed, key, Cmd_Argv(3));
875 void ED_ParseGlobals (const char *data)
877 char keyname[1024]; // LordHavoc: good idea? bad idea? was 64
883 if (!COM_ParseToken(&data, false))
884 Host_Error ("ED_ParseEntity: EOF without closing brace");
885 if (com_token[0] == '}')
888 strcpy (keyname, com_token);
891 if (!COM_ParseToken(&data, false))
892 Host_Error ("ED_ParseEntity: EOF without closing brace");
894 if (com_token[0] == '}')
895 Host_Error ("ED_ParseEntity: closing brace without data");
897 key = ED_FindGlobal (keyname);
900 Con_DPrintf("'%s' is not a global\n", keyname);
904 if (!ED_ParseEpair(NULL, key, com_token))
905 Host_Error ("ED_ParseGlobals: parse error");
909 //============================================================================
917 char *ED_NewString (const char *string)
922 l = strlen(string) + 1;
926 for (i=0 ; i< l ; i++)
928 if (string[i] == '\\' && i < l-1)
931 if (string[i] == 'n')
933 else if (string[i] == 'r')
939 *new_p++ = string[i];
950 Can parse either fields or globals
951 returns false if error
954 qboolean ED_ParseEpair(edict_t *ent, ddef_t *key, const char *s)
962 val = (eval_t *)((int *)ent->v + key->ofs);
964 val = (eval_t *)((int *)pr_globals + key->ofs);
965 switch (key->type & ~DEF_SAVEGLOBAL)
968 val->string = PR_SetString(ED_NewString(s));
972 while (*s && *s <= ' ')
974 val->_float = atof(s);
978 for (i = 0;i < 3;i++)
980 while (*s && *s <= ' ')
983 val->vector[i] = atof(s);
992 while (*s && *s <= ' ')
995 if (i < 0 || i >= MAX_EDICTS)
996 Con_Printf("ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i)\n", i, MAX_EDICTS);
997 while (i >= sv.max_edicts)
999 // if SV_IncreaseEdicts was called the base pointer needs to be updated
1001 val = (eval_t *)((int *)ent->v + key->ofs);
1002 val->edict = EDICT_TO_PROG(EDICT_NUM(i));
1006 def = ED_FindField(s);
1009 Con_DPrintf("ED_ParseEpair: Can't find field %s\n", s);
1012 //val->_int = G_INT(def->ofs); // AK Please check this - seems to be an org. quake bug
1013 val->_int = def->ofs;
1017 func = ED_FindFunction(s);
1020 Con_Printf("ED_ParseEpair: Can't find function %s\n", s);
1023 val->function = func - pr_functions;
1027 Con_Printf("ED_ParseEpair: Unknown key->type %i for key \"%s\"\n", key->type, PR_GetString(key->s_name));
1034 ====================
1037 Parses an edict out of the given string, returning the new position
1038 ed should be a properly initialized empty edict.
1039 Used for initial level load and for savegames.
1040 ====================
1042 const char *ED_ParseEdict (const char *data, edict_t *ent)
1053 if (ent != sv.edicts) // hack
1054 memset (ent->v, 0, progs->entityfields * 4);
1056 // go through all the dictionary pairs
1060 if (!COM_ParseToken(&data, false))
1061 Host_Error ("ED_ParseEntity: EOF without closing brace");
1062 if (com_token[0] == '}')
1065 // anglehack is to allow QuakeEd to write single scalar angles
1066 // and allow them to be turned into vectors. (FIXME...)
1067 anglehack = !strcmp (com_token, "angle");
1069 strlcpy (com_token, "angles", sizeof (com_token));
1071 // FIXME: change light to _light to get rid of this hack
1072 if (!strcmp(com_token, "light"))
1073 strlcpy (com_token, "light_lev", sizeof (com_token)); // hack for single light def
1075 strlcpy (keyname, com_token, sizeof (keyname));
1077 // another hack to fix heynames with trailing spaces
1078 n = strlen(keyname);
1079 while (n && keyname[n-1] == ' ')
1086 if (!COM_ParseToken(&data, false))
1087 Host_Error ("ED_ParseEntity: EOF without closing brace");
1089 if (com_token[0] == '}')
1090 Host_Error ("ED_ParseEntity: closing brace without data");
1094 // keynames with a leading underscore are used for utility comments,
1095 // and are immediately discarded by quake
1096 if (keyname[0] == '_')
1099 key = ED_FindField (keyname);
1102 Con_DPrintf("'%s' is not a field\n", keyname);
1109 strlcpy (temp, com_token, sizeof (temp));
1110 dpsnprintf (com_token, sizeof (com_token), "0 %s 0", temp);
1113 if (!ED_ParseEpair(ent, key, com_token))
1114 Host_Error ("ED_ParseEdict: parse error");
1118 ent->e->free = true;
1128 The entities are directly placed in the array, rather than allocated with
1129 ED_Alloc, because otherwise an error loading the map would have entity
1130 number references out of order.
1132 Creates a server's entity / program execution context by
1133 parsing textual entity definitions out of an ent file.
1135 Used for both fresh maps and savegame loads. A fresh map would also need
1136 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1139 void ED_LoadFromFile (const char *data)
1142 int parsed, inhibited, spawned, died;
1150 pr_global_struct->time = sv.time;
1155 // parse the opening brace
1156 if (!COM_ParseToken(&data, false))
1158 if (com_token[0] != '{')
1159 Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1165 data = ED_ParseEdict (data, ent);
1168 // remove things from different skill levels or deathmatch
1169 if (gamemode != GAME_TRANSFUSION) //Transfusion does this in QC
1171 if (deathmatch.integer)
1173 if (((int)ent->v->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1180 else if ((current_skill <= 0 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_EASY ))
1181 || (current_skill == 1 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_MEDIUM))
1182 || (current_skill >= 2 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_HARD )))
1190 // immediately call spawn function
1192 if (!ent->v->classname)
1194 Con_Print("No classname for:\n");
1200 // look for the spawn function
1201 func = ED_FindFunction (PR_GetString(ent->v->classname));
1205 if (developer.integer) // don't confuse non-developers with errors
1207 Con_Print("No spawn function for:\n");
1214 pr_global_struct->self = EDICT_TO_PROG(ent);
1215 PR_ExecuteProgram (func - pr_functions, "QC function spawn is missing");
1221 Con_DPrintf("%i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", parsed, inhibited, spawned, died, spawned - died);
1225 typedef struct dpfield_s
1232 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1234 dpfield_t dpfields[] =
1236 {ev_entity, "cursor_trace_ent"},
1237 {ev_entity, "drawonlytoclient"},
1238 {ev_entity, "exteriormodeltoclient"},
1239 {ev_entity, "nodrawtoclient"},
1240 {ev_entity, "tag_entity"},
1241 {ev_entity, "viewmodelforclient"},
1242 {ev_float, "alpha"},
1243 {ev_float, "ammo_cells1"},
1244 {ev_float, "ammo_lava_nails"},
1245 {ev_float, "ammo_multi_rockets"},
1246 {ev_float, "ammo_nails1"},
1247 {ev_float, "ammo_plasma"},
1248 {ev_float, "ammo_rockets1"},
1249 {ev_float, "ammo_shells1"},
1250 {ev_float, "button3"},
1251 {ev_float, "button4"},
1252 {ev_float, "button5"},
1253 {ev_float, "button6"},
1254 {ev_float, "button7"},
1255 {ev_float, "button8"},
1256 {ev_float, "buttonchat"},
1257 {ev_float, "buttonuse"},
1258 {ev_float, "clientcolors"},
1259 {ev_float, "cursor_active"},
1260 {ev_float, "fullbright"},
1261 {ev_float, "glow_color"},
1262 {ev_float, "glow_size"},
1263 {ev_float, "glow_trail"},
1264 {ev_float, "gravity"},
1265 {ev_float, "idealpitch"},
1266 {ev_float, "items2"},
1267 {ev_float, "light_lev"},
1268 {ev_float, "pflags"},
1270 {ev_float, "pitch_speed"},
1271 {ev_float, "pmodel"},
1272 {ev_float, "renderamt"}, // HalfLife support
1273 {ev_float, "rendermode"}, // HalfLife support
1274 {ev_float, "scale"},
1275 {ev_float, "style"},
1276 {ev_float, "tag_index"},
1277 {ev_float, "viewzoom"},
1278 {ev_vector, "color"},
1279 {ev_vector, "colormod"},
1280 {ev_vector, "cursor_screen"},
1281 {ev_vector, "cursor_trace_endpos"},
1282 {ev_vector, "cursor_trace_start"},
1283 {ev_vector, "movement"},
1284 {ev_vector, "punchvector"},
1285 {ev_string, "playermodel"},
1286 {ev_string, "playerskin"}
1294 extern void PR_Cmd_Reset (void);
1295 void PR_LoadProgs (const char *progsname)
1299 ddef_t *infielddefs;
1300 dfunction_t *dfunctions;
1302 if (!progsname || !*progsname)
1303 Host_Error("PR_LoadProgs: passed empty progsname");
1305 // flush the non-C variable lookup cache
1306 for (i=0 ; i<GEFV_CACHESIZE ; i++)
1307 gefvCache[i].field[0] = 0;
1311 progs = (dprograms_t *)FS_LoadFile (progsname, serverprogs_mempool, false);
1313 Host_Error ("PR_LoadProgs: couldn't load %s", progsname);
1315 Con_DPrintf("Programs occupy %iK.\n", fs_filesize/1024);
1317 pr_crc = CRC_Block((qbyte *)progs, fs_filesize);
1319 // byte swap the header
1320 for (i = 0;i < (int) sizeof(*progs) / 4;i++)
1321 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1323 if (progs->version != PROG_VERSION)
1324 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1325 if (progs->crc != PROGHEADER_CRC && progs->crc != 32401) // tenebrae crc also allowed
1326 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1328 //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1329 dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1330 pr_strings = (char *)progs + progs->ofs_strings;
1331 pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1333 // we need to expand the fielddefs list to include all the engine fields,
1334 // so allocate a new place for it
1335 infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1336 pr_fielddefs = PR_Alloc((progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1337 pr_functions = PR_Alloc(sizeof(mfunction_t) * progs->numfunctions);
1339 pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1341 // moved edict_size calculation down below field adding code
1343 pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1344 pr_globals = (float *)pr_global_struct;
1346 // byte swap the lumps
1347 for (i=0 ; i<progs->numstatements ; i++)
1349 pr_statements[i].op = LittleShort(pr_statements[i].op);
1350 pr_statements[i].a = LittleShort(pr_statements[i].a);
1351 pr_statements[i].b = LittleShort(pr_statements[i].b);
1352 pr_statements[i].c = LittleShort(pr_statements[i].c);
1355 for (i = 0;i < progs->numfunctions;i++)
1357 pr_functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1358 pr_functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1359 pr_functions[i].s_name = LittleLong (dfunctions[i].s_name);
1360 pr_functions[i].s_file = LittleLong (dfunctions[i].s_file);
1361 pr_functions[i].numparms = LittleLong (dfunctions[i].numparms);
1362 pr_functions[i].locals = LittleLong (dfunctions[i].locals);
1363 memcpy(pr_functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1366 for (i=0 ; i<progs->numglobaldefs ; i++)
1368 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1369 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1370 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1373 // copy the progs fields to the new fields list
1374 for (i = 0;i < progs->numfielddefs;i++)
1376 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1377 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1378 Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1379 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1380 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1383 // append the darkplaces fields
1384 for (i = 0;i < (int) DPFIELDS;i++)
1386 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1387 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1388 pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
1389 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1390 progs->entityfields += 3;
1392 progs->entityfields++;
1393 progs->numfielddefs++;
1396 for (i=0 ; i<progs->numglobals ; i++)
1397 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1399 // moved edict_size calculation down here, below field adding code
1400 // LordHavoc: this no longer includes the edict_t header
1401 pr_edict_size = progs->entityfields * 4;
1402 pr_edictareasize = pr_edict_size * MAX_EDICTS;
1404 // LordHavoc: bounds check anything static
1405 for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1411 if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1412 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1415 if (st->a + i < 0 || st->a + i >= progs->numstatements)
1416 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1418 // global global global
1453 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1454 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1456 // global none global
1462 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1463 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1479 if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1480 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1494 if ((unsigned short) st->a >= progs->numglobals)
1495 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1498 Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1503 FindEdictFieldOffsets(); // LordHavoc: update field offset list
1504 PR_Execute_ProgsLoaded();
1509 void PR_Fields_f (void)
1511 int i, j, ednum, used, usedamount;
1513 char tempstring[5000], tempstring2[260], *name;
1519 Con_Print("no progs loaded\n");
1522 counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1523 for (ednum = 0;ednum < sv.max_edicts;ednum++)
1525 ed = EDICT_NUM(ednum);
1528 for (i = 1;i < progs->numfielddefs;i++)
1530 d = &pr_fielddefs[i];
1531 name = PR_GetString(d->s_name);
1532 if (name[strlen(name)-2] == '_')
1533 continue; // skip _x, _y, _z vars
1534 v = (int *)((char *)ed->v + d->ofs*4);
1535 // if the value is still all 0, skip the field
1536 for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1549 for (i = 0;i < progs->numfielddefs;i++)
1551 d = &pr_fielddefs[i];
1552 name = PR_GetString(d->s_name);
1553 if (name[strlen(name)-2] == '_')
1554 continue; // skip _x, _y, _z vars
1555 switch(d->type & ~DEF_SAVEGLOBAL)
1558 strlcat (tempstring, "string ", sizeof (tempstring));
1561 strlcat (tempstring, "entity ", sizeof (tempstring));
1564 strlcat (tempstring, "function ", sizeof (tempstring));
1567 strlcat (tempstring, "field ", sizeof (tempstring));
1570 strlcat (tempstring, "void ", sizeof (tempstring));
1573 strlcat (tempstring, "float ", sizeof (tempstring));
1576 strlcat (tempstring, "vector ", sizeof (tempstring));
1579 strlcat (tempstring, "pointer ", sizeof (tempstring));
1582 dpsnprintf (tempstring2, sizeof (tempstring2), "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1583 strlcat (tempstring, tempstring2, sizeof (tempstring));
1586 if (strlen(name) > 256)
1588 memcpy(tempstring2, name, 256);
1589 tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1590 tempstring2[259] = 0;
1593 strcat (tempstring, name);
1594 for (j = strlen(name);j < 25;j++)
1595 strcat(tempstring, " ");
1596 dpsnprintf (tempstring2, sizeof (tempstring2), "%5d", counts[i]);
1597 strlcat (tempstring, tempstring2, sizeof (tempstring));
1598 strlcat (tempstring, "\n", sizeof (tempstring));
1599 if (strlen(tempstring) >= 4096)
1601 Con_Print(tempstring);
1607 usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1611 Con_Printf("%i entity fields (%i in use), totalling %i bytes per edict (%i in use), %i edicts allocated, %i bytes total spent on edict fields (%i needed)\n", progs->entityfields, used, progs->entityfields * 4, usedamount * 4, sv.max_edicts, progs->entityfields * 4 * sv.max_edicts, usedamount * 4 * sv.max_edicts);
1614 void PR_Globals_f (void)
1619 Con_Print("no progs loaded\n");
1622 for (i = 0;i < progs->numglobaldefs;i++)
1623 Con_Printf("%s\n", PR_GetString(pr_globaldefs[i].s_name));
1624 Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1632 extern void PR_Cmd_Init(void);
1635 Cmd_AddCommand ("edict", ED_PrintEdict_f);
1636 Cmd_AddCommand ("edicts", ED_PrintEdicts);
1637 Cmd_AddCommand ("edictcount", ED_Count);
1638 Cmd_AddCommand ("edictset", ED_EdictSet_f);
1639 Cmd_AddCommand ("profile", PR_Profile_f);
1640 Cmd_AddCommand ("pr_fields", PR_Fields_f);
1641 Cmd_AddCommand ("pr_globals", PR_Globals_f);
1642 Cvar_RegisterVariable (&pr_checkextension);
1643 Cvar_RegisterVariable (&nomonsters);
1644 Cvar_RegisterVariable (&gamecfg);
1645 Cvar_RegisterVariable (&scratch1);
1646 Cvar_RegisterVariable (&scratch2);
1647 Cvar_RegisterVariable (&scratch3);
1648 Cvar_RegisterVariable (&scratch4);
1649 Cvar_RegisterVariable (&savedgamecfg);
1650 Cvar_RegisterVariable (&saved1);
1651 Cvar_RegisterVariable (&saved2);
1652 Cvar_RegisterVariable (&saved3);
1653 Cvar_RegisterVariable (&saved4);
1654 // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1655 Cvar_RegisterVariable (&decors);
1656 // LordHavoc: Nehahra uses these to pass data around cutscene demos
1657 if (gamemode == GAME_NEHAHRA)
1659 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1660 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1661 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1662 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1663 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1664 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1665 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1666 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1667 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1668 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1670 Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1671 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1672 Cvar_RegisterVariable (&pr_boundscheck);
1673 Cvar_RegisterVariable (&pr_traceqc);
1675 serverprogs_mempool = Mem_AllocPool("server progs", 0, NULL);
1685 extern void PR_Cmd_Shutdown(void);
1686 void PR_Shutdown (void)
1690 Mem_FreePool(&serverprogs_mempool);
1693 void *PR_Alloc(size_t buffersize)
1695 return Mem_Alloc(serverprogs_mempool, buffersize);
1698 void PR_Free(void *buffer)
1703 void PR_FreeAll(void)
1706 pr_fielddefs = NULL;
1707 pr_functions = NULL;
1708 Mem_EmptyPool(serverprogs_mempool);
1711 // LordHavoc: turned EDICT_NUM into a #define for speed reasons
1712 edict_t *EDICT_NUM_ERROR(int n, char *filename, int fileline)
1714 Host_Error ("EDICT_NUM: bad number %i (called at %s:%i)", n, filename, fileline);
1719 int NUM_FOR_EDICT_ERROR(edict_t *e)
1721 Host_Error ("NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, sv.edicts, e - sv.edicts);
1725 int NUM_FOR_EDICT(edict_t *e)
1729 if ((unsigned int)n >= MAX_EDICTS)
1730 Host_Error ("NUM_FOR_EDICT: bad pointer");
1734 //int NoCrash_NUM_FOR_EDICT(edict_t *e)
1736 // return e - sv.edicts;
1739 //#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields))
1740 //#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4)))
1741 int EDICT_TO_PROG(edict_t *e)
1745 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1746 Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts);
1747 return n;// EXPERIMENTAL
1748 //return (qbyte *)e->v - (qbyte *)sv.edictsfields;
1750 edict_t *PROG_TO_EDICT(int n)
1752 if ((unsigned int)n >= (unsigned int)sv.max_edicts)
1753 Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n);
1754 return sv.edicts + n; // EXPERIMENTAL
1755 //return sv.edicts + ((n) / (progs->entityfields * 4));