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