]> git.xonotic.org Git - xonotic/darkplaces.git/blob - pr_edict.c
default offsetmapping off (as it messes up model skins)
[xonotic/darkplaces.git] / pr_edict.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
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.
8
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.
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20 // sv_edict.c -- entity dictionary
21
22 #include "quakedef.h"
23
24 dprograms_t             *progs;
25 mfunction_t             *prog->functions;
26 char                    *pr_strings;
27 int                             pr_stringssize;
28 ddef_t                  *pr_fielddefs;
29 ddef_t                  *pr_globaldefs;
30 dstatement_t    *pr_statements;
31 globalvars_t    *pr_global_struct;
32 float                   *pr_globals;                    // same as pr_global_struct
33 int                             prog->edict_size;                       // in bytes
34 int                             pr_edictareasize;               // LordHavoc: in bytes
35
36 int                             pr_maxknownstrings;
37 int                             pr_numknownstrings;
38 const char              **pr_knownstrings;
39
40 unsigned short  pr_crc;
41
42 mempool_t               *serverprogs_mempool;
43
44 int             type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
45
46 ddef_t *ED_FieldAtOfs(int ofs);
47 qboolean ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s);
48
49 cvar_t  pr_checkextension = {CVAR_READONLY, "pr_checkextension", "1"};
50 cvar_t  nomonsters = {0, "nomonsters", "0"};
51 cvar_t  gamecfg = {0, "gamecfg", "0"};
52 cvar_t  scratch1 = {0, "scratch1", "0"};
53 cvar_t  scratch2 = {0,"scratch2", "0"};
54 cvar_t  scratch3 = {0, "scratch3", "0"};
55 cvar_t  scratch4 = {0, "scratch4", "0"};
56 cvar_t  savedgamecfg = {CVAR_SAVE, "savedgamecfg", "0"};
57 cvar_t  saved1 = {CVAR_SAVE, "saved1", "0"};
58 cvar_t  saved2 = {CVAR_SAVE, "saved2", "0"};
59 cvar_t  saved3 = {CVAR_SAVE, "saved3", "0"};
60 cvar_t  saved4 = {CVAR_SAVE, "saved4", "0"};
61 cvar_t  decors = {0, "decors", "0"};
62 cvar_t  nehx00 = {0, "nehx00", "0"};cvar_t      nehx01 = {0, "nehx01", "0"};
63 cvar_t  nehx02 = {0, "nehx02", "0"};cvar_t      nehx03 = {0, "nehx03", "0"};
64 cvar_t  nehx04 = {0, "nehx04", "0"};cvar_t      nehx05 = {0, "nehx05", "0"};
65 cvar_t  nehx06 = {0, "nehx06", "0"};cvar_t      nehx07 = {0, "nehx07", "0"};
66 cvar_t  nehx08 = {0, "nehx08", "0"};cvar_t      nehx09 = {0, "nehx09", "0"};
67 cvar_t  nehx10 = {0, "nehx10", "0"};cvar_t      nehx11 = {0, "nehx11", "0"};
68 cvar_t  nehx12 = {0, "nehx12", "0"};cvar_t      nehx13 = {0, "nehx13", "0"};
69 cvar_t  nehx14 = {0, "nehx14", "0"};cvar_t      nehx15 = {0, "nehx15", "0"};
70 cvar_t  nehx16 = {0, "nehx16", "0"};cvar_t      nehx17 = {0, "nehx17", "0"};
71 cvar_t  nehx18 = {0, "nehx18", "0"};cvar_t      nehx19 = {0, "nehx19", "0"};
72 cvar_t  cutscene = {0, "cutscene", "1"};
73 // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
74 cvar_t  pr_boundscheck = {0, "pr_boundscheck", "1"};
75 // LordHavoc: prints every opcode as it executes - warning: this is significant spew
76 cvar_t  pr_traceqc = {0, "pr_traceqc", "0"};
77
78 #define MAX_FIELD_LEN   64
79 #define GEFV_CACHESIZE  2
80
81 typedef struct {
82         ddef_t  *pcache;
83         char    field[MAX_FIELD_LEN];
84 } gefv_cache;
85
86 static gefv_cache       gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};
87
88 ddef_t *ED_FindField (const char *name);
89 mfunction_t *PRVM_ED_FindFunction (const char *name);
90
91 // LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue...  these are defined as externs in progs.h
92 int eval_gravity;
93 int eval_button3;
94 int eval_button4;
95 int eval_button5;
96 int eval_button6;
97 int eval_button7;
98 int eval_button8;
99 int eval_buttonuse;
100 int eval_buttonchat;
101 int eval_glow_size;
102 int eval_glow_trail;
103 int eval_glow_color;
104 int eval_items2;
105 int eval_scale;
106 int eval_alpha;
107 int eval_renderamt; // HalfLife support
108 int eval_rendermode; // HalfLife support
109 int eval_fullbright;
110 int eval_ammo_shells1;
111 int eval_ammo_nails1;
112 int eval_ammo_lava_nails;
113 int eval_ammo_rockets1;
114 int eval_ammo_multi_rockets;
115 int eval_ammo_cells1;
116 int eval_ammo_plasma;
117 int eval_idealpitch;
118 int eval_pitch_speed;
119 int eval_viewmodelforclient;
120 int eval_nodrawtoclient;
121 int eval_exteriormodeltoclient;
122 int eval_drawonlytoclient;
123 int eval_ping;
124 int eval_movement;
125 int eval_pmodel;
126 int eval_punchvector;
127 int eval_viewzoom;
128 int eval_clientcolors;
129 int eval_tag_entity;
130 int eval_tag_index;
131 int eval_light_lev;
132 int eval_color;
133 int eval_style;
134 int eval_pflags;
135 int eval_cursor_active;
136 int eval_cursor_screen;
137 int eval_cursor_trace_start;
138 int eval_cursor_trace_endpos;
139 int eval_cursor_trace_ent;
140 int eval_colormod;
141 int eval_playermodel;
142 int eval_playerskin;
143
144 mfunction_t *SV_PlayerPhysicsQC;
145 mfunction_t *EndFrameQC;
146 //KrimZon - SERVER COMMANDS IN QUAKEC
147 mfunction_t *SV_ParseClientCommandQC;
148
149 int FindFieldOffset(const char *field)
150 {
151         ddef_t *d;
152         d = ED_FindField(field);
153         if (!d)
154                 return 0;
155         return d->ofs*4;
156 }
157
158 void FindEdictFieldOffsets(void)
159 {
160         eval_gravity = FindFieldOffset("gravity");
161         eval_button3 = FindFieldOffset("button3");
162         eval_button4 = FindFieldOffset("button4");
163         eval_button5 = FindFieldOffset("button5");
164         eval_button6 = FindFieldOffset("button6");
165         eval_button7 = FindFieldOffset("button7");
166         eval_button8 = FindFieldOffset("button8");
167         eval_buttonuse = FindFieldOffset("buttonuse");
168         eval_buttonchat = FindFieldOffset("buttonchat");
169         eval_glow_size = FindFieldOffset("glow_size");
170         eval_glow_trail = FindFieldOffset("glow_trail");
171         eval_glow_color = FindFieldOffset("glow_color");
172         eval_items2 = FindFieldOffset("items2");
173         eval_scale = FindFieldOffset("scale");
174         eval_alpha = FindFieldOffset("alpha");
175         eval_renderamt = FindFieldOffset("renderamt"); // HalfLife support
176         eval_rendermode = FindFieldOffset("rendermode"); // HalfLife support
177         eval_fullbright = FindFieldOffset("fullbright");
178         eval_ammo_shells1 = FindFieldOffset("ammo_shells1");
179         eval_ammo_nails1 = FindFieldOffset("ammo_nails1");
180         eval_ammo_lava_nails = FindFieldOffset("ammo_lava_nails");
181         eval_ammo_rockets1 = FindFieldOffset("ammo_rockets1");
182         eval_ammo_multi_rockets = FindFieldOffset("ammo_multi_rockets");
183         eval_ammo_cells1 = FindFieldOffset("ammo_cells1");
184         eval_ammo_plasma = FindFieldOffset("ammo_plasma");
185         eval_idealpitch = FindFieldOffset("idealpitch");
186         eval_pitch_speed = FindFieldOffset("pitch_speed");
187         eval_viewmodelforclient = FindFieldOffset("viewmodelforclient");
188         eval_nodrawtoclient = FindFieldOffset("nodrawtoclient");
189         eval_exteriormodeltoclient = FindFieldOffset("exteriormodeltoclient");
190         eval_drawonlytoclient = FindFieldOffset("drawonlytoclient");
191         eval_ping = FindFieldOffset("ping");
192         eval_movement = FindFieldOffset("movement");
193         eval_pmodel = FindFieldOffset("pmodel");
194         eval_punchvector = FindFieldOffset("punchvector");
195         eval_viewzoom = FindFieldOffset("viewzoom");
196         eval_clientcolors = FindFieldOffset("clientcolors");
197         eval_tag_entity = FindFieldOffset("tag_entity");
198         eval_tag_index = FindFieldOffset("tag_index");
199         eval_light_lev = FindFieldOffset("light_lev");
200         eval_color = FindFieldOffset("color");
201         eval_style = FindFieldOffset("style");
202         eval_pflags = FindFieldOffset("pflags");
203         eval_cursor_active = FindFieldOffset("cursor_active");
204         eval_cursor_screen = FindFieldOffset("cursor_screen");
205         eval_cursor_trace_start = FindFieldOffset("cursor_trace_start");
206         eval_cursor_trace_endpos = FindFieldOffset("cursor_trace_endpos");
207         eval_cursor_trace_ent = FindFieldOffset("cursor_trace_ent");
208         eval_colormod = FindFieldOffset("colormod");
209         eval_playermodel = FindFieldOffset("playermodel");
210         eval_playerskin = FindFieldOffset("playerskin");
211
212         // LordHavoc: allowing QuakeC to override the player movement code
213         SV_PlayerPhysicsQC = PRVM_ED_FindFunction ("SV_PlayerPhysics");
214         // LordHavoc: support for endframe
215         EndFrameQC = PRVM_ED_FindFunction ("EndFrame");
216         //KrimZon - SERVER COMMANDS IN QUAKEC
217         SV_ParseClientCommandQC = PRVM_ED_FindFunction ("SV_ParseClientCommand");
218 }
219
220 /*
221 =================
222 ED_ClearEdict
223
224 Sets everything to NULL
225 =================
226 */
227 void ED_ClearEdict (prvm_edict_t *e)
228 {
229         int num;
230         memset (e->v, 0, progs->entityfields * 4);
231         e->priv.server->free = false;
232         // LordHavoc: for consistency set these here
233         num = PRVM_NUM_FOR_EDICT(e) - 1;
234         if (num >= 0 && num < svs.maxclients)
235         {
236                 prvm_eval_t *val;
237                 // set colormap and team on newly created player entity
238                 e->fields.server->colormap = num + 1;
239                 e->fields.server->team = (svs.clients[num].colors & 15) + 1;
240                 // set netname/clientcolors back to client values so that
241                 // DP_SV_CLIENTNAME and DPV_SV_CLIENTCOLORS will not immediately
242                 // reset them
243                 e->fields.server->netname = PRVM_SetEngineString(svs.clients[num].name);
244                 if ((val = PRVM_GETEDICTFIELDVALUE(e, eval_clientcolors)))
245                         val->_float = svs.clients[num].colors;
246                 // NEXUIZ_PLAYERMODEL and NEXUIZ_PLAYERSKIN
247                 if( eval_playermodel )
248                         PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PRVM_SetEngineString(svs.clients[num].playermodel);
249                 if( eval_playerskin )
250                         PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PRVM_SetEngineString(svs.clients[num].playerskin);
251         }
252 }
253
254 /*
255 =================
256 ED_Alloc
257
258 Either finds a free edict, or allocates a new one.
259 Try to avoid reusing an entity that was recently freed, because it
260 can cause the client to think the entity morphed into something else
261 instead of being removed and recreated, which can cause interpolated
262 angles and bad trails.
263 =================
264 */
265 prvm_edict_t *ED_Alloc (void)
266 {
267         int                     i;
268         prvm_edict_t            *e;
269
270         for (i = svs.maxclients + 1;i < prog->num_edicts;i++)
271         {
272                 e = PRVM_EDICT_NUM(i);
273                 // the first couple seconds of server time can involve a lot of
274                 // freeing and allocating, so relax the replacement policy
275                 if (e->priv.server->free && ( e->priv.server->freetime < 2 || sv.time - e->priv.server->freetime > 0.5 ) )
276                 {
277                         ED_ClearEdict (e);
278                         return e;
279                 }
280         }
281
282         if (i == MAX_EDICTS)
283                 Host_Error ("ED_Alloc: no free edicts");
284
285         prog->num_edicts++;
286         if (prog->num_edicts >= prog->max_edicts)
287                 SV_IncreaseEdicts();
288         e = PRVM_EDICT_NUM(i);
289         ED_ClearEdict (e);
290
291         return e;
292 }
293
294 /*
295 =================
296 ED_Free
297
298 Marks the edict as free
299 FIXME: walk all entities and NULL out references to this entity
300 =================
301 */
302 void ED_Free (prvm_edict_t *ed)
303 {
304         SV_UnlinkEdict (ed);            // unlink from world bsp
305
306         ed->priv.server->free = true;
307         ed->fields.server->model = 0;
308         ed->fields.server->takedamage = 0;
309         ed->fields.server->modelindex = 0;
310         ed->fields.server->colormap = 0;
311         ed->fields.server->skin = 0;
312         ed->fields.server->frame = 0;
313         VectorClear(ed->fields.server->origin);
314         VectorClear(ed->fields.server->angles);
315         ed->fields.server->nextthink = -1;
316         ed->fields.server->solid = 0;
317
318         ed->priv.server->freetime = sv.time;
319 }
320
321 //===========================================================================
322
323 /*
324 ============
325 ED_GlobalAtOfs
326 ============
327 */
328 ddef_t *ED_GlobalAtOfs (int ofs)
329 {
330         ddef_t          *def;
331         int                     i;
332
333         for (i=0 ; i<progs->numglobaldefs ; i++)
334         {
335                 def = &pr_globaldefs[i];
336                 if (def->ofs == ofs)
337                         return def;
338         }
339         return NULL;
340 }
341
342 /*
343 ============
344 ED_FieldAtOfs
345 ============
346 */
347 ddef_t *ED_FieldAtOfs (int ofs)
348 {
349         ddef_t          *def;
350         int                     i;
351
352         for (i=0 ; i<progs->numfielddefs ; i++)
353         {
354                 def = &pr_fielddefs[i];
355                 if (def->ofs == ofs)
356                         return def;
357         }
358         return NULL;
359 }
360
361 /*
362 ============
363 ED_FindField
364 ============
365 */
366 ddef_t *ED_FindField (const char *name)
367 {
368         ddef_t *def;
369         int i;
370
371         for (i=0 ; i<progs->numfielddefs ; i++)
372         {
373                 def = &pr_fielddefs[i];
374                 if (!strcmp(PRVM_GetString(def->s_name), name))
375                         return def;
376         }
377         return NULL;
378 }
379
380 /*
381 ============
382 ED_FindGlobal
383 ============
384 */
385 ddef_t *ED_FindGlobal (const char *name)
386 {
387         ddef_t *def;
388         int i;
389
390         for (i=0 ; i<progs->numglobaldefs ; i++)
391         {
392                 def = &pr_globaldefs[i];
393                 if (!strcmp(PRVM_GetString(def->s_name), name))
394                         return def;
395         }
396         return NULL;
397 }
398
399
400 /*
401 ============
402 PRVM_ED_FindFunction
403 ============
404 */
405 mfunction_t *PRVM_ED_FindFunction (const char *name)
406 {
407         mfunction_t             *func;
408         int                             i;
409
410         for (i=0 ; i<progs->numfunctions ; i++)
411         {
412                 func = &prog->functions[i];
413                 if (!strcmp(PRVM_GetString(func->s_name), name))
414                         return func;
415         }
416         return NULL;
417 }
418
419
420 /*
421 ============
422 PR_ValueString
423
424 Returns a string describing *data in a type specific manner
425 =============
426 */
427 //int NoCrash_NUM_FOR_EDICT(prvm_edict_t *e);
428 char *PR_ValueString (etype_t type, prvm_eval_t *val)
429 {
430         static char line[1024]; // LordHavoc: enlarged a bit (was 256)
431         ddef_t *def;
432         mfunction_t *f;
433         int n;
434
435         type &= ~DEF_SAVEGLOBAL;
436
437         switch (type)
438         {
439         case ev_string:
440                 strlcpy (line, PRVM_GetString (val->string), sizeof (line));
441                 break;
442         case ev_entity:
443                 //n = NoCrash_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict));
444                 n = val->edict;
445                 if (n < 0 || n >= MAX_EDICTS)
446                         dpsnprintf (line, sizeof (line), "entity %i (invalid!)", n);
447                 else
448                         dpsnprintf (line, sizeof (line), "entity %i", n);
449                 break;
450         case ev_function:
451                 f = prog->functions + val->function;
452                 dpsnprintf (line, sizeof (line), "%s()", PRVM_GetString(f->s_name));
453                 break;
454         case ev_field:
455                 def = ED_FieldAtOfs ( val->_int );
456                 dpsnprintf (line, sizeof (line), ".%s", PRVM_GetString(def->s_name));
457                 break;
458         case ev_void:
459                 dpsnprintf (line, sizeof (line), "void");
460                 break;
461         case ev_float:
462                 // LordHavoc: changed from %5.1f to %10.4f
463                 dpsnprintf (line, sizeof (line), "%10.4f", val->_float);
464                 break;
465         case ev_vector:
466                 // LordHavoc: changed from %5.1f to %10.4f
467                 dpsnprintf (line, sizeof (line), "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
468                 break;
469         case ev_pointer:
470                 dpsnprintf (line, sizeof (line), "pointer");
471                 break;
472         default:
473                 dpsnprintf (line, sizeof (line), "bad type %i", type);
474                 break;
475         }
476
477         return line;
478 }
479
480 /*
481 ============
482 PR_UglyValueString
483
484 Returns a string describing *data in a type specific manner
485 Easier to parse than PR_ValueString
486 =============
487 */
488 char *PR_UglyValueString (etype_t type, prvm_eval_t *val)
489 {
490         static char line[4096];
491         int i;
492         const char *s;
493         ddef_t *def;
494         mfunction_t *f;
495
496         type &= ~DEF_SAVEGLOBAL;
497
498         switch (type)
499         {
500         case ev_string:
501                 // Parse the string a bit to turn special characters
502                 // (like newline, specifically) into escape codes,
503                 // this fixes saving games from various mods
504                 s = PRVM_GetString (val->string);
505                 for (i = 0;i < (int)sizeof(line) - 2 && *s;)
506                 {
507                         if (*s == '\n')
508                         {
509                                 line[i++] = '\\';
510                                 line[i++] = 'n';
511                         }
512                         else if (*s == '\r')
513                         {
514                                 line[i++] = '\\';
515                                 line[i++] = 'r';
516                         }
517                         else
518                                 line[i++] = *s;
519                         s++;
520                 }
521                 line[i] = '\0';
522                 break;
523         case ev_entity:
524                 dpsnprintf (line, sizeof (line), "%i", PRVM_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict)));
525                 break;
526         case ev_function:
527                 f = prog->functions + val->function;
528                 strlcpy (line, PRVM_GetString (f->s_name), sizeof (line));
529                 break;
530         case ev_field:
531                 def = ED_FieldAtOfs ( val->_int );
532                 dpsnprintf (line, sizeof (line), ".%s", PRVM_GetString(def->s_name));
533                 break;
534         case ev_void:
535                 dpsnprintf (line, sizeof (line), "void");
536                 break;
537         case ev_float:
538                 dpsnprintf (line, sizeof (line), "%f", val->_float);
539                 break;
540         case ev_vector:
541                 dpsnprintf (line, sizeof (line), "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
542                 break;
543         default:
544                 dpsnprintf (line, sizeof (line), "bad type %i", type);
545                 break;
546         }
547
548         return line;
549 }
550
551 /*
552 ============
553 PR_GlobalString
554
555 Returns a string with a description and the contents of a global,
556 padded to 20 field width
557 ============
558 */
559 char *PR_GlobalString (int ofs)
560 {
561         char    *s;
562         int             i;
563         ddef_t  *def;
564         void    *val;
565         static char     line[128];
566
567         val = (void *)&pr_globals[ofs];
568         def = ED_GlobalAtOfs(ofs);
569         if (!def)
570                 dpsnprintf (line, sizeof (line), "%i(?)", ofs);
571         else
572         {
573                 s = PR_ValueString (def->type, val);
574                 dpsnprintf (line, sizeof (line), "%i(%s)%s", ofs, PRVM_GetString(def->s_name), s);
575         }
576
577         i = strlen(line);
578         for ( ; i<20 ; i++)
579                 strlcat (line, " ", sizeof (line));
580         strlcat (line, " ", sizeof (line));
581
582         return line;
583 }
584
585 char *PR_GlobalStringNoContents (int ofs)
586 {
587         int             i;
588         ddef_t  *def;
589         static char     line[128];
590
591         def = ED_GlobalAtOfs(ofs);
592         if (!def)
593                 dpsnprintf (line, sizeof (line), "%i(?)", ofs);
594         else
595                 dpsnprintf (line, sizeof (line), "%i(%s)", ofs, PRVM_GetString(def->s_name));
596
597         i = strlen(line);
598         for ( ; i<20 ; i++)
599                 strlcat (line, " ", sizeof (line));
600         strlcat (line, " ", sizeof (line));
601
602         return line;
603 }
604
605
606 /*
607 =============
608 ED_Print
609
610 For debugging
611 =============
612 */
613 // LordHavoc: optimized this to print out much more quickly (tempstring)
614 // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
615 void ED_Print(prvm_edict_t *ed)
616 {
617         int             l;
618         ddef_t  *d;
619         int             *v;
620         int             i, j;
621         const char      *name;
622         int             type;
623         char    tempstring[8192], tempstring2[260]; // temporary string buffers
624
625         if (ed->priv.server->free)
626         {
627                 Con_Print("FREE\n");
628                 return;
629         }
630
631         tempstring[0] = 0;
632         dpsnprintf (tempstring, sizeof (tempstring), "\nEDICT %i:\n", PRVM_NUM_FOR_EDICT(ed));
633         for (i=1 ; i<progs->numfielddefs ; i++)
634         {
635                 d = &pr_fielddefs[i];
636                 name = PRVM_GetString(d->s_name);
637                 if (name[strlen(name)-2] == '_')
638                         continue;       // skip _x, _y, _z vars
639
640                 v = (int *)((char *)ed->v + d->ofs*4);
641
642         // if the value is still all 0, skip the field
643                 type = d->type & ~DEF_SAVEGLOBAL;
644
645                 for (j=0 ; j<type_size[type] ; j++)
646                         if (v[j])
647                                 break;
648                 if (j == type_size[type])
649                         continue;
650
651                 if (strlen(name) > 256)
652                 {
653                         memcpy (tempstring2, name, 256);
654                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
655                         tempstring2[259] = 0;
656                         name = tempstring2;
657                 }
658                 strlcat (tempstring, name, sizeof (tempstring));
659                 for (l = strlen(name);l < 14;l++)
660                         strcat(tempstring, " ");
661                 strcat(tempstring, " ");
662
663                 name = PR_ValueString(d->type, (prvm_eval_t *)v);
664                 if (strlen(name) > 256)
665                 {
666                         memcpy(tempstring2, name, 256);
667                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
668                         tempstring2[259] = 0;
669                         name = tempstring2;
670                 }
671                 strlcat (tempstring, name, sizeof (tempstring));
672                 strlcat (tempstring, "\n", sizeof (tempstring));
673                 if (strlen(tempstring) >= 4096)
674                 {
675                         Con_Print(tempstring);
676                         tempstring[0] = 0;
677                 }
678         }
679         if (tempstring[0])
680                 Con_Print(tempstring);
681 }
682
683 /*
684 =============
685 ED_Write
686
687 For savegames
688 =============
689 */
690 void ED_Write (qfile_t *f, prvm_edict_t *ed)
691 {
692         ddef_t  *d;
693         int             *v;
694         int             i, j;
695         const char      *name;
696         int             type;
697
698         FS_Print(f, "{\n");
699
700         if (ed->priv.server->free)
701         {
702                 FS_Print(f, "}\n");
703                 return;
704         }
705
706         for (i=1 ; i<progs->numfielddefs ; i++)
707         {
708                 d = &pr_fielddefs[i];
709                 name = PRVM_GetString(d->s_name);
710                 if (name[strlen(name)-2] == '_')
711                         continue;       // skip _x, _y, _z vars
712
713                 v = (int *)((char *)ed->v + d->ofs*4);
714
715         // if the value is still all 0, skip the field
716                 type = d->type & ~DEF_SAVEGLOBAL;
717                 for (j=0 ; j<type_size[type] ; j++)
718                         if (v[j])
719                                 break;
720                 if (j == type_size[type])
721                         continue;
722
723                 FS_Printf(f,"\"%s\" ",name);
724                 FS_Printf(f,"\"%s\"\n", PR_UglyValueString(d->type, (prvm_eval_t *)v));
725         }
726
727         FS_Print(f, "}\n");
728 }
729
730 void ED_PrintNum (int ent)
731 {
732         ED_Print(PRVM_EDICT_NUM(ent));
733 }
734
735 /*
736 =============
737 ED_PrintEdicts
738
739 For debugging, prints all the entities in the current server
740 =============
741 */
742 void ED_PrintEdicts (void)
743 {
744         int             i;
745
746         Con_Printf("%i entities\n", prog->num_edicts);
747         for (i=0 ; i<prog->num_edicts ; i++)
748                 ED_PrintNum (i);
749 }
750
751 /*
752 =============
753 ED_PrintEdict_f
754
755 For debugging, prints a single edict
756 =============
757 */
758 void ED_PrintEdict_f (void)
759 {
760         int             i;
761
762         i = atoi (Cmd_Argv(1));
763         if (i < 0 || i >= prog->num_edicts)
764         {
765                 Con_Print("Bad edict number\n");
766                 return;
767         }
768         ED_PrintNum (i);
769 }
770
771 /*
772 =============
773 ED_Count
774
775 For debugging
776 =============
777 */
778 void ED_Count (void)
779 {
780         int             i;
781         prvm_edict_t    *ent;
782         int             active, models, solid, step;
783
784         active = models = solid = step = 0;
785         for (i=0 ; i<prog->num_edicts ; i++)
786         {
787                 ent = PRVM_EDICT_NUM(i);
788                 if (ent->priv.server->free)
789                         continue;
790                 active++;
791                 if (ent->fields.server->solid)
792                         solid++;
793                 if (ent->fields.server->model)
794                         models++;
795                 if (ent->fields.server->movetype == MOVETYPE_STEP)
796                         step++;
797         }
798
799         Con_Printf("num_edicts:%3i\n", prog->num_edicts);
800         Con_Printf("active    :%3i\n", active);
801         Con_Printf("view      :%3i\n", models);
802         Con_Printf("touch     :%3i\n", solid);
803         Con_Printf("step      :%3i\n", step);
804
805 }
806
807 /*
808 ==============================================================================
809
810                                         ARCHIVING GLOBALS
811
812 FIXME: need to tag constants, doesn't really work
813 ==============================================================================
814 */
815
816 /*
817 =============
818 ED_WriteGlobals
819 =============
820 */
821 void ED_WriteGlobals (qfile_t *f)
822 {
823         ddef_t          *def;
824         int                     i;
825         const char              *name;
826         int                     type;
827
828         FS_Print(f,"{\n");
829         for (i=0 ; i<progs->numglobaldefs ; i++)
830         {
831                 def = &pr_globaldefs[i];
832                 type = def->type;
833                 if ( !(def->type & DEF_SAVEGLOBAL) )
834                         continue;
835                 type &= ~DEF_SAVEGLOBAL;
836
837                 if (type != ev_string && type != ev_float && type != ev_entity)
838                         continue;
839
840                 name = PRVM_GetString(def->s_name);
841                 FS_Printf(f,"\"%s\" ", name);
842                 FS_Printf(f,"\"%s\"\n", PR_UglyValueString(type, (prvm_eval_t *)&pr_globals[def->ofs]));
843         }
844         FS_Print(f,"}\n");
845 }
846
847 /*
848 =============
849 ED_EdictSet_f
850
851 Console command to set a field of a specified edict
852 =============
853 */
854 void ED_EdictSet_f(void)
855 {
856         prvm_edict_t *ed;
857         ddef_t *key;
858
859         if(Cmd_Argc() != 4)
860         {
861                 Con_Print("edictset <edict number> <field> <value>\n");
862                 return;
863         }
864         ed = PRVM_EDICT_NUM(atoi(Cmd_Argv(1)));
865
866         if((key = ED_FindField(Cmd_Argv(2))) == 0)
867         {
868                 Con_Printf("Key %s not found !\n", Cmd_Argv(2));
869                 return;
870         }
871
872         ED_ParseEpair(ed, key, Cmd_Argv(3));
873 }
874
875 /*
876 =============
877 ED_ParseGlobals
878 =============
879 */
880 void ED_ParseGlobals (const char *data)
881 {
882         char keyname[1024]; // LordHavoc: good idea? bad idea?  was 64
883         ddef_t *key;
884
885         while (1)
886         {
887                 // parse key
888                 if (!COM_ParseToken(&data, false))
889                         Host_Error ("ED_ParseEntity: EOF without closing brace");
890                 if (com_token[0] == '}')
891                         break;
892
893                 strcpy (keyname, com_token);
894
895                 // parse value
896                 if (!COM_ParseToken(&data, false))
897                         Host_Error ("ED_ParseEntity: EOF without closing brace");
898
899                 if (com_token[0] == '}')
900                         Host_Error ("ED_ParseEntity: closing brace without data");
901
902                 key = ED_FindGlobal (keyname);
903                 if (!key)
904                 {
905                         Con_DPrintf("'%s' is not a global\n", keyname);
906                         continue;
907                 }
908
909                 if (!ED_ParseEpair(NULL, key, com_token))
910                         Host_Error ("ED_ParseGlobals: parse error");
911         }
912 }
913
914 //============================================================================
915
916
917 /*
918 =============
919 ED_ParseEval
920
921 Can parse either fields or globals
922 returns false if error
923 =============
924 */
925 qboolean ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s)
926 {
927         int i, l;
928         char *new_p;
929         ddef_t *def;
930         prvm_eval_t *val;
931         mfunction_t *func;
932
933         if (ent)
934                 val = (prvm_eval_t *)((int *)ent->v + key->ofs);
935         else
936                 val = (prvm_eval_t *)((int *)pr_globals + key->ofs);
937         switch (key->type & ~DEF_SAVEGLOBAL)
938         {
939         case ev_string:
940                 l = strlen(s) + 1;
941                 new_p = PR_AllocString(l);
942                 val->string = PR_SetQCString(new_p);
943                 for (i = 0;i < l;i++)
944                 {
945                         if (s[i] == '\\' && i < l-1)
946                         {
947                                 i++;
948                                 if (s[i] == 'n')
949                                         *new_p++ = '\n';
950                                 else if (s[i] == 'r')
951                                         *new_p++ = '\r';
952                                 else
953                                         *new_p++ = s[i];
954                         }
955                         else
956                                 *new_p++ = s[i];
957                 }
958                 break;
959
960         case ev_float:
961                 while (*s && *s <= ' ')
962                         s++;
963                 val->_float = atof(s);
964                 break;
965
966         case ev_vector:
967                 for (i = 0;i < 3;i++)
968                 {
969                         while (*s && *s <= ' ')
970                                 s++;
971                         if (*s)
972                                 val->vector[i] = atof(s);
973                         else
974                                 val->vector[i] = 0;
975                         while (*s > ' ')
976                                 s++;
977                 }
978                 break;
979
980         case ev_entity:
981                 while (*s && *s <= ' ')
982                         s++;
983                 i = atoi(s);
984                 if (i < 0 || i >= MAX_EDICTS)
985                         Con_Printf("ED_ParseEpair: ev_entity reference too large (edict %i >= MAX_EDICTS %i)\n", i, MAX_EDICTS);
986                 while (i >= prog->max_edicts)
987                         SV_IncreaseEdicts();
988                 // if SV_IncreaseEdicts was called the base pointer needs to be updated
989                 if (ent)
990                         val = (prvm_eval_t *)((int *)ent->v + key->ofs);
991                 val->edict = PRVM_EDICT_TO_PROG(PRVM_EDICT_NUM(i));
992                 break;
993
994         case ev_field:
995                 def = ED_FindField(s);
996                 if (!def)
997                 {
998                         Con_DPrintf("ED_ParseEpair: Can't find field %s\n", s);
999                         return false;
1000                 }
1001                 //val->_int = PRVM_G_INT(def->ofs); // AK Please check this - seems to be an org. quake bug
1002                 val->_int = def->ofs;
1003                 break;
1004
1005         case ev_function:
1006                 func = PRVM_ED_FindFunction(s);
1007                 if (!func)
1008                 {
1009                         Con_Printf("ED_ParseEpair: Can't find function %s\n", s);
1010                         return false;
1011                 }
1012                 val->function = func - prog->functions;
1013                 break;
1014
1015         default:
1016                 Con_Printf("ED_ParseEpair: Unknown key->type %i for key \"%s\"\n", key->type, PRVM_GetString(key->s_name));
1017                 return false;
1018         }
1019         return true;
1020 }
1021
1022 /*
1023 ====================
1024 ED_ParseEdict
1025
1026 Parses an edict out of the given string, returning the new position
1027 ed should be a properly initialized empty edict.
1028 Used for initial level load and for savegames.
1029 ====================
1030 */
1031 const char *ED_ParseEdict (const char *data, prvm_edict_t *ent)
1032 {
1033         ddef_t *key;
1034         qboolean anglehack;
1035         qboolean init;
1036         char keyname[256];
1037         int n;
1038
1039         init = false;
1040
1041 // clear it
1042         if (ent != prog->edicts)        // hack
1043                 memset (ent->v, 0, progs->entityfields * 4);
1044
1045 // go through all the dictionary pairs
1046         while (1)
1047         {
1048         // parse key
1049                 if (!COM_ParseToken(&data, false))
1050                         Host_Error ("ED_ParseEntity: EOF without closing brace");
1051                 if (com_token[0] == '}')
1052                         break;
1053
1054                 // anglehack is to allow QuakeEd to write single scalar angles
1055                 // and allow them to be turned into vectors. (FIXME...)
1056                 anglehack = !strcmp (com_token, "angle");
1057                 if (anglehack)
1058                         strlcpy (com_token, "angles", sizeof (com_token));
1059
1060                 // FIXME: change light to _light to get rid of this hack
1061                 if (!strcmp(com_token, "light"))
1062                         strlcpy (com_token, "light_lev", sizeof (com_token));   // hack for single light def
1063
1064                 strlcpy (keyname, com_token, sizeof (keyname));
1065
1066                 // another hack to fix heynames with trailing spaces
1067                 n = strlen(keyname);
1068                 while (n && keyname[n-1] == ' ')
1069                 {
1070                         keyname[n-1] = 0;
1071                         n--;
1072                 }
1073
1074         // parse value
1075                 if (!COM_ParseToken(&data, false))
1076                         Host_Error ("ED_ParseEntity: EOF without closing brace");
1077
1078                 if (com_token[0] == '}')
1079                         Host_Error ("ED_ParseEntity: closing brace without data");
1080
1081                 init = true;
1082
1083 // keynames with a leading underscore are used for utility comments,
1084 // and are immediately discarded by quake
1085                 if (keyname[0] == '_')
1086                         continue;
1087
1088                 key = ED_FindField (keyname);
1089                 if (!key)
1090                 {
1091                         Con_DPrintf("'%s' is not a field\n", keyname);
1092                         continue;
1093                 }
1094
1095                 if (anglehack)
1096                 {
1097                         char    temp[32];
1098                         strlcpy (temp, com_token, sizeof (temp));
1099                         dpsnprintf (com_token, sizeof (com_token), "0 %s 0", temp);
1100                 }
1101
1102                 if (!ED_ParseEpair(ent, key, com_token))
1103                         Host_Error ("ED_ParseEdict: parse error");
1104         }
1105
1106         if (!init)
1107                 ent->priv.server->free = true;
1108
1109         return data;
1110 }
1111
1112
1113 /*
1114 ================
1115 ED_LoadFromFile
1116
1117 The entities are directly placed in the array, rather than allocated with
1118 ED_Alloc, because otherwise an error loading the map would have entity
1119 number references out of order.
1120
1121 Creates a server's entity / program execution context by
1122 parsing textual entity definitions out of an ent file.
1123
1124 Used for both fresh maps and savegame loads.  A fresh map would also need
1125 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
1126 ================
1127 */
1128 void ED_LoadFromFile (const char *data)
1129 {
1130         prvm_edict_t *ent;
1131         int parsed, inhibited, spawned, died;
1132         mfunction_t *func;
1133
1134         ent = NULL;
1135         parsed = 0;
1136         inhibited = 0;
1137         spawned = 0;
1138         died = 0;
1139         prog->globals.server->time = sv.time;
1140
1141 // parse ents
1142         while (1)
1143         {
1144 // parse the opening brace
1145                 if (!COM_ParseToken(&data, false))
1146                         break;
1147                 if (com_token[0] != '{')
1148                         Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1149
1150                 if (!ent)
1151                         ent = PRVM_EDICT_NUM(0);
1152                 else
1153                         ent = ED_Alloc ();
1154                 data = ED_ParseEdict (data, ent);
1155                 parsed++;
1156
1157 // remove things from different skill levels or deathmatch
1158                 if (gamemode != GAME_TRANSFUSION) //Transfusion does this in QC
1159                 {
1160                         if (deathmatch.integer)
1161                         {
1162                                 if (((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1163                                 {
1164                                         ED_Free (ent);
1165                                         inhibited++;
1166                                         continue;
1167                                 }
1168                         }
1169                         else if ((current_skill <= 0 && ((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_EASY  ))
1170                                 || (current_skill == 1 && ((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_MEDIUM))
1171                                 || (current_skill >= 2 && ((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_HARD  )))
1172                         {
1173                                 ED_Free (ent);
1174                                 inhibited++;
1175                                 continue;
1176                         }
1177                 }
1178 //
1179 // immediately call spawn function
1180 //
1181                 if (!ent->fields.server->classname)
1182                 {
1183                         Con_Print("No classname for:\n");
1184                         ED_Print(ent);
1185                         ED_Free (ent);
1186                         continue;
1187                 }
1188
1189         // look for the spawn function
1190                 func = PRVM_ED_FindFunction (PRVM_GetString(ent->fields.server->classname));
1191
1192                 if (!func)
1193                 {
1194                         if (developer.integer) // don't confuse non-developers with errors
1195                         {
1196                                 Con_Print("No spawn function for:\n");
1197                                 ED_Print(ent);
1198                         }
1199                         ED_Free (ent);
1200                         continue;
1201                 }
1202
1203                 prog->globals.server->self = PRVM_EDICT_TO_PROG(ent);
1204                 PRVM_ExecuteProgram (func - prog->functions, "QC function spawn is missing");
1205                 spawned++;
1206                 if (ent->priv.server->free)
1207                         died++;
1208         }
1209
1210         Con_DPrintf("%i entities parsed, %i inhibited, %i spawned (%i removed self, %i stayed)\n", parsed, inhibited, spawned, died, spawned - died);
1211 }
1212
1213
1214 typedef struct dpfield_s
1215 {
1216         int type;
1217         char *string;
1218 }
1219 dpfield_t;
1220
1221 #define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
1222
1223 dpfield_t dpfields[] =
1224 {
1225         {ev_entity, "cursor_trace_ent"},
1226         {ev_entity, "drawonlytoclient"},
1227         {ev_entity, "exteriormodeltoclient"},
1228         {ev_entity, "nodrawtoclient"},
1229         {ev_entity, "tag_entity"},
1230         {ev_entity, "viewmodelforclient"},
1231         {ev_float, "alpha"},
1232         {ev_float, "ammo_cells1"},
1233         {ev_float, "ammo_lava_nails"},
1234         {ev_float, "ammo_multi_rockets"},
1235         {ev_float, "ammo_nails1"},
1236         {ev_float, "ammo_plasma"},
1237         {ev_float, "ammo_rockets1"},
1238         {ev_float, "ammo_shells1"},
1239         {ev_float, "button3"},
1240         {ev_float, "button4"},
1241         {ev_float, "button5"},
1242         {ev_float, "button6"},
1243         {ev_float, "button7"},
1244         {ev_float, "button8"},
1245         {ev_float, "buttonchat"},
1246         {ev_float, "buttonuse"},
1247         {ev_float, "clientcolors"},
1248         {ev_float, "cursor_active"},
1249         {ev_float, "fullbright"},
1250         {ev_float, "glow_color"},
1251         {ev_float, "glow_size"},
1252         {ev_float, "glow_trail"},
1253         {ev_float, "gravity"},
1254         {ev_float, "idealpitch"},
1255         {ev_float, "items2"},
1256         {ev_float, "light_lev"},
1257         {ev_float, "pflags"},
1258         {ev_float, "ping"},
1259         {ev_float, "pitch_speed"},
1260         {ev_float, "pmodel"},
1261         {ev_float, "renderamt"}, // HalfLife support
1262         {ev_float, "rendermode"}, // HalfLife support
1263         {ev_float, "scale"},
1264         {ev_float, "style"},
1265         {ev_float, "tag_index"},
1266         {ev_float, "viewzoom"},
1267         {ev_vector, "color"},
1268         {ev_vector, "colormod"},
1269         {ev_vector, "cursor_screen"},
1270         {ev_vector, "cursor_trace_endpos"},
1271         {ev_vector, "cursor_trace_start"},
1272         {ev_vector, "movement"},
1273         {ev_vector, "punchvector"},
1274         {ev_string, "playermodel"},
1275         {ev_string, "playerskin"}
1276 };
1277
1278 /*
1279 ===============
1280 PR_LoadProgs
1281 ===============
1282 */
1283 extern void PR_Cmd_Reset (void);
1284 void PR_LoadProgs (const char *progsname)
1285 {
1286         int i;
1287         dstatement_t *st;
1288         ddef_t *infielddefs;
1289         dfunction_t *dfunctions;
1290
1291         if (!progsname || !*progsname)
1292                 Host_Error("PR_LoadProgs: passed empty progsname");
1293
1294 // flush the non-C variable lookup cache
1295         for (i=0 ; i<GEFV_CACHESIZE ; i++)
1296                 gefvCache[i].field[0] = 0;
1297
1298         PR_FreeAll();
1299
1300         progs = (dprograms_t *)FS_LoadFile (progsname, serverprogs_mempool, false);
1301         if (!progs)
1302                 Host_Error ("PR_LoadProgs: couldn't load %s", progsname);
1303
1304         Con_DPrintf("Programs occupy %iK.\n", fs_filesize/1024);
1305
1306         pr_crc = CRC_Block((qbyte *)progs, fs_filesize);
1307
1308 // byte swap the header
1309         for (i = 0;i < (int) sizeof(*progs) / 4;i++)
1310                 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
1311
1312         if (progs->version != PROG_VERSION)
1313                 Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
1314         if (progs->crc != PROGHEADER_CRC && progs->crc != 32401) // tenebrae crc also allowed
1315                 Host_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
1316
1317         //prog->functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1318         dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
1319
1320         pr_strings = (char *)progs + progs->ofs_strings;
1321         pr_stringssize = 0;
1322         for (i = 0;i < progs->numstrings;i++)
1323         {
1324                 if (progs->ofs_strings + pr_stringssize >= fs_filesize)
1325                         Host_Error ("progs.dat strings go past end of file\n");
1326                 pr_stringssize += strlen (pr_strings + pr_stringssize) + 1;
1327         }
1328         pr_numknownstrings = 0;
1329         pr_maxknownstrings = 0;
1330         pr_knownstrings = NULL;
1331
1332         pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
1333
1334         // we need to expand the fielddefs list to include all the engine fields,
1335         // so allocate a new place for it
1336         infielddefs = (ddef_t *)((qbyte *)progs + progs->ofs_fielddefs);
1337         pr_fielddefs = PR_Alloc((progs->numfielddefs + DPFIELDS) * sizeof(ddef_t));
1338         prog->functions = PR_Alloc(sizeof(mfunction_t) * progs->numfunctions);
1339
1340         pr_statements = (dstatement_t *)((qbyte *)progs + progs->ofs_statements);
1341
1342         // moved edict_size calculation down below field adding code
1343
1344         pr_global_struct = (globalvars_t *)((qbyte *)progs + progs->ofs_globals);
1345         pr_globals = (float *)pr_global_struct;
1346
1347 // byte swap the lumps
1348         for (i=0 ; i<progs->numstatements ; i++)
1349         {
1350                 pr_statements[i].op = LittleShort(pr_statements[i].op);
1351                 pr_statements[i].a = LittleShort(pr_statements[i].a);
1352                 pr_statements[i].b = LittleShort(pr_statements[i].b);
1353                 pr_statements[i].c = LittleShort(pr_statements[i].c);
1354         }
1355
1356         for (i = 0;i < progs->numfunctions;i++)
1357         {
1358                 prog->functions[i].first_statement = LittleLong (dfunctions[i].first_statement);
1359                 prog->functions[i].parm_start = LittleLong (dfunctions[i].parm_start);
1360                 prog->functions[i].s_name = LittleLong (dfunctions[i].s_name);
1361                 prog->functions[i].s_file = LittleLong (dfunctions[i].s_file);
1362                 prog->functions[i].numparms = LittleLong (dfunctions[i].numparms);
1363                 prog->functions[i].locals = LittleLong (dfunctions[i].locals);
1364                 memcpy(prog->functions[i].parm_size, dfunctions[i].parm_size, sizeof(dfunctions[i].parm_size));
1365         }
1366
1367         for (i=0 ; i<progs->numglobaldefs ; i++)
1368         {
1369                 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
1370                 pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
1371                 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
1372         }
1373
1374         // copy the progs fields to the new fields list
1375         for (i = 0;i < progs->numfielddefs;i++)
1376         {
1377                 pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
1378                 if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
1379                         Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1380                 pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
1381                 pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
1382         }
1383
1384         // append the darkplaces fields
1385         for (i = 0;i < (int) DPFIELDS;i++)
1386         {
1387                 pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
1388                 pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
1389                 pr_fielddefs[progs->numfielddefs].s_name = PRVM_SetEngineString(dpfields[i].string);
1390                 if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
1391                         progs->entityfields += 3;
1392                 else
1393                         progs->entityfields++;
1394                 progs->numfielddefs++;
1395         }
1396
1397         for (i=0 ; i<progs->numglobals ; i++)
1398                 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
1399
1400         // moved edict_size calculation down here, below field adding code
1401         // LordHavoc: this no longer includes the prvm_edict_t header
1402         prog->edict_size = progs->entityfields * 4;
1403         pr_edictareasize = prog->edict_size * MAX_EDICTS;
1404
1405         // LordHavoc: bounds check anything static
1406         for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
1407         {
1408                 switch (st->op)
1409                 {
1410                 case OP_IF:
1411                 case OP_IFNOT:
1412                         if ((unsigned short) st->a >= progs->numglobals || st->b + i < 0 || st->b + i >= progs->numstatements)
1413                                 Host_Error("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i);
1414                         break;
1415                 case OP_GOTO:
1416                         if (st->a + i < 0 || st->a + i >= progs->numstatements)
1417                                 Host_Error("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i);
1418                         break;
1419                 // global global global
1420                 case OP_ADD_F:
1421                 case OP_ADD_V:
1422                 case OP_SUB_F:
1423                 case OP_SUB_V:
1424                 case OP_MUL_F:
1425                 case OP_MUL_V:
1426                 case OP_MUL_FV:
1427                 case OP_MUL_VF:
1428                 case OP_DIV_F:
1429                 case OP_BITAND:
1430                 case OP_BITOR:
1431                 case OP_GE:
1432                 case OP_LE:
1433                 case OP_GT:
1434                 case OP_LT:
1435                 case OP_AND:
1436                 case OP_OR:
1437                 case OP_EQ_F:
1438                 case OP_EQ_V:
1439                 case OP_EQ_S:
1440                 case OP_EQ_E:
1441                 case OP_EQ_FNC:
1442                 case OP_NE_F:
1443                 case OP_NE_V:
1444                 case OP_NE_S:
1445                 case OP_NE_E:
1446                 case OP_NE_FNC:
1447                 case OP_ADDRESS:
1448                 case OP_LOAD_F:
1449                 case OP_LOAD_FLD:
1450                 case OP_LOAD_ENT:
1451                 case OP_LOAD_S:
1452                 case OP_LOAD_FNC:
1453                 case OP_LOAD_V:
1454                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1455                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1456                         break;
1457                 // global none global
1458                 case OP_NOT_F:
1459                 case OP_NOT_V:
1460                 case OP_NOT_S:
1461                 case OP_NOT_FNC:
1462                 case OP_NOT_ENT:
1463                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->c >= progs->numglobals)
1464                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1465                         break;
1466                 // 2 globals
1467                 case OP_STOREP_F:
1468                 case OP_STOREP_ENT:
1469                 case OP_STOREP_FLD:
1470                 case OP_STOREP_S:
1471                 case OP_STOREP_FNC:
1472                 case OP_STORE_F:
1473                 case OP_STORE_ENT:
1474                 case OP_STORE_FLD:
1475                 case OP_STORE_S:
1476                 case OP_STORE_FNC:
1477                 case OP_STATE:
1478                 case OP_STOREP_V:
1479                 case OP_STORE_V:
1480                         if ((unsigned short) st->a >= progs->numglobals || (unsigned short) st->b >= progs->numglobals)
1481                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1482                         break;
1483                 // 1 global
1484                 case OP_CALL0:
1485                 case OP_CALL1:
1486                 case OP_CALL2:
1487                 case OP_CALL3:
1488                 case OP_CALL4:
1489                 case OP_CALL5:
1490                 case OP_CALL6:
1491                 case OP_CALL7:
1492                 case OP_CALL8:
1493                 case OP_DONE:
1494                 case OP_RETURN:
1495                         if ((unsigned short) st->a >= progs->numglobals)
1496                                 Host_Error("PR_LoadProgs: out of bounds global index (statement %d)\n", i);
1497                         break;
1498                 default:
1499                         Host_Error("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i);
1500                         break;
1501                 }
1502         }
1503
1504         FindEdictFieldOffsets(); // LordHavoc: update field offset list
1505         PR_Execute_ProgsLoaded();
1506         PR_Cmd_Reset();
1507 }
1508
1509
1510 void PR_Fields_f (void)
1511 {
1512         int i, j, ednum, used, usedamount;
1513         int *counts;
1514         const char *name;
1515         char tempstring[5000], tempstring2[260];
1516         prvm_edict_t *ed;
1517         ddef_t *d;
1518         int *v;
1519         if (!sv.active)
1520         {
1521                 Con_Print("no progs loaded\n");
1522                 return;
1523         }
1524         counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int));
1525         for (ednum = 0;ednum < prog->max_edicts;ednum++)
1526         {
1527                 ed = PRVM_EDICT_NUM(ednum);
1528                 if (ed->priv.server->free)
1529                         continue;
1530                 for (i = 1;i < progs->numfielddefs;i++)
1531                 {
1532                         d = &pr_fielddefs[i];
1533                         name = PRVM_GetString(d->s_name);
1534                         if (name[strlen(name)-2] == '_')
1535                                 continue;       // skip _x, _y, _z vars
1536                         v = (int *)((char *)ed->v + d->ofs*4);
1537                         // if the value is still all 0, skip the field
1538                         for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++)
1539                         {
1540                                 if (v[j])
1541                                 {
1542                                         counts[i]++;
1543                                         break;
1544                                 }
1545                         }
1546                 }
1547         }
1548         used = 0;
1549         usedamount = 0;
1550         tempstring[0] = 0;
1551         for (i = 0;i < progs->numfielddefs;i++)
1552         {
1553                 d = &pr_fielddefs[i];
1554                 name = PRVM_GetString(d->s_name);
1555                 if (name[strlen(name)-2] == '_')
1556                         continue;       // skip _x, _y, _z vars
1557                 switch(d->type & ~DEF_SAVEGLOBAL)
1558                 {
1559                 case ev_string:
1560                         strlcat (tempstring, "string   ", sizeof (tempstring));
1561                         break;
1562                 case ev_entity:
1563                         strlcat (tempstring, "entity   ", sizeof (tempstring));
1564                         break;
1565                 case ev_function:
1566                         strlcat (tempstring, "function ", sizeof (tempstring));
1567                         break;
1568                 case ev_field:
1569                         strlcat (tempstring, "field    ", sizeof (tempstring));
1570                         break;
1571                 case ev_void:
1572                         strlcat (tempstring, "void     ", sizeof (tempstring));
1573                         break;
1574                 case ev_float:
1575                         strlcat (tempstring, "float    ", sizeof (tempstring));
1576                         break;
1577                 case ev_vector:
1578                         strlcat (tempstring, "vector   ", sizeof (tempstring));
1579                         break;
1580                 case ev_pointer:
1581                         strlcat (tempstring, "pointer  ", sizeof (tempstring));
1582                         break;
1583                 default:
1584                         dpsnprintf (tempstring2, sizeof (tempstring2), "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
1585                         strlcat (tempstring, tempstring2, sizeof (tempstring));
1586                         break;
1587                 }
1588                 if (strlen(name) > 256)
1589                 {
1590                         memcpy(tempstring2, name, 256);
1591                         tempstring2[256] = tempstring2[257] = tempstring2[258] = '.';
1592                         tempstring2[259] = 0;
1593                         name = tempstring2;
1594                 }
1595                 strcat (tempstring, name);
1596                 for (j = strlen(name);j < 25;j++)
1597                         strcat(tempstring, " ");
1598                 dpsnprintf (tempstring2, sizeof (tempstring2), "%5d", counts[i]);
1599                 strlcat (tempstring, tempstring2, sizeof (tempstring));
1600                 strlcat (tempstring, "\n", sizeof (tempstring));
1601                 if (strlen(tempstring) >= 4096)
1602                 {
1603                         Con_Print(tempstring);
1604                         tempstring[0] = 0;
1605                 }
1606                 if (counts[i])
1607                 {
1608                         used++;
1609                         usedamount += type_size[d->type & ~DEF_SAVEGLOBAL];
1610                 }
1611         }
1612         Mem_Free(counts);
1613         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, prog->max_edicts, progs->entityfields * 4 * prog->max_edicts, usedamount * 4 * prog->max_edicts);
1614 }
1615
1616 void PR_Globals_f (void)
1617 {
1618         int i;
1619         if (!sv.active)
1620         {
1621                 Con_Print("no progs loaded\n");
1622                 return;
1623         }
1624         for (i = 0;i < progs->numglobaldefs;i++)
1625                 Con_Printf("%s\n", PRVM_GetString(pr_globaldefs[i].s_name));
1626         Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4);
1627 }
1628
1629 /*
1630 ===============
1631 PR_Init
1632 ===============
1633 */
1634 extern void PR_Cmd_Init(void);
1635 void PR_Init (void)
1636 {
1637         Cmd_AddCommand ("edict", ED_PrintEdict_f);
1638         Cmd_AddCommand ("edicts", ED_PrintEdicts);
1639         Cmd_AddCommand ("edictcount", ED_Count);
1640         Cmd_AddCommand ("edictset", ED_EdictSet_f);
1641         Cmd_AddCommand ("profile", PR_Profile_f);
1642         Cmd_AddCommand ("pr_fields", PR_Fields_f);
1643         Cmd_AddCommand ("pr_globals", PR_Globals_f);
1644         Cvar_RegisterVariable (&pr_checkextension);
1645         Cvar_RegisterVariable (&nomonsters);
1646         Cvar_RegisterVariable (&gamecfg);
1647         Cvar_RegisterVariable (&scratch1);
1648         Cvar_RegisterVariable (&scratch2);
1649         Cvar_RegisterVariable (&scratch3);
1650         Cvar_RegisterVariable (&scratch4);
1651         Cvar_RegisterVariable (&savedgamecfg);
1652         Cvar_RegisterVariable (&saved1);
1653         Cvar_RegisterVariable (&saved2);
1654         Cvar_RegisterVariable (&saved3);
1655         Cvar_RegisterVariable (&saved4);
1656         // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
1657         Cvar_RegisterVariable (&decors);
1658         // LordHavoc: Nehahra uses these to pass data around cutscene demos
1659         if (gamemode == GAME_NEHAHRA)
1660         {
1661                 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
1662                 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
1663                 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
1664                 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
1665                 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
1666                 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
1667                 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
1668                 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
1669                 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
1670                 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
1671         }
1672         Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
1673         // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
1674         Cvar_RegisterVariable (&pr_boundscheck);
1675         Cvar_RegisterVariable (&pr_traceqc);
1676
1677         serverprogs_mempool = Mem_AllocPool("server progs", 0, NULL);
1678
1679         PR_Cmd_Init();
1680 }
1681
1682 /*
1683 ===============
1684 PR_Shutdown
1685 ===============
1686 */
1687 extern void PR_Cmd_Shutdown(void);
1688 void PR_Shutdown (void)
1689 {
1690         PR_Cmd_Shutdown();
1691
1692         Mem_FreePool(&serverprogs_mempool);
1693 }
1694
1695 void *_PR_Alloc(size_t buffersize, const char *filename, int fileline)
1696 {
1697         return _Mem_Alloc(serverprogs_mempool, buffersize, filename, fileline);
1698 }
1699
1700 void _PR_Free(void *buffer, const char *filename, int fileline)
1701 {
1702         _Mem_Free(buffer, filename, fileline);
1703 }
1704
1705 void _PR_FreeAll(const char *filename, int fileline)
1706 {
1707         progs = NULL;
1708         pr_fielddefs = NULL;
1709         prog->functions = NULL;
1710         _Mem_EmptyPool(serverprogs_mempool, filename, fileline);
1711 }
1712
1713 // LordHavoc: turned PRVM_EDICT_NUM into a #define for speed reasons
1714 prvm_edict_t *EDICT_NUM_ERROR(int n, char *filename, int fileline)
1715 {
1716         Host_Error ("PRVM_EDICT_NUM: bad number %i (called at %s:%i)", n, filename, fileline);
1717         return NULL;
1718 }
1719
1720 /*
1721 int NUM_FOR_EDICT_ERROR(prvm_edict_t *e)
1722 {
1723         Host_Error ("PRVM_NUM_FOR_EDICT: bad pointer %p (world is %p, entity number would be %i)", e, prog->edicts, e - prog->edicts);
1724         return 0;
1725 }
1726
1727 int PRVM_NUM_FOR_EDICT(prvm_edict_t *e)
1728 {
1729         int n;
1730         n = e - prog->edicts;
1731         if ((unsigned int)n >= MAX_EDICTS)
1732                 Host_Error ("PRVM_NUM_FOR_EDICT: bad pointer");
1733         return n;
1734 }
1735
1736 //int NoCrash_NUM_FOR_EDICT(prvm_edict_t *e)
1737 //{
1738 //      return e - prog->edicts;
1739 //}
1740
1741 //#define       PRVM_EDICT_TO_PROG(e) ((qbyte *)(((prvm_edict_t *)e)->v) - (qbyte *)(prog->edictsfields))
1742 //#define PRVM_PROG_TO_EDICT(e) (prog->edicts + ((e) / (progs->entityfields * 4)))
1743 int PRVM_EDICT_TO_PROG(prvm_edict_t *e)
1744 {
1745         int n;
1746         n = e - prog->edicts;
1747         if ((unsigned int)n >= (unsigned int)prog->max_edicts)
1748                 Host_Error("PRVM_EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, prog->edicts);
1749         return n;// EXPERIMENTAL
1750         //return (qbyte *)e->v - (qbyte *)prog->edictsfields;
1751 }
1752 prvm_edict_t *PRVM_PROG_TO_EDICT(int n)
1753 {
1754         if ((unsigned int)n >= (unsigned int)prog->max_edicts)
1755                 Host_Error("PRVM_PROG_TO_EDICT: invalid edict number %i\n", n);
1756         return prog->edicts + n; // EXPERIMENTAL
1757         //return prog->edicts + ((n) / (progs->entityfields * 4));
1758 }
1759 */
1760
1761 const char *PRVM_GetString(int num)
1762 {
1763         if (num >= 0 && num < pr_stringssize)
1764                 return pr_strings + num;
1765         else if (num < 0 && num >= -pr_numknownstrings)
1766         {
1767                 num = -1 - num;
1768                 if (!pr_knownstrings[num])
1769                         Host_Error("PRVM_GetString: attempt to get string that is already freed\n");
1770                 return pr_knownstrings[num];
1771         }
1772         else
1773         {
1774                 Host_Error("PRVM_GetString: invalid string offset %i\n", num);
1775                 return "";
1776         }
1777 }
1778
1779 int PR_SetQCString(const char *s)
1780 {
1781         int i;
1782         if (!s)
1783                 return 0;
1784         if (s >= pr_strings && s <= pr_strings + pr_stringssize)
1785                 return s - pr_strings;
1786         for (i = 0;i < pr_numknownstrings;i++)
1787                 if (pr_knownstrings[i] == s)
1788                         return -1 - i;
1789         Host_Error("PR_SetQCString: unknown string\n");
1790         return -1 - i;
1791 }
1792
1793 int PRVM_SetEngineString(const char *s)
1794 {
1795         int i;
1796         if (!s)
1797                 return 0;
1798         if (s >= pr_strings && s <= pr_strings + pr_stringssize)
1799                 Host_Error("PRVM_SetEngineString: s in pr_strings area\n");
1800         for (i = 0;i < pr_numknownstrings;i++)
1801                 if (pr_knownstrings[i] == s)
1802                         return -1 - i;
1803         // new unknown engine string
1804         if (developer.integer >= 3)
1805                 Con_Printf("new engine string %p\n", s);
1806         for (i = 0;i < pr_numknownstrings;i++)
1807                 if (!pr_knownstrings[i])
1808                         break;
1809         if (i >= pr_numknownstrings)
1810         {
1811                 if (i >= pr_maxknownstrings)
1812                 {
1813                         const char **oldstrings = pr_knownstrings;
1814                         pr_maxknownstrings += 128;
1815                         pr_knownstrings = PR_Alloc(pr_maxknownstrings * sizeof(char *));
1816                         if (pr_numknownstrings)
1817                                 memcpy((char **)pr_knownstrings, oldstrings, pr_numknownstrings * sizeof(char *));
1818                 }
1819                 pr_numknownstrings++;
1820         }
1821         pr_knownstrings[i] = s;
1822         return -1 - i;
1823 }
1824
1825 char *PR_AllocString(int bufferlength)
1826 {
1827         int i;
1828         if (!bufferlength)
1829                 return 0;
1830         for (i = 0;i < pr_numknownstrings;i++)
1831                 if (!pr_knownstrings[i])
1832                         break;
1833         if (i >= pr_numknownstrings)
1834         {
1835                 if (i >= pr_maxknownstrings)
1836                 {
1837                         const char **oldstrings = pr_knownstrings;
1838                         pr_maxknownstrings += 128;
1839                         pr_knownstrings = PR_Alloc(pr_maxknownstrings * sizeof(char *));
1840                         if (pr_numknownstrings)
1841                                 memcpy((char **)pr_knownstrings, oldstrings, pr_numknownstrings * sizeof(char *));
1842                 }
1843                 pr_numknownstrings++;
1844         }
1845         return (char *)(pr_knownstrings[i] = PR_Alloc(bufferlength));
1846 }
1847
1848 void PR_FreeString(char *s)
1849 {
1850         int i;
1851         if (!s)
1852                 Host_Error("PR_FreeString: attempt to free a NULL string\n");
1853         if (s >= pr_strings && s <= pr_strings + pr_stringssize)
1854                 Host_Error("PR_FreeString: attempt to free a constant string\n");
1855         for (i = 0;i < pr_numknownstrings;i++)
1856                 if (pr_knownstrings[i] == s)
1857                         break;
1858         if (i == pr_numknownstrings)
1859                 Host_Error("PR_FreeString: attempt to free a non-existent or already freed string\n");
1860         PR_Free((char *)pr_knownstrings[i]);
1861         pr_knownstrings[i] = NULL;
1862 }
1863