diff options
Diffstat (limited to 'apps/plugins/sdl/progs/quake/pr_edict.c')
-rw-r--r-- | apps/plugins/sdl/progs/quake/pr_edict.c | 1113 |
1 files changed, 1113 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/pr_edict.c b/apps/plugins/sdl/progs/quake/pr_edict.c new file mode 100644 index 0000000000..2f0e8eccb3 --- /dev/null +++ b/apps/plugins/sdl/progs/quake/pr_edict.c | |||
@@ -0,0 +1,1113 @@ | |||
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 | dfunction_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 | |||
34 | unsigned short pr_crc; | ||
35 | |||
36 | int type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4}; | ||
37 | |||
38 | ddef_t *ED_FieldAtOfs (int ofs); | ||
39 | qboolean ED_ParseEpair (void *base, ddef_t *key, char *s); | ||
40 | |||
41 | cvar_t nomonsters = {"nomonsters", "0"}; | ||
42 | cvar_t gamecfg = {"gamecfg", "0"}; | ||
43 | cvar_t scratch1 = {"scratch1", "0"}; | ||
44 | cvar_t scratch2 = {"scratch2", "0"}; | ||
45 | cvar_t scratch3 = {"scratch3", "0"}; | ||
46 | cvar_t scratch4 = {"scratch4", "0"}; | ||
47 | cvar_t savedgamecfg = {"savedgamecfg", "0", true}; | ||
48 | cvar_t saved1 = {"saved1", "0", true}; | ||
49 | cvar_t saved2 = {"saved2", "0", true}; | ||
50 | cvar_t saved3 = {"saved3", "0", true}; | ||
51 | cvar_t saved4 = {"saved4", "0", true}; | ||
52 | |||
53 | #define MAX_FIELD_LEN 64 | ||
54 | #define GEFV_CACHESIZE 2 | ||
55 | |||
56 | typedef struct { | ||
57 | ddef_t *pcache; | ||
58 | char field[MAX_FIELD_LEN]; | ||
59 | } gefv_cache; | ||
60 | |||
61 | static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}}; | ||
62 | |||
63 | /* | ||
64 | ================= | ||
65 | ED_ClearEdict | ||
66 | |||
67 | Sets everything to NULL | ||
68 | ================= | ||
69 | */ | ||
70 | void ED_ClearEdict (edict_t *e) | ||
71 | { | ||
72 | memset (&e->v, 0, progs->entityfields * 4); | ||
73 | e->free = false; | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | ================= | ||
78 | ED_Alloc | ||
79 | |||
80 | Either finds a free edict, or allocates a new one. | ||
81 | Try to avoid reusing an entity that was recently freed, because it | ||
82 | can cause the client to think the entity morphed into something else | ||
83 | instead of being removed and recreated, which can cause interpolated | ||
84 | angles and bad trails. | ||
85 | ================= | ||
86 | */ | ||
87 | edict_t *ED_Alloc (void) | ||
88 | { | ||
89 | int i; | ||
90 | edict_t *e; | ||
91 | |||
92 | for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++) | ||
93 | { | ||
94 | e = EDICT_NUM(i); | ||
95 | // the first couple seconds of server time can involve a lot of | ||
96 | // freeing and allocating, so relax the replacement policy | ||
97 | if (e->free && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) ) | ||
98 | { | ||
99 | ED_ClearEdict (e); | ||
100 | return e; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | if (i == MAX_EDICTS) | ||
105 | Sys_Error ("ED_Alloc: no free edicts"); | ||
106 | |||
107 | sv.num_edicts++; | ||
108 | e = EDICT_NUM(i); | ||
109 | ED_ClearEdict (e); | ||
110 | |||
111 | return e; | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | ================= | ||
116 | ED_Free | ||
117 | |||
118 | Marks the edict as free | ||
119 | FIXME: walk all entities and NULL out references to this entity | ||
120 | ================= | ||
121 | */ | ||
122 | void ED_Free (edict_t *ed) | ||
123 | { | ||
124 | SV_UnlinkEdict (ed); // unlink from world bsp | ||
125 | |||
126 | ed->free = true; | ||
127 | ed->v.model = 0; | ||
128 | ed->v.takedamage = 0; | ||
129 | ed->v.modelindex = 0; | ||
130 | ed->v.colormap = 0; | ||
131 | ed->v.skin = 0; | ||
132 | ed->v.frame = 0; | ||
133 | VectorCopy (vec3_origin, ed->v.origin); | ||
134 | VectorCopy (vec3_origin, ed->v.angles); | ||
135 | ed->v.nextthink = -1; | ||
136 | ed->v.solid = 0; | ||
137 | |||
138 | ed->freetime = sv.time; | ||
139 | } | ||
140 | |||
141 | //=========================================================================== | ||
142 | |||
143 | /* | ||
144 | ============ | ||
145 | ED_GlobalAtOfs | ||
146 | ============ | ||
147 | */ | ||
148 | ddef_t *ED_GlobalAtOfs (int ofs) | ||
149 | { | ||
150 | ddef_t *def; | ||
151 | int i; | ||
152 | |||
153 | for (i=0 ; i<progs->numglobaldefs ; i++) | ||
154 | { | ||
155 | def = &pr_globaldefs[i]; | ||
156 | if (def->ofs == ofs) | ||
157 | return def; | ||
158 | } | ||
159 | return NULL; | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | ============ | ||
164 | ED_FieldAtOfs | ||
165 | ============ | ||
166 | */ | ||
167 | ddef_t *ED_FieldAtOfs (int ofs) | ||
168 | { | ||
169 | ddef_t *def; | ||
170 | int i; | ||
171 | |||
172 | for (i=0 ; i<progs->numfielddefs ; i++) | ||
173 | { | ||
174 | def = &pr_fielddefs[i]; | ||
175 | if (def->ofs == ofs) | ||
176 | return def; | ||
177 | } | ||
178 | return NULL; | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | ============ | ||
183 | ED_FindField | ||
184 | ============ | ||
185 | */ | ||
186 | ddef_t *ED_FindField (char *name) | ||
187 | { | ||
188 | ddef_t *def; | ||
189 | int i; | ||
190 | |||
191 | for (i=0 ; i<progs->numfielddefs ; i++) | ||
192 | { | ||
193 | def = &pr_fielddefs[i]; | ||
194 | if (!strcmp(pr_strings + def->s_name,name) ) | ||
195 | return def; | ||
196 | } | ||
197 | return NULL; | ||
198 | } | ||
199 | |||
200 | |||
201 | /* | ||
202 | ============ | ||
203 | ED_FindGlobal | ||
204 | ============ | ||
205 | */ | ||
206 | ddef_t *ED_FindGlobal (char *name) | ||
207 | { | ||
208 | ddef_t *def; | ||
209 | int i; | ||
210 | |||
211 | for (i=0 ; i<progs->numglobaldefs ; i++) | ||
212 | { | ||
213 | def = &pr_globaldefs[i]; | ||
214 | if (!strcmp(pr_strings + def->s_name,name) ) | ||
215 | return def; | ||
216 | } | ||
217 | return NULL; | ||
218 | } | ||
219 | |||
220 | |||
221 | /* | ||
222 | ============ | ||
223 | ED_FindFunction | ||
224 | ============ | ||
225 | */ | ||
226 | dfunction_t *ED_FindFunction (char *name) | ||
227 | { | ||
228 | dfunction_t *func; | ||
229 | int i; | ||
230 | |||
231 | for (i=0 ; i<progs->numfunctions ; i++) | ||
232 | { | ||
233 | func = &pr_functions[i]; | ||
234 | if (!strcmp(pr_strings + func->s_name,name) ) | ||
235 | return func; | ||
236 | } | ||
237 | return NULL; | ||
238 | } | ||
239 | |||
240 | |||
241 | eval_t *GetEdictFieldValue(edict_t *ed, char *field) | ||
242 | { | ||
243 | ddef_t *def = NULL; | ||
244 | int i; | ||
245 | static int rep = 0; | ||
246 | |||
247 | for (i=0 ; i<GEFV_CACHESIZE ; i++) | ||
248 | { | ||
249 | if (!strcmp(field, gefvCache[i].field)) | ||
250 | { | ||
251 | def = gefvCache[i].pcache; | ||
252 | goto Done; | ||
253 | } | ||
254 | } | ||
255 | |||
256 | def = ED_FindField (field); | ||
257 | |||
258 | if (strlen(field) < MAX_FIELD_LEN) | ||
259 | { | ||
260 | gefvCache[rep].pcache = def; | ||
261 | strcpy (gefvCache[rep].field, field); | ||
262 | rep ^= 1; | ||
263 | } | ||
264 | |||
265 | Done: | ||
266 | if (!def) | ||
267 | return NULL; | ||
268 | |||
269 | return (eval_t *)((char *)&ed->v + def->ofs*4); | ||
270 | } | ||
271 | |||
272 | |||
273 | /* | ||
274 | ============ | ||
275 | PR_ValueString | ||
276 | |||
277 | Returns a string describing *data in a type specific manner | ||
278 | ============= | ||
279 | */ | ||
280 | char *PR_ValueString (etype_t type, eval_t *val) | ||
281 | { | ||
282 | static char line[256]; | ||
283 | ddef_t *def; | ||
284 | dfunction_t *f; | ||
285 | |||
286 | type &= ~DEF_SAVEGLOBAL; | ||
287 | |||
288 | switch (type) | ||
289 | { | ||
290 | case ev_string: | ||
291 | sprintf (line, "%s", pr_strings + val->string); | ||
292 | break; | ||
293 | case ev_entity: | ||
294 | sprintf (line, "entity %i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)) ); | ||
295 | break; | ||
296 | case ev_function: | ||
297 | f = pr_functions + val->function; | ||
298 | sprintf (line, "%s()", pr_strings + f->s_name); | ||
299 | break; | ||
300 | case ev_field: | ||
301 | def = ED_FieldAtOfs ( val->_int ); | ||
302 | sprintf (line, ".%s", pr_strings + def->s_name); | ||
303 | break; | ||
304 | case ev_void: | ||
305 | sprintf (line, "void"); | ||
306 | break; | ||
307 | case ev_float: | ||
308 | sprintf (line, "%5.1f", val->_float); | ||
309 | break; | ||
310 | case ev_vector: | ||
311 | sprintf (line, "'%5.1f %5.1f %5.1f'", val->vector[0], val->vector[1], val->vector[2]); | ||
312 | break; | ||
313 | case ev_pointer: | ||
314 | sprintf (line, "pointer"); | ||
315 | break; | ||
316 | default: | ||
317 | sprintf (line, "bad type %i", type); | ||
318 | break; | ||
319 | } | ||
320 | |||
321 | return line; | ||
322 | } | ||
323 | |||
324 | /* | ||
325 | ============ | ||
326 | PR_UglyValueString | ||
327 | |||
328 | Returns a string describing *data in a type specific manner | ||
329 | Easier to parse than PR_ValueString | ||
330 | ============= | ||
331 | */ | ||
332 | char *PR_UglyValueString (etype_t type, eval_t *val) | ||
333 | { | ||
334 | static char line[256]; | ||
335 | ddef_t *def; | ||
336 | dfunction_t *f; | ||
337 | |||
338 | type &= ~DEF_SAVEGLOBAL; | ||
339 | |||
340 | switch (type) | ||
341 | { | ||
342 | case ev_string: | ||
343 | sprintf (line, "%s", pr_strings + val->string); | ||
344 | break; | ||
345 | case ev_entity: | ||
346 | sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict))); | ||
347 | break; | ||
348 | case ev_function: | ||
349 | f = pr_functions + val->function; | ||
350 | sprintf (line, "%s", pr_strings + f->s_name); | ||
351 | break; | ||
352 | case ev_field: | ||
353 | def = ED_FieldAtOfs ( val->_int ); | ||
354 | sprintf (line, "%s", pr_strings + def->s_name); | ||
355 | break; | ||
356 | case ev_void: | ||
357 | sprintf (line, "void"); | ||
358 | break; | ||
359 | case ev_float: | ||
360 | sprintf (line, "%f", val->_float); | ||
361 | break; | ||
362 | case ev_vector: | ||
363 | sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]); | ||
364 | break; | ||
365 | default: | ||
366 | sprintf (line, "bad type %i", type); | ||
367 | break; | ||
368 | } | ||
369 | |||
370 | return line; | ||
371 | } | ||
372 | |||
373 | /* | ||
374 | ============ | ||
375 | PR_GlobalString | ||
376 | |||
377 | Returns a string with a description and the contents of a global, | ||
378 | padded to 20 field width | ||
379 | ============ | ||
380 | */ | ||
381 | char *PR_GlobalString (int ofs) | ||
382 | { | ||
383 | char *s; | ||
384 | int i; | ||
385 | ddef_t *def; | ||
386 | void *val; | ||
387 | static char line[128]; | ||
388 | |||
389 | val = (void *)&pr_globals[ofs]; | ||
390 | def = ED_GlobalAtOfs(ofs); | ||
391 | if (!def) | ||
392 | sprintf (line,"%i(???)", ofs); | ||
393 | else | ||
394 | { | ||
395 | s = PR_ValueString (def->type, val); | ||
396 | sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s); | ||
397 | } | ||
398 | |||
399 | i = strlen(line); | ||
400 | for ( ; i<20 ; i++) | ||
401 | strcat (line," "); | ||
402 | strcat (line," "); | ||
403 | |||
404 | return line; | ||
405 | } | ||
406 | |||
407 | char *PR_GlobalStringNoContents (int ofs) | ||
408 | { | ||
409 | int i; | ||
410 | ddef_t *def; | ||
411 | static char line[128]; | ||
412 | |||
413 | def = ED_GlobalAtOfs(ofs); | ||
414 | if (!def) | ||
415 | sprintf (line,"%i(???)", ofs); | ||
416 | else | ||
417 | sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name); | ||
418 | |||
419 | i = strlen(line); | ||
420 | for ( ; i<20 ; i++) | ||
421 | strcat (line," "); | ||
422 | strcat (line," "); | ||
423 | |||
424 | return line; | ||
425 | } | ||
426 | |||
427 | |||
428 | /* | ||
429 | ============= | ||
430 | ED_Print | ||
431 | |||
432 | For debugging | ||
433 | ============= | ||
434 | */ | ||
435 | void ED_Print (edict_t *ed) | ||
436 | { | ||
437 | int l; | ||
438 | ddef_t *d; | ||
439 | int *v; | ||
440 | int i, j; | ||
441 | char *name; | ||
442 | int type; | ||
443 | |||
444 | if (ed->free) | ||
445 | { | ||
446 | Con_Printf ("FREE\n"); | ||
447 | return; | ||
448 | } | ||
449 | |||
450 | Con_Printf("\nEDICT %i:\n", NUM_FOR_EDICT(ed)); | ||
451 | for (i=1 ; i<progs->numfielddefs ; i++) | ||
452 | { | ||
453 | d = &pr_fielddefs[i]; | ||
454 | name = pr_strings + d->s_name; | ||
455 | if (name[strlen(name)-2] == '_') | ||
456 | continue; // skip _x, _y, _z vars | ||
457 | |||
458 | v = (int *)((char *)&ed->v + d->ofs*4); | ||
459 | |||
460 | // if the value is still all 0, skip the field | ||
461 | type = d->type & ~DEF_SAVEGLOBAL; | ||
462 | |||
463 | for (j=0 ; j<type_size[type] ; j++) | ||
464 | if (v[j]) | ||
465 | break; | ||
466 | if (j == type_size[type]) | ||
467 | continue; | ||
468 | |||
469 | Con_Printf ("%s",name); | ||
470 | l = strlen (name); | ||
471 | while (l++ < 15) | ||
472 | Con_Printf (" "); | ||
473 | |||
474 | Con_Printf ("%s\n", PR_ValueString(d->type, (eval_t *)v)); | ||
475 | } | ||
476 | } | ||
477 | |||
478 | /* | ||
479 | ============= | ||
480 | ED_Write | ||
481 | |||
482 | For savegames | ||
483 | ============= | ||
484 | */ | ||
485 | void ED_Write (FILE *f, edict_t *ed) | ||
486 | { | ||
487 | ddef_t *d; | ||
488 | int *v; | ||
489 | int i, j; | ||
490 | char *name; | ||
491 | int type; | ||
492 | |||
493 | fprintf (f, "{\n"); | ||
494 | |||
495 | if (ed->free) | ||
496 | { | ||
497 | fprintf (f, "}\n"); | ||
498 | return; | ||
499 | } | ||
500 | |||
501 | for (i=1 ; i<progs->numfielddefs ; i++) | ||
502 | { | ||
503 | d = &pr_fielddefs[i]; | ||
504 | name = pr_strings + d->s_name; | ||
505 | if (name[strlen(name)-2] == '_') | ||
506 | continue; // skip _x, _y, _z vars | ||
507 | |||
508 | v = (int *)((char *)&ed->v + d->ofs*4); | ||
509 | |||
510 | // if the value is still all 0, skip the field | ||
511 | type = d->type & ~DEF_SAVEGLOBAL; | ||
512 | for (j=0 ; j<type_size[type] ; j++) | ||
513 | if (v[j]) | ||
514 | break; | ||
515 | if (j == type_size[type]) | ||
516 | continue; | ||
517 | |||
518 | fprintf (f,"\"%s\" ",name); | ||
519 | fprintf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v)); | ||
520 | } | ||
521 | |||
522 | fprintf (f, "}\n"); | ||
523 | } | ||
524 | |||
525 | void ED_PrintNum (int ent) | ||
526 | { | ||
527 | ED_Print (EDICT_NUM(ent)); | ||
528 | } | ||
529 | |||
530 | /* | ||
531 | ============= | ||
532 | ED_PrintEdicts | ||
533 | |||
534 | For debugging, prints all the entities in the current server | ||
535 | ============= | ||
536 | */ | ||
537 | void ED_PrintEdicts (void) | ||
538 | { | ||
539 | int i; | ||
540 | |||
541 | Con_Printf ("%i entities\n", sv.num_edicts); | ||
542 | for (i=0 ; i<sv.num_edicts ; i++) | ||
543 | ED_PrintNum (i); | ||
544 | } | ||
545 | |||
546 | /* | ||
547 | ============= | ||
548 | ED_PrintEdict_f | ||
549 | |||
550 | For debugging, prints a single edicy | ||
551 | ============= | ||
552 | */ | ||
553 | void ED_PrintEdict_f (void) | ||
554 | { | ||
555 | int i; | ||
556 | |||
557 | i = Q_atoi (Cmd_Argv(1)); | ||
558 | if (i >= sv.num_edicts) | ||
559 | { | ||
560 | Con_Printf("Bad edict number\n"); | ||
561 | return; | ||
562 | } | ||
563 | ED_PrintNum (i); | ||
564 | } | ||
565 | |||
566 | /* | ||
567 | ============= | ||
568 | ED_Count | ||
569 | |||
570 | For debugging | ||
571 | ============= | ||
572 | */ | ||
573 | void ED_Count (void) | ||
574 | { | ||
575 | int i; | ||
576 | edict_t *ent; | ||
577 | int active, models, solid, step; | ||
578 | |||
579 | active = models = solid = step = 0; | ||
580 | for (i=0 ; i<sv.num_edicts ; i++) | ||
581 | { | ||
582 | ent = EDICT_NUM(i); | ||
583 | if (ent->free) | ||
584 | continue; | ||
585 | active++; | ||
586 | if (ent->v.solid) | ||
587 | solid++; | ||
588 | if (ent->v.model) | ||
589 | models++; | ||
590 | if (ent->v.movetype == MOVETYPE_STEP) | ||
591 | step++; | ||
592 | } | ||
593 | |||
594 | Con_Printf ("num_edicts:%3i\n", sv.num_edicts); | ||
595 | Con_Printf ("active :%3i\n", active); | ||
596 | Con_Printf ("view :%3i\n", models); | ||
597 | Con_Printf ("touch :%3i\n", solid); | ||
598 | Con_Printf ("step :%3i\n", step); | ||
599 | |||
600 | } | ||
601 | |||
602 | /* | ||
603 | ============================================================================== | ||
604 | |||
605 | ARCHIVING GLOBALS | ||
606 | |||
607 | FIXME: need to tag constants, doesn't really work | ||
608 | ============================================================================== | ||
609 | */ | ||
610 | |||
611 | /* | ||
612 | ============= | ||
613 | ED_WriteGlobals | ||
614 | ============= | ||
615 | */ | ||
616 | void ED_WriteGlobals (FILE *f) | ||
617 | { | ||
618 | ddef_t *def; | ||
619 | int i; | ||
620 | char *name; | ||
621 | int type; | ||
622 | |||
623 | fprintf (f,"{\n"); | ||
624 | for (i=0 ; i<progs->numglobaldefs ; i++) | ||
625 | { | ||
626 | def = &pr_globaldefs[i]; | ||
627 | type = def->type; | ||
628 | if ( !(def->type & DEF_SAVEGLOBAL) ) | ||
629 | continue; | ||
630 | type &= ~DEF_SAVEGLOBAL; | ||
631 | |||
632 | if (type != ev_string | ||
633 | && type != ev_float | ||
634 | && type != ev_entity) | ||
635 | continue; | ||
636 | |||
637 | name = pr_strings + def->s_name; | ||
638 | fprintf (f,"\"%s\" ", name); | ||
639 | fprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs])); | ||
640 | } | ||
641 | fprintf (f,"}\n"); | ||
642 | } | ||
643 | |||
644 | /* | ||
645 | ============= | ||
646 | ED_ParseGlobals | ||
647 | ============= | ||
648 | */ | ||
649 | void ED_ParseGlobals (char *data) | ||
650 | { | ||
651 | char keyname[64]; | ||
652 | ddef_t *key; | ||
653 | |||
654 | while (1) | ||
655 | { | ||
656 | // parse key | ||
657 | data = COM_Parse (data); | ||
658 | if (com_token[0] == '}') | ||
659 | break; | ||
660 | if (!data) | ||
661 | Sys_Error ("ED_ParseEntity: EOF without closing brace"); | ||
662 | |||
663 | strcpy (keyname, com_token); | ||
664 | |||
665 | // parse value | ||
666 | data = COM_Parse (data); | ||
667 | if (!data) | ||
668 | Sys_Error ("ED_ParseEntity: EOF without closing brace"); | ||
669 | |||
670 | if (com_token[0] == '}') | ||
671 | Sys_Error ("ED_ParseEntity: closing brace without data"); | ||
672 | |||
673 | key = ED_FindGlobal (keyname); | ||
674 | if (!key) | ||
675 | { | ||
676 | Con_Printf ("'%s' is not a global\n", keyname); | ||
677 | continue; | ||
678 | } | ||
679 | |||
680 | if (!ED_ParseEpair ((void *)pr_globals, key, com_token)) | ||
681 | Host_Error ("ED_ParseGlobals: parse error"); | ||
682 | } | ||
683 | } | ||
684 | |||
685 | //============================================================================ | ||
686 | |||
687 | |||
688 | /* | ||
689 | ============= | ||
690 | ED_NewString | ||
691 | ============= | ||
692 | */ | ||
693 | char *ED_NewString (char *string) | ||
694 | { | ||
695 | char *new, *new_p; | ||
696 | int i,l; | ||
697 | |||
698 | l = strlen(string) + 1; | ||
699 | new = Hunk_Alloc (l); | ||
700 | new_p = new; | ||
701 | |||
702 | for (i=0 ; i< l ; i++) | ||
703 | { | ||
704 | if (string[i] == '\\' && i < l-1) | ||
705 | { | ||
706 | i++; | ||
707 | if (string[i] == 'n') | ||
708 | *new_p++ = '\n'; | ||
709 | else | ||
710 | *new_p++ = '\\'; | ||
711 | } | ||
712 | else | ||
713 | *new_p++ = string[i]; | ||
714 | } | ||
715 | |||
716 | return new; | ||
717 | } | ||
718 | |||
719 | |||
720 | /* | ||
721 | ============= | ||
722 | ED_ParseEval | ||
723 | |||
724 | Can parse either fields or globals | ||
725 | returns false if error | ||
726 | ============= | ||
727 | */ | ||
728 | qboolean ED_ParseEpair (void *base, ddef_t *key, char *s) | ||
729 | { | ||
730 | int i; | ||
731 | char string[128]; | ||
732 | ddef_t *def; | ||
733 | char *v, *w; | ||
734 | void *d; | ||
735 | dfunction_t *func; | ||
736 | |||
737 | d = (void *)((int *)base + key->ofs); | ||
738 | |||
739 | switch (key->type & ~DEF_SAVEGLOBAL) | ||
740 | { | ||
741 | case ev_string: | ||
742 | *(string_t *)d = ED_NewString (s) - pr_strings; | ||
743 | break; | ||
744 | |||
745 | case ev_float: | ||
746 | *(float *)d = Q_atof (s); | ||
747 | break; | ||
748 | |||
749 | case ev_vector: | ||
750 | strcpy (string, s); | ||
751 | v = string; | ||
752 | w = string; | ||
753 | for (i=0 ; i<3 ; i++) | ||
754 | { | ||
755 | while (*v && *v != ' ') | ||
756 | v++; | ||
757 | *v = 0; | ||
758 | ((float *)d)[i] = Q_atof (w); | ||
759 | w = v = v+1; | ||
760 | } | ||
761 | break; | ||
762 | |||
763 | case ev_entity: | ||
764 | *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s))); | ||
765 | break; | ||
766 | |||
767 | case ev_field: | ||
768 | def = ED_FindField (s); | ||
769 | if (!def) | ||
770 | { | ||
771 | Con_Printf ("Can't find field %s\n", s); | ||
772 | return false; | ||
773 | } | ||
774 | *(int *)d = G_INT(def->ofs); | ||
775 | break; | ||
776 | |||
777 | case ev_function: | ||
778 | func = ED_FindFunction (s); | ||
779 | if (!func) | ||
780 | { | ||
781 | Con_Printf ("Can't find function %s\n", s); | ||
782 | return false; | ||
783 | } | ||
784 | *(func_t *)d = func - pr_functions; | ||
785 | break; | ||
786 | |||
787 | default: | ||
788 | break; | ||
789 | } | ||
790 | return true; | ||
791 | } | ||
792 | |||
793 | /* | ||
794 | ==================== | ||
795 | ED_ParseEdict | ||
796 | |||
797 | Parses an edict out of the given string, returning the new position | ||
798 | ed should be a properly initialized empty edict. | ||
799 | Used for initial level load and for savegames. | ||
800 | ==================== | ||
801 | */ | ||
802 | char *ED_ParseEdict (char *data, edict_t *ent) | ||
803 | { | ||
804 | ddef_t *key; | ||
805 | qboolean anglehack; | ||
806 | qboolean init; | ||
807 | char keyname[256]; | ||
808 | int n; | ||
809 | |||
810 | init = false; | ||
811 | |||
812 | // clear it | ||
813 | if (ent != sv.edicts) // hack | ||
814 | memset (&ent->v, 0, progs->entityfields * 4); | ||
815 | |||
816 | // go through all the dictionary pairs | ||
817 | while (1) | ||
818 | { | ||
819 | // parse key | ||
820 | data = COM_Parse (data); | ||
821 | if (com_token[0] == '}') | ||
822 | break; | ||
823 | if (!data) | ||
824 | Sys_Error ("ED_ParseEntity: EOF without closing brace"); | ||
825 | |||
826 | // anglehack is to allow QuakeEd to write single scalar angles | ||
827 | // and allow them to be turned into vectors. (FIXME...) | ||
828 | if (!strcmp(com_token, "angle")) | ||
829 | { | ||
830 | strcpy (com_token, "angles"); | ||
831 | anglehack = true; | ||
832 | } | ||
833 | else | ||
834 | anglehack = false; | ||
835 | |||
836 | // FIXME: change light to _light to get rid of this hack | ||
837 | if (!strcmp(com_token, "light")) | ||
838 | strcpy (com_token, "light_lev"); // hack for single light def | ||
839 | |||
840 | strcpy (keyname, com_token); | ||
841 | |||
842 | // another hack to fix heynames with trailing spaces | ||
843 | n = strlen(keyname); | ||
844 | while (n && keyname[n-1] == ' ') | ||
845 | { | ||
846 | keyname[n-1] = 0; | ||
847 | n--; | ||
848 | } | ||
849 | |||
850 | // parse value | ||
851 | data = COM_Parse (data); | ||
852 | if (!data) | ||
853 | Sys_Error ("ED_ParseEntity: EOF without closing brace"); | ||
854 | |||
855 | if (com_token[0] == '}') | ||
856 | Sys_Error ("ED_ParseEntity: closing brace without data"); | ||
857 | |||
858 | init = true; | ||
859 | |||
860 | // keynames with a leading underscore are used for utility comments, | ||
861 | // and are immediately discarded by quake | ||
862 | if (keyname[0] == '_') | ||
863 | continue; | ||
864 | |||
865 | key = ED_FindField (keyname); | ||
866 | if (!key) | ||
867 | { | ||
868 | Con_Printf ("'%s' is not a field\n", keyname); | ||
869 | continue; | ||
870 | } | ||
871 | |||
872 | if (anglehack) | ||
873 | { | ||
874 | char temp[32]; | ||
875 | strcpy (temp, com_token); | ||
876 | sprintf (com_token, "0 %s 0", temp); | ||
877 | } | ||
878 | |||
879 | if (!ED_ParseEpair ((void *)&ent->v, key, com_token)) | ||
880 | Host_Error ("ED_ParseEdict: parse error"); | ||
881 | } | ||
882 | |||
883 | if (!init) | ||
884 | ent->free = true; | ||
885 | |||
886 | return data; | ||
887 | } | ||
888 | |||
889 | |||
890 | /* | ||
891 | ================ | ||
892 | ED_LoadFromFile | ||
893 | |||
894 | The entities are directly placed in the array, rather than allocated with | ||
895 | ED_Alloc, because otherwise an error loading the map would have entity | ||
896 | number references out of order. | ||
897 | |||
898 | Creates a server's entity / program execution context by | ||
899 | parsing textual entity definitions out of an ent file. | ||
900 | |||
901 | Used for both fresh maps and savegame loads. A fresh map would also need | ||
902 | to call ED_CallSpawnFunctions () to let the objects initialize themselves. | ||
903 | ================ | ||
904 | */ | ||
905 | void ED_LoadFromFile (char *data) | ||
906 | { | ||
907 | edict_t *ent; | ||
908 | int inhibit; | ||
909 | dfunction_t *func; | ||
910 | |||
911 | ent = NULL; | ||
912 | inhibit = 0; | ||
913 | pr_global_struct->time = sv.time; | ||
914 | |||
915 | // parse ents | ||
916 | while (1) | ||
917 | { | ||
918 | // parse the opening brace | ||
919 | data = COM_Parse (data); | ||
920 | if (!data) | ||
921 | break; | ||
922 | if (com_token[0] != '{') | ||
923 | Sys_Error ("ED_LoadFromFile: found %s when expecting {",com_token); | ||
924 | |||
925 | if (!ent) | ||
926 | ent = EDICT_NUM(0); | ||
927 | else | ||
928 | ent = ED_Alloc (); | ||
929 | data = ED_ParseEdict (data, ent); | ||
930 | |||
931 | // remove things from different skill levels or deathmatch | ||
932 | if (deathmatch.value) | ||
933 | { | ||
934 | if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) | ||
935 | { | ||
936 | ED_Free (ent); | ||
937 | inhibit++; | ||
938 | continue; | ||
939 | } | ||
940 | } | ||
941 | else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY)) | ||
942 | || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM)) | ||
943 | || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD)) ) | ||
944 | { | ||
945 | ED_Free (ent); | ||
946 | inhibit++; | ||
947 | continue; | ||
948 | } | ||
949 | |||
950 | // | ||
951 | // immediately call spawn function | ||
952 | // | ||
953 | if (!ent->v.classname) | ||
954 | { | ||
955 | Con_Printf ("No classname for:\n"); | ||
956 | ED_Print (ent); | ||
957 | ED_Free (ent); | ||
958 | continue; | ||
959 | } | ||
960 | |||
961 | // look for the spawn function | ||
962 | func = ED_FindFunction ( pr_strings + ent->v.classname ); | ||
963 | |||
964 | if (!func) | ||
965 | { | ||
966 | Con_Printf ("No spawn function for:\n"); | ||
967 | ED_Print (ent); | ||
968 | ED_Free (ent); | ||
969 | continue; | ||
970 | } | ||
971 | |||
972 | pr_global_struct->self = EDICT_TO_PROG(ent); | ||
973 | PR_ExecuteProgram (func - pr_functions); | ||
974 | } | ||
975 | |||
976 | Con_DPrintf ("%i entities inhibited\n", inhibit); | ||
977 | } | ||
978 | |||
979 | |||
980 | /* | ||
981 | =============== | ||
982 | PR_LoadProgs | ||
983 | =============== | ||
984 | */ | ||
985 | void PR_LoadProgs (void) | ||
986 | { | ||
987 | int i; | ||
988 | |||
989 | // flush the non-C variable lookup cache | ||
990 | for (i=0 ; i<GEFV_CACHESIZE ; i++) | ||
991 | gefvCache[i].field[0] = 0; | ||
992 | |||
993 | CRC_Init (&pr_crc); | ||
994 | |||
995 | //printf("loadprogs 1"); | ||
996 | |||
997 | progs = (dprograms_t *)COM_LoadHunkFile ("progs.dat"); | ||
998 | //printf("loadprogs 2"); | ||
999 | |||
1000 | if (!progs) | ||
1001 | Sys_Error ("PR_LoadProgs: couldn't load progs.dat"); | ||
1002 | Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024); | ||
1003 | //printf("loadprogs 3"); | ||
1004 | |||
1005 | for (i=0 ; i<com_filesize ; i++) | ||
1006 | CRC_ProcessByte (&pr_crc, ((byte *)progs)[i]); | ||
1007 | |||
1008 | //printf("loadprogs 4"); | ||
1009 | // byte swap the header | ||
1010 | for (i=0 ; i<sizeof(*progs)/4 ; i++) | ||
1011 | ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] ); | ||
1012 | |||
1013 | if (progs->version != PROG_VERSION) | ||
1014 | Sys_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION); | ||
1015 | if (progs->crc != PROGHEADER_CRC) | ||
1016 | Sys_Error ("progs.dat system vars have been modified, progdefs.h is out of date"); | ||
1017 | //printf("loadprogs 5"); | ||
1018 | |||
1019 | pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions); | ||
1020 | pr_strings = (char *)progs + progs->ofs_strings; | ||
1021 | pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs); | ||
1022 | pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs); | ||
1023 | pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements); | ||
1024 | |||
1025 | pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals); | ||
1026 | pr_globals = (float *)pr_global_struct; | ||
1027 | |||
1028 | pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t); | ||
1029 | |||
1030 | // byte swap the lumps | ||
1031 | for (i=0 ; i<progs->numstatements ; i++) | ||
1032 | { | ||
1033 | pr_statements[i].op = LittleShort(pr_statements[i].op); | ||
1034 | pr_statements[i].a = LittleShort(pr_statements[i].a); | ||
1035 | pr_statements[i].b = LittleShort(pr_statements[i].b); | ||
1036 | pr_statements[i].c = LittleShort(pr_statements[i].c); | ||
1037 | } | ||
1038 | |||
1039 | for (i=0 ; i<progs->numfunctions; i++) | ||
1040 | { | ||
1041 | pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement); | ||
1042 | pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start); | ||
1043 | pr_functions[i].s_name = LittleLong (pr_functions[i].s_name); | ||
1044 | pr_functions[i].s_file = LittleLong (pr_functions[i].s_file); | ||
1045 | pr_functions[i].numparms = LittleLong (pr_functions[i].numparms); | ||
1046 | pr_functions[i].locals = LittleLong (pr_functions[i].locals); | ||
1047 | } | ||
1048 | |||
1049 | for (i=0 ; i<progs->numglobaldefs ; i++) | ||
1050 | { | ||
1051 | pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type); | ||
1052 | pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs); | ||
1053 | pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name); | ||
1054 | } | ||
1055 | |||
1056 | for (i=0 ; i<progs->numfielddefs ; i++) | ||
1057 | { | ||
1058 | pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type); | ||
1059 | if (pr_fielddefs[i].type & DEF_SAVEGLOBAL) | ||
1060 | Sys_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); | ||
1061 | pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs); | ||
1062 | pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name); | ||
1063 | } | ||
1064 | |||
1065 | for (i=0 ; i<progs->numglobals ; i++) | ||
1066 | ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]); | ||
1067 | } | ||
1068 | |||
1069 | |||
1070 | /* | ||
1071 | =============== | ||
1072 | PR_Init | ||
1073 | =============== | ||
1074 | */ | ||
1075 | void PR_Init (void) | ||
1076 | { | ||
1077 | Cmd_AddCommand ("edict", ED_PrintEdict_f); | ||
1078 | Cmd_AddCommand ("edicts", ED_PrintEdicts); | ||
1079 | Cmd_AddCommand ("edictcount", ED_Count); | ||
1080 | Cmd_AddCommand ("profile", PR_Profile_f); | ||
1081 | Cvar_RegisterVariable (&nomonsters); | ||
1082 | Cvar_RegisterVariable (&gamecfg); | ||
1083 | Cvar_RegisterVariable (&scratch1); | ||
1084 | Cvar_RegisterVariable (&scratch2); | ||
1085 | Cvar_RegisterVariable (&scratch3); | ||
1086 | Cvar_RegisterVariable (&scratch4); | ||
1087 | Cvar_RegisterVariable (&savedgamecfg); | ||
1088 | Cvar_RegisterVariable (&saved1); | ||
1089 | Cvar_RegisterVariable (&saved2); | ||
1090 | Cvar_RegisterVariable (&saved3); | ||
1091 | Cvar_RegisterVariable (&saved4); | ||
1092 | } | ||
1093 | |||
1094 | |||
1095 | |||
1096 | edict_t *EDICT_NUM(int n) | ||
1097 | { | ||
1098 | if (n < 0 || n >= sv.max_edicts) | ||
1099 | Sys_Error ("EDICT_NUM: bad number %i", n); | ||
1100 | return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size); | ||
1101 | } | ||
1102 | |||
1103 | int NUM_FOR_EDICT(edict_t *e) | ||
1104 | { | ||
1105 | int b; | ||
1106 | |||
1107 | b = (byte *)e - (byte *)sv.edicts; | ||
1108 | b = b / pr_edict_size; | ||
1109 | |||
1110 | if (b < 0 || b >= sv.num_edicts) | ||
1111 | Sys_Error ("NUM_FOR_EDICT: bad pointer"); | ||
1112 | return b; | ||
1113 | } | ||