Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5131 | clevermous | 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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 = 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] = 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 |
||
991 | gefvCache[i].field[0] = 0; |
||
992 | |||
993 | CRC_Init (&pr_crc); |
||
994 | |||
995 | progs = (dprograms_t *)COM_LoadHunkFile ("progs.dat"); |
||
996 | if (!progs) |
||
997 | Sys_Error ("PR_LoadProgs: couldn't load progs.dat"); |
||
998 | Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024); |
||
999 | |||
1000 | for (i=0 ; i |
||
1001 | CRC_ProcessByte (&pr_crc, ((byte *)progs)[i]); |
||
1002 | |||
1003 | // byte swap the header |
||
1004 | for (i=0 ; i |
||
1005 | ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] ); |
||
1006 | |||
1007 | if (progs->version != PROG_VERSION) |
||
1008 | Sys_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION); |
||
1009 | if (progs->crc != PROGHEADER_CRC) |
||
1010 | Sys_Error ("progs.dat system vars have been modified, progdefs.h is out of date"); |
||
1011 | |||
1012 | pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions); |
||
1013 | pr_strings = (char *)progs + progs->ofs_strings; |
||
1014 | pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs); |
||
1015 | pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs); |
||
1016 | pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements); |
||
1017 | |||
1018 | pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals); |
||
1019 | pr_globals = (float *)pr_global_struct; |
||
1020 | |||
1021 | pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t); |
||
1022 | |||
1023 | // byte swap the lumps |
||
1024 | for (i=0 ; i |
||
1025 | { |
||
1026 | pr_statements[i].op = LittleShort(pr_statements[i].op); |
||
1027 | pr_statements[i].a = LittleShort(pr_statements[i].a); |
||
1028 | pr_statements[i].b = LittleShort(pr_statements[i].b); |
||
1029 | pr_statements[i].c = LittleShort(pr_statements[i].c); |
||
1030 | } |
||
1031 | |||
1032 | for (i=0 ; i |
||
1033 | { |
||
1034 | pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement); |
||
1035 | pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start); |
||
1036 | pr_functions[i].s_name = LittleLong (pr_functions[i].s_name); |
||
1037 | pr_functions[i].s_file = LittleLong (pr_functions[i].s_file); |
||
1038 | pr_functions[i].numparms = LittleLong (pr_functions[i].numparms); |
||
1039 | pr_functions[i].locals = LittleLong (pr_functions[i].locals); |
||
1040 | } |
||
1041 | |||
1042 | for (i=0 ; i |
||
1043 | { |
||
1044 | pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type); |
||
1045 | pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs); |
||
1046 | pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name); |
||
1047 | } |
||
1048 | |||
1049 | for (i=0 ; i |
||
1050 | { |
||
1051 | pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type); |
||
1052 | if (pr_fielddefs[i].type & DEF_SAVEGLOBAL) |
||
1053 | Sys_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); |
||
1054 | pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs); |
||
1055 | pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name); |
||
1056 | } |
||
1057 | |||
1058 | for (i=0 ; i |
||
1059 | ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]); |
||
1060 | } |
||
1061 | |||
1062 | |||
1063 | /* |
||
1064 | =============== |
||
1065 | PR_Init |
||
1066 | =============== |
||
1067 | */ |
||
1068 | void PR_Init (void) |
||
1069 | { |
||
1070 | Cmd_AddCommand ("edict", ED_PrintEdict_f); |
||
1071 | Cmd_AddCommand ("edicts", ED_PrintEdicts); |
||
1072 | Cmd_AddCommand ("edictcount", ED_Count); |
||
1073 | Cmd_AddCommand ("profile", PR_Profile_f); |
||
1074 | Cvar_RegisterVariable (&nomonsters); |
||
1075 | Cvar_RegisterVariable (&gamecfg); |
||
1076 | Cvar_RegisterVariable (&scratch1); |
||
1077 | Cvar_RegisterVariable (&scratch2); |
||
1078 | Cvar_RegisterVariable (&scratch3); |
||
1079 | Cvar_RegisterVariable (&scratch4); |
||
1080 | Cvar_RegisterVariable (&savedgamecfg); |
||
1081 | Cvar_RegisterVariable (&saved1); |
||
1082 | Cvar_RegisterVariable (&saved2); |
||
1083 | Cvar_RegisterVariable (&saved3); |
||
1084 | Cvar_RegisterVariable (&saved4); |
||
1085 | } |
||
1086 | |||
1087 | |||
1088 | |||
1089 | edict_t *EDICT_NUM(int n) |
||
1090 | { |
||
1091 | if (n < 0 || n >= sv.max_edicts) |
||
1092 | Sys_Error ("EDICT_NUM: bad number %i", n); |
||
1093 | return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size); |
||
1094 | } |
||
1095 | |||
1096 | int NUM_FOR_EDICT(edict_t *e) |
||
1097 | { |
||
1098 | int b; |
||
1099 | |||
1100 | b = (byte *)e - (byte *)sv.edicts; |
||
1101 | b = b / pr_edict_size; |
||
1102 | |||
1103 | if (b < 0 || b >= sv.num_edicts) |
||
1104 | Sys_Error ("NUM_FOR_EDICT: bad pointer"); |
||
1105 | return b; |
||
1106 | }>>3>>>>20>20>>> |