1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <limits.h>
5 #include <ctype.h>
6 #include <sys/stat.h>
7 #include <math.h>
8
9 #include "../include/fio.h"
10 #include "../include/string.h"
11 #include "../include/strexp.h"
12 #include "../include/disk.h"
13
14 #include "sfm.h"
15
16 #include "obj.h"
17 #include "objutils.h"
18 #include "objio.h"
19 #include "menu.h"
20 #include "sarreality.h"
21 #include "weather.h"
22 #include "mission.h"
23 #include "simutils.h"
24 #include "sar.h"
25 #include "sarfio.h"
26 #include "sceneio.h"
27 #include "missionio.h"
28 #include "config.h"
29
30
31 static int SARMissionGetInterceptNameFromScene(
32 const char *filename,
33 const char *obj_name,
34 sar_intercept_struct *intercept
35 );
36 static int SARMissionLoadSceneMapToMenuMap(
37 sar_core_struct *core_ptr, sar_menu_struct *m,
38 sar_menu_map_struct *map_ptr,
39 const char *filename /* Scene file */
40 );
41 static int SARMissionLoadSceneMapToMenuMapMarkings(
42 sar_core_struct *core_ptr,
43 sar_menu_struct *m, sar_menu_map_struct *map_ptr,
44 const char *scene_filename, const char *mission_filename
45 );
46
47 char *SARMissionLoadDescription(const char *filename);
48 void SARMissionLoadSceneToMenuMap(
49 sar_core_struct *core_ptr,
50 sar_menu_struct *m,
51 const char *filename /* Mission file name */
52 );
53 void SARMissionLoadMissionLogToMenuMap(
54 sar_core_struct *core_ptr,
55 sar_menu_struct *m,
56 const char *filename /* Mission log file name */
57 );
58
59 sar_mission_struct *SARMissionLoadFromFile(
60 sar_core_struct *core_ptr,
61 const char *filename,
62 void *client_data,
63 int (*progress_func)(void *, long, long)
64 );
65
66 void SARMissionLogReset(
67 sar_core_struct *core_ptr, sar_mission_struct *mission,
68 const char *filename /* Mission log file name */
69 );
70 void SARMissionLogEvent(
71 sar_core_struct *core_ptr, sar_mission_struct *mission,
72 int event_type, /* One of SAR_LOG_EVENT_* */
73 float tod, /* Time of day in seconds since midnight */
74 sar_position_struct *pos, /* Position of event */
75 const float *value, /* Additional values */
76 int total_values, /* Total number of additional values */
77 const char *message, /* The message */
78 const char *filename /* Mission log file name */
79 );
80
81
82 #define ATOI(s) (((s) != NULL) ? atoi(s) : 0)
83 #define ATOL(s) (((s) != NULL) ? atol(s) : 0)
84 #define ATOF(s) (((s) != NULL) ? (float)atof(s) : 0.0f)
85 #define STRDUP(s) (((s) != NULL) ? strdup(s) : NULL)
86
87 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
88 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
89 #define CLIP(a,l,h) (MIN(MAX((a),(l)),(h)))
90 #define STRLEN(s) (((s) != NULL) ? (int)strlen(s) : 0)
91 #define STRISEMPTY(s) (((s) != NULL) ? (*(s) == '\0') : 1)
92
93 #define RADTODEG(r) ((r) * 180.0 / PI)
94 #define DEGTORAD(d) ((d) * PI / 180.0)
95
96 #define ISCOMMENT(c) ((c) == SAR_COMMENT_CHAR)
97 #define ISCR(c) (((c) == '\n') || ((c) == '\r'))
98
99
100 /*
101 * Load intercept by name from scene file, returns 0 on success
102 * or -1 on no match.
103 */
SARMissionGetInterceptNameFromScene(const char * filename,const char * obj_name,sar_intercept_struct * intercept)104 static int SARMissionGetInterceptNameFromScene(
105 const char *filename, const char *obj_name,
106 sar_intercept_struct *intercept
107 )
108 {
109 int i, status, ptype, total_parms;
110 char *cur_obj_name = NULL;
111 void *p, **parm;
112 sar_parm_version_struct *p_version;
113 sar_parm_object_name_struct *p_object_name;
114 sar_parm_translate_struct *p_translate;
115 sar_parm_rotate_struct *p_rotate;
116 Boolean matched_translate = False, matched_rotate = False;
117
118 if(STRISEMPTY(filename) || STRISEMPTY(obj_name) ||
119 (intercept == NULL)
120 )
121 return(-1);
122
123 /* Load parms from scene file */
124 status = SARParmLoadFromFile(
125 filename, SAR_FILE_FORMAT_SCENE,
126 &parm, &total_parms,
127 -1,
128 NULL, NULL
129 );
130 if(status)
131 return(-1);
132
133 /* Iterate through loaded parms */
134 for(i = 0; i < total_parms; i++)
135 {
136 p = parm[i];
137 if(p == NULL)
138 continue;
139
140 /* Handle by parm type */
141 ptype = *(int *)p;
142 switch(ptype)
143 {
144 case SAR_PARM_VERSION:
145 p_version = (sar_parm_version_struct *)p;
146 if((p_version->major > PROG_VERSION_MAJOR) ||
147 (p_version->minor > PROG_VERSION_MINOR) ||
148 (p_version->release > PROG_VERSION_RELEASE)
149 )
150 {
151 int need_warn = 0;
152 if(p_version->major > PROG_VERSION_MAJOR)
153 need_warn = 1;
154 else if((p_version->major == PROG_VERSION_MAJOR) &&
155 (p_version->minor > PROG_VERSION_MINOR)
156 )
157 need_warn = 1;
158 else if((p_version->major == PROG_VERSION_MAJOR) &&
159 (p_version->minor == PROG_VERSION_MINOR) &&
160 (p_version->release == PROG_VERSION_RELEASE)
161 )
162 need_warn = 1;
163 if(need_warn)
164 fprintf(
165 stderr,
166 "%s: Warning: File format version %i.%i.%i is newer than program\
167 version %i.%i.%i.\n",
168 filename,
169 p_version->major, p_version->minor,
170 p_version->release, PROG_VERSION_MAJOR,
171 PROG_VERSION_MINOR, PROG_VERSION_RELEASE
172 );
173 }
174 break;
175
176 case SAR_PARM_OBJECT_NAME:
177 p_object_name = (sar_parm_object_name_struct *)p;
178 /* Update current object name */
179 free(cur_obj_name);
180 cur_obj_name = STRDUP(p_object_name->name);
181 /* Reset all other context values */
182 matched_translate = False;
183 matched_rotate = False;
184 break;
185
186 case SAR_PARM_TRANSLATE:
187 p_translate = (sar_parm_translate_struct *)p;
188 if((cur_obj_name != NULL) && !matched_translate)
189 {
190 if(!strcasecmp(cur_obj_name, obj_name))
191 {
192 intercept->x = p_translate->translate.x;
193 intercept->y = p_translate->translate.y;
194 intercept->z = p_translate->translate.z;
195
196 intercept->radius = 40; /* Explicitly set */
197
198 matched_translate = True;
199 }
200 }
201 break;
202
203 case SAR_PARM_ROTATE:
204 p_rotate = (sar_parm_rotate_struct *)p;
205 if((cur_obj_name != NULL) && !matched_rotate)
206 {
207 if(!strcasecmp(cur_obj_name, obj_name))
208 {
209 /* TODO, not really needed right now */
210
211 matched_rotate = True;
212 }
213 }
214 break;
215 }
216 }
217
218 /* Delete all loaded parms */
219 SARParmDeleteAll(&parm, &total_parms);
220
221 free(cur_obj_name);
222
223 return(0);
224 }
225
226 /*
227 * Loads the scene map of the given scene specified by filename
228 * to the given map object as a texture. Any existing texture already
229 * loaded on the given map object will be unloaded first.
230 *
231 * Returns -1 on error or 0 on success.
232 *
233 * This function is intended to be called by
234 * SARMissionLoadMissionLogToMenuMap().
235 */
SARMissionLoadSceneMapToMenuMap(sar_core_struct * core_ptr,sar_menu_struct * m,sar_menu_map_struct * map_ptr,const char * filename)236 static int SARMissionLoadSceneMapToMenuMap(
237 sar_core_struct *core_ptr, sar_menu_struct *m,
238 sar_menu_map_struct *map_ptr,
239 const char *filename /* Scene file */
240 )
241 {
242 int i, status, ptype, total_parms;
243 const char *img_path;
244 void *p, **parm;
245 sar_parm_version_struct *p_version;
246 sar_parm_name_struct *p_name;
247 sar_parm_scene_map_struct *p_scene_map;
248
249
250 if(STRISEMPTY(filename) || (map_ptr == NULL))
251 return(-1);
252
253 /* Load parms from scene file */
254 status = SARParmLoadFromFile(
255 filename, SAR_FILE_FORMAT_SCENE,
256 &parm, &total_parms,
257 -1,
258 NULL, NULL
259 );
260 if(status)
261 return(-1);
262
263 /* Iterate through loaded parms */
264 for(i = 0; i < total_parms; i++)
265 {
266 p = parm[i];
267 if(p == NULL)
268 continue;
269
270 /* Handle by parm type */
271 ptype = *(int *)p;
272 switch(ptype)
273 {
274 case SAR_PARM_VERSION:
275 p_version = (sar_parm_version_struct *)p;
276 if((p_version->major > PROG_VERSION_MAJOR) ||
277 (p_version->minor > PROG_VERSION_MINOR) ||
278 (p_version->release > PROG_VERSION_RELEASE)
279 )
280 {
281 int need_warn = 0;
282 if(p_version->major > PROG_VERSION_MAJOR)
283 need_warn = 1;
284 else if((p_version->major == PROG_VERSION_MAJOR) &&
285 (p_version->minor > PROG_VERSION_MINOR)
286 )
287 need_warn = 1;
288 else if((p_version->major == PROG_VERSION_MAJOR) &&
289 (p_version->minor == PROG_VERSION_MINOR) &&
290 (p_version->release == PROG_VERSION_RELEASE)
291 )
292 need_warn = 1;
293 if(need_warn)
294 fprintf(
295 stderr,
296 "%s: Warning: File format version %i.%i.%i is newer than program\
297 version %i.%i.%i.\n",
298 filename,
299 p_version->major, p_version->minor,
300 p_version->release, PROG_VERSION_MAJOR,
301 PROG_VERSION_MINOR, PROG_VERSION_RELEASE
302 );
303 }
304 break;
305
306 case SAR_PARM_NAME:
307 p_name = (sar_parm_name_struct *)p;
308 free(map_ptr->title);
309 map_ptr->title = STRDUP(p_name->name);
310 break;
311
312 case SAR_PARM_SCENE_MAP:
313 p_scene_map = (sar_parm_scene_map_struct *)p;
314 /* Width and height in meters */
315 map_ptr->bg_tex_width = (float)MAX(p_scene_map->width, 10.0);
316 map_ptr->bg_tex_height = (float)MAX(p_scene_map->height, 10.0);
317
318 /* Texture image path */
319 img_path = p_scene_map->file;
320 if(!STRISEMPTY(img_path))
321 {
322 char *dpath;
323
324 if(ISPATHABSOLUTE(img_path))
325 {
326 dpath = STRDUP(img_path);
327 }
328 else
329 {
330 struct stat stat_buf;
331 const char *s = PrefixPaths(dname.local_data, img_path);
332 if((s != NULL) ? stat(s, &stat_buf) : True)
333 s = PrefixPaths(
334 dname.global_data, img_path
335 );
336 dpath = STRDUP(s);
337 }
338
339 /* Unload menu map's background texture as needed */
340 V3DTextureDestroy(map_ptr->bg_tex);
341
342 /* Load new texture for menu map's background */
343 map_ptr->bg_tex = V3DTextureLoadFromFile2DPreempt(
344 dpath,
345 "mission_map_tex", /* Not used */
346 V3D_TEX_FORMAT_RGB /* Destination format */
347 );
348 V3DTexturePriority(map_ptr->bg_tex, 0.95f);
349
350 free(dpath);
351 }
352 break;
353
354 } /* Handle by parm type */
355 } /* Iterate through loaded parms */
356
357 /* Delete all loaded parms */
358 SARParmDeleteAll(&parm, &total_parms);
359
360 return(0);
361 }
362
363 /*
364 * Called by SARMissionLoadSceneMapToMenuMap().
365 *
366 * Loads the scene map and markings of the given scene specified by
367 * filename to the map object as a texture
368 *
369 * Intercept points are not loaded.
370 */
SARMissionLoadSceneMapToMenuMapMarkings(sar_core_struct * core_ptr,sar_menu_struct * m,sar_menu_map_struct * map_ptr,const char * scene_filename,const char * mission_filename)371 static int SARMissionLoadSceneMapToMenuMapMarkings(
372 sar_core_struct *core_ptr,
373 sar_menu_struct *m, sar_menu_map_struct *map_ptr,
374 const char *scene_filename, const char *mission_filename
375 )
376 {
377 int i, n, pass, ptype, total_parms;
378 const char *img_path;
379 void *p, **parm;
380 sar_menu_color_struct fg_color;
381 sar_menu_map_marking_struct *marking_ptr;
382 Boolean got_translate,
383 got_rotate,
384 got_object_name,
385 got_object_map_desc;
386 sar_parm_version_struct *p_version;
387 sar_parm_name_struct *p_name;
388 sar_parm_scene_map_struct *p_scene_map;
389 sar_parm_new_object_struct *p_new_object;
390 sar_parm_new_helipad_struct *p_new_helipad;
391 sar_parm_new_runway_struct *p_new_runway;
392 sar_parm_new_human_struct *p_new_human;
393 sar_parm_new_premodeled_struct *p_new_premodeled;
394 sar_parm_translate_struct *p_translate;
395 sar_parm_rotate_struct *p_rotate;
396 sar_parm_object_name_struct *p_object_name;
397 sar_parm_object_map_description_struct *p_object_map_desc;
398
399 if((m == NULL) || (map_ptr == NULL))
400 return(-1);
401
402 /* Load parms from scene file */
403 if(SARParmLoadFromFile(
404 scene_filename, SAR_FILE_FORMAT_SCENE,
405 &parm, &total_parms,
406 -1,
407 NULL, NULL
408 ))
409 return(-1);
410
411 /* Iterate through loaded parms */
412 for(i = 0; i < total_parms; i++)
413 {
414 p = parm[i];
415 if(p == NULL)
416 continue;
417
418 /* Handle by parm type */
419 ptype = *(int *)p;
420 switch(ptype)
421 {
422 case SAR_PARM_VERSION:
423 p_version = (sar_parm_version_struct *)p;
424 if((p_version->major > PROG_VERSION_MAJOR) ||
425 (p_version->minor > PROG_VERSION_MINOR) ||
426 (p_version->release > PROG_VERSION_RELEASE)
427 )
428 {
429 int need_warn = 0;
430 if(p_version->major > PROG_VERSION_MAJOR)
431 need_warn = 1;
432 else if((p_version->major == PROG_VERSION_MAJOR) &&
433 (p_version->minor > PROG_VERSION_MINOR)
434 )
435 need_warn = 1;
436 else if((p_version->major == PROG_VERSION_MAJOR) &&
437 (p_version->minor == PROG_VERSION_MINOR) &&
438 (p_version->release == PROG_VERSION_RELEASE)
439 )
440 need_warn = 1;
441 if(need_warn)
442 fprintf(
443 stderr,
444 "%s: Warning: File format version %i.%i.%i is newer than program\
445 version %i.%i.%i.\n",
446 scene_filename,
447 p_version->major, p_version->minor,
448 p_version->release, PROG_VERSION_MAJOR,
449 PROG_VERSION_MINOR, PROG_VERSION_RELEASE
450 );
451 }
452 break;
453
454 case SAR_PARM_NAME:
455 p_name = (sar_parm_name_struct *)p;
456 free(map_ptr->title);
457 map_ptr->title = STRDUP(p_name->name);
458 break;
459
460 case SAR_PARM_SCENE_MAP:
461 p_scene_map = (sar_parm_scene_map_struct *)p;
462 /* Width and height in meters */
463 map_ptr->bg_tex_width = (float)MAX(p_scene_map->width, 10.0);
464 map_ptr->bg_tex_height = (float)MAX(p_scene_map->height, 10.0);
465
466 /* Texture image path */
467 img_path = p_scene_map->file;
468 if(!STRISEMPTY(img_path))
469 {
470 char *dpath;
471
472 if(ISPATHABSOLUTE(img_path))
473 {
474 dpath = STRDUP(img_path);
475 }
476 else
477 {
478 struct stat stat_buf;
479 const char *s = PrefixPaths(dname.local_data, img_path);
480 if((s != NULL) ? stat(s, &stat_buf) : True)
481 s = PrefixPaths(
482 dname.global_data, img_path
483 );
484 dpath = STRDUP(s);
485 }
486
487 /* Unload menu map's background texture as needed */
488 V3DTextureDestroy(map_ptr->bg_tex);
489
490 /* Load new texture for menu map's background */
491 map_ptr->bg_tex = V3DTextureLoadFromFile2DPreempt(
492 dpath,
493 "mission_map_tex", /* Not used */
494 V3D_TEX_FORMAT_RGB /* Destination format */
495 );
496 V3DTexturePriority(map_ptr->bg_tex, 0.95f);
497
498 free(dpath);
499 }
500 break;
501
502 } /* Handle by parm type */
503 } /* Iterate through loaded parms */
504
505
506 /* Resets all local contexts pointers */
507 #define RESET_CONTEXTS { \
508 marking_ptr = NULL; \
509 got_translate = False; \
510 got_rotate = False; \
511 got_object_name = False; \
512 got_object_map_desc = False; \
513 }
514
515 /* Reset local contexts */
516 RESET_CONTEXTS
517
518 /* Perform two iterations, the first on the existing loaded
519 * parms and then reload the parms from the mission file
520 * and load from them. This will ensure that we get map markings
521 * from first the scene file and then the mission file.
522 */
523 for(pass = 0; pass < 2; pass++)
524 {
525 /* Iterate through loaded parms (second time around) */
526 for(i = 0; i < total_parms; i++)
527 {
528 p = parm[i];
529 if(p == NULL)
530 continue;
531
532 /* Handle by parm type */
533 ptype = *(int *)p;
534 switch(ptype)
535 {
536 case SAR_PARM_NEW_OBJECT:
537 p_new_object = (sar_parm_new_object_struct *)p;
538 /* Reset local contexts */
539 RESET_CONTEXTS
540 /* Ignore for now */
541 break;
542
543 case SAR_PARM_NEW_HELIPAD:
544 p_new_helipad = (sar_parm_new_helipad_struct *)p;
545 /* Reset local contexts */
546 RESET_CONTEXTS
547 /* Set foreground color */
548 fg_color.a = 1.0f;
549 fg_color.r = 0.0f;
550 fg_color.g = 1.0f;
551 fg_color.b = 0.0f;
552 /* Allocate new marking on map for intercept */
553 n = SARMenuMapAppendMarking(
554 map_ptr, SAR_MENU_MAP_MARKING_TYPE_ICON,
555 &fg_color, 0.0, 0.0, 0.0, 0.0,
556 core_ptr->menumap_helipad_img,
557 NULL
558 );
559 marking_ptr = (n > -1) ? map_ptr->marking[n] : NULL;
560 break;
561
562 case SAR_PARM_NEW_RUNWAY:
563 p_new_runway = (sar_parm_new_runway_struct *)p;
564 /* Reset local contexts */
565 RESET_CONTEXTS
566 /* Ignore for now */
567 break;
568
569 case SAR_PARM_NEW_HUMAN:
570 p_new_human = (sar_parm_new_human_struct *)p;
571 /* Reset local contexts */
572 RESET_CONTEXTS
573 /* Ignore for now */
574 break;
575
576 case SAR_PARM_NEW_PREMODELED:
577 p_new_premodeled = (sar_parm_new_premodeled_struct *)p;
578 /* Reset local contexts */
579 RESET_CONTEXTS
580 /* Ignore for now */
581 break;
582
583 case SAR_PARM_TRANSLATE:
584 p_translate = (sar_parm_translate_struct *)p;
585 if((marking_ptr != NULL) && !got_translate)
586 {
587 marking_ptr->x = p_translate->translate.x;
588 marking_ptr->y = p_translate->translate.y;
589 got_translate = True;
590 }
591 break;
592
593 case SAR_PARM_ROTATE:
594 p_rotate = (sar_parm_rotate_struct *)p;
595 if((marking_ptr != NULL) && !got_rotate)
596 {
597 /* Ignore for now */
598 got_rotate = True;
599 }
600 break;
601
602 case SAR_PARM_OBJECT_NAME:
603 p_object_name = (sar_parm_object_name_struct *)p;
604 if((marking_ptr != NULL) && !got_object_name)
605 {
606 /* Ignore for now */
607 got_object_name = True;
608 }
609 break;
610
611 case SAR_PARM_OBJECT_MAP_DESCRIPTION:
612 p_object_map_desc =
613 (sar_parm_object_map_description_struct *)p;
614 if((marking_ptr != NULL) && !got_object_map_desc)
615 {
616 free(marking_ptr->desc);
617 marking_ptr->desc = STRDUP(
618 p_object_map_desc->description
619 );
620 got_object_map_desc = True;
621 }
622 break;
623
624 } /* Handle by parm type */
625 } /* Iterate through loaded parms (second time around) */
626
627 if(pass >= 1)
628 break;
629
630 /* Delete loaded parms and then load parms from mission file */
631 SARParmDeleteAll(&parm, &total_parms);
632 if(SARParmLoadFromFile(
633 mission_filename, SAR_FILE_FORMAT_MISSION,
634 &parm, &total_parms,
635 -1,
636 NULL, NULL
637 ))
638 break;
639
640 RESET_CONTEXTS
641 }
642
643 /* Delete loaded parms */
644 SARParmDeleteAll(&parm, &total_parms);
645
646 #undef RESET_CONTEXTS
647
648 return(0);
649 }
650
651
652 /*
653 * Returns a pointer to a dynamically allocated description fetched
654 * from the specified mission file.
655 *
656 * The calling function needs to deallocate the returned string.
657 */
SARMissionLoadDescription(const char * filename)658 char *SARMissionLoadDescription(const char *filename)
659 {
660 int i, status, ptype, total_parms;
661 void *p, **parm;
662 sar_parm_description_struct *p_desc;
663 char *desc = NULL;
664
665 if(STRISEMPTY(filename))
666 return(desc);
667
668 /* Load parms from mission file */
669 status = SARParmLoadFromFile(
670 filename, SAR_FILE_FORMAT_MISSION,
671 &parm, &total_parms,
672 SAR_PARM_DESCRIPTION,
673 NULL, NULL
674 );
675 if(status)
676 return(desc);
677
678 /* Iterate through loaded parms */
679 for(i = 0; i < total_parms; i++)
680 {
681 p = parm[i];
682 if(p == NULL)
683 continue;
684
685 ptype = *(int *)p;
686 switch(ptype)
687 {
688 case SAR_PARM_DESCRIPTION:
689 p_desc = (sar_parm_description_struct *)p;
690 free(desc);
691 desc = STRDUP(p_desc->description);
692 break;
693 }
694 }
695
696 /* Delete loaded parms */
697 SARParmDeleteAll(&parm, &total_parms);
698
699 return(desc);
700 }
701
702 /*
703 * Loads the scene specified by filename to the map object on the
704 * menu.
705 *
706 * All relivent objects specified in the scene will be loaded
707 * as markings on the map object.
708 */
SARMissionLoadSceneToMenuMap(sar_core_struct * core_ptr,sar_menu_struct * m,const char * filename)709 void SARMissionLoadSceneToMenuMap(
710 sar_core_struct *core_ptr,
711 sar_menu_struct *m,
712 const char *filename /* Mission file name */
713 )
714 {
715 int i, n, status, ptype, total_parms;
716 void *p, **parm;
717 sar_parm_version_struct *p_version;
718 sar_parm_mission_scene_file_struct *p_mission_scene_file;
719 sar_parm_mission_begin_at_struct *p_mission_begin_at;
720 sar_parm_mission_begin_at_pos_struct *p_mission_begin_at_pos;
721 sar_parm_mission_arrive_at_struct *p_mission_arrive_at;
722 sar_parm_mission_add_intercept_struct *p_mission_add_intercept;
723 int map_num = -1;
724 sar_menu_map_struct *map_ptr = NULL;
725 const char *s;
726 Boolean begin_at_set = False;
727 char *scene_filename = NULL,
728 *arrive_at_name = NULL,
729 *begin_at_name = NULL;
730 sar_menu_map_marking_struct *marking_ptr = NULL,
731 *intercept_marking_ptr = NULL;
732 int intercepts_set = 0;
733
734 if(m == NULL)
735 return;
736
737 /* Get first map object on the menu */
738 for(i = 0; i < m->total_objects; i++)
739 {
740 p = m->object[i];
741 if(p == NULL)
742 continue;
743
744 ptype = (*(int *)p);
745 if(ptype == SAR_MENU_OBJECT_TYPE_MAP)
746 {
747 map_num = i;
748 map_ptr = SAR_MENU_MAP(p);
749 break;
750 }
751 }
752 if(map_ptr == NULL)
753 return;
754
755 /* Delete all markings on menu's map object */
756 SARMenuMapDeleteAllMarkings(map_ptr);
757
758 /* If no filename was given then only delete map markings */
759 if(STRISEMPTY(filename))
760 return;
761
762 /* Note that order of which parameters appear in the mission
763 * file is important!
764 *
765 * We expect to parse certain parameters before others
766 */
767
768 /* Load parms from mission file */
769 status = SARParmLoadFromFile(
770 filename, SAR_FILE_FORMAT_MISSION,
771 &parm, &total_parms,
772 -1,
773 NULL, NULL
774 );
775 if(status)
776 return;
777
778 /* Iterate through loaded parms */
779 for(i = 0; i < total_parms; i++)
780 {
781 p = parm[i];
782 if(p == NULL)
783 continue;
784
785 /* Handle by parm type */
786 ptype = *(int *)p;
787 switch(ptype)
788 {
789 case SAR_PARM_VERSION:
790 p_version = (sar_parm_version_struct *)p;
791 if((p_version->major > PROG_VERSION_MAJOR) ||
792 (p_version->minor > PROG_VERSION_MINOR) ||
793 (p_version->release > PROG_VERSION_RELEASE)
794 )
795 {
796 int need_warn = 0;
797 if(p_version->major > PROG_VERSION_MAJOR)
798 need_warn = 1;
799 else if((p_version->major == PROG_VERSION_MAJOR) &&
800 (p_version->minor > PROG_VERSION_MINOR)
801 )
802 need_warn = 1;
803 else if((p_version->major == PROG_VERSION_MAJOR) &&
804 (p_version->minor == PROG_VERSION_MINOR) &&
805 (p_version->release == PROG_VERSION_RELEASE)
806 )
807 need_warn = 1;
808 if(need_warn)
809 fprintf(
810 stderr,
811 "%s: Warning: File format version %i.%i.%i is newer than program\
812 version %i.%i.%i.\n",
813 filename,
814 p_version->major, p_version->minor,
815 p_version->release, PROG_VERSION_MAJOR,
816 PROG_VERSION_MINOR, PROG_VERSION_RELEASE
817 );
818 }
819 break;
820
821 case SAR_PARM_MISSION_SCENE_FILE:
822 p_mission_scene_file = (sar_parm_mission_scene_file_struct *)p;
823 s = p_mission_scene_file->file;
824 if(!STRISEMPTY(s))
825 {
826 if(ISPATHABSOLUTE(s))
827 {
828 free(scene_filename);
829 scene_filename = STRDUP(s);
830 }
831 else
832 {
833 struct stat stat_buf;
834 char *s2 = PrefixPaths(dname.local_data, s);
835 if((s2 != NULL) ? stat(s2, &stat_buf) : True)
836 s2 = PrefixPaths(dname.global_data, s);
837 if(s2 != NULL)
838 {
839 free(scene_filename);
840 scene_filename = STRDUP(s2);
841 }
842 }
843
844 /* Load information from scene file which are
845 * relivent to the mission map (such as map
846 * background texture file and landmarks)
847 */
848 SARMissionLoadSceneMapToMenuMapMarkings(
849 core_ptr, m, map_ptr,
850 scene_filename, /* Scene file */
851 filename /* Mission file */
852 );
853 }
854 break;
855
856 case SAR_PARM_MISSION_BEGIN_AT:
857 p_mission_begin_at = (sar_parm_mission_begin_at_struct *)p;
858 if(p_mission_begin_at->name != NULL)
859 {
860 sar_menu_color_struct fg_color;
861 sar_intercept_struct intercept;
862 memset(&intercept, 0x00, sizeof(sar_intercept_struct));
863
864 /* Update begin at name */
865 free(begin_at_name);
866 begin_at_name = STRDUP(p_mission_begin_at->name);
867
868 /* Match intercept by name and set begin at location (only
869 * if the begin at location has not been set yet)
870 */
871 if(!SARMissionGetInterceptNameFromScene(
872 scene_filename, begin_at_name, &intercept
873 ) && !begin_at_set)
874 {
875 fg_color.a = 1.0;
876 fg_color.r = 0.0;
877 fg_color.g = 1.0;
878 fg_color.b = 0.0;
879
880 /* Allocate new marking on map for intercept */
881 n = SARMenuMapAppendMarking(
882 map_ptr, SAR_MENU_MAP_MARKING_TYPE_INTERCEPT_LINE,
883 &fg_color,
884 intercept.x, intercept.y,
885 0.0, 0.0,
886 NULL, NULL
887 );
888 marking_ptr = ((n >= 0) ? map_ptr->marking[n] : NULL);
889 intercept_marking_ptr = marking_ptr;
890 if(marking_ptr != NULL)
891 {
892 intercepts_set++;
893
894 /* Reset meters to pixels coeff zoom */
895 map_ptr->m_to_pixels_coeff = (float)SAR_MAP_DEF_MTOP_COEFF;
896
897 /* Set initial scroll position on map with
898 * respect to the begin at location
899 */
900 map_ptr->scroll_x = (int)(-intercept.x *
901 map_ptr->m_to_pixels_coeff);
902 map_ptr->scroll_y = (int)(-intercept.y *
903 map_ptr->m_to_pixels_coeff);
904
905 /* Reset selected_marking on menu map */
906 map_ptr->selected_marking = -1;
907 }
908
909 begin_at_set = True;
910 }
911 }
912 break;
913
914 case SAR_PARM_MISSION_BEGIN_AT_POS:
915 p_mission_begin_at_pos = (sar_parm_mission_begin_at_pos_struct *)p;
916 if(!begin_at_set)
917 {
918 sar_menu_color_struct fg_color;
919 sar_position_struct *ipos = &p_mission_begin_at_pos->pos;
920
921 fg_color.a = 1.0f;
922 fg_color.r = 0.0f;
923 fg_color.g = 1.0f;
924 fg_color.b = 0.0f;
925
926 /* Allocate new marking on map for intercept */
927 n = SARMenuMapAppendMarking(
928 map_ptr, SAR_MENU_MAP_MARKING_TYPE_INTERCEPT_LINE,
929 &fg_color,
930 ipos->x, ipos->y,
931 0.0f, 0.0f,
932 NULL, NULL
933 );
934 marking_ptr = (n > -1) ? map_ptr->marking[n] : NULL;
935 intercept_marking_ptr = marking_ptr;
936 if(marking_ptr != NULL)
937 {
938 intercepts_set++;
939
940 /* Reset meters to pixels coeff zoom */
941 map_ptr->m_to_pixels_coeff = (float)SAR_MAP_DEF_MTOP_COEFF;
942
943 /* Set initial scroll position on map with
944 * respect to the begin at location
945 */
946 map_ptr->scroll_x = (int)(-ipos->x *
947 map_ptr->m_to_pixels_coeff);
948 map_ptr->scroll_y = (int)(-ipos->y *
949 map_ptr->m_to_pixels_coeff);
950
951 /* Reset selected_marking on menu map */
952 map_ptr->selected_marking = -1;
953 }
954
955 begin_at_set = True;
956 }
957 break;
958
959 case SAR_PARM_MISSION_ARRIVE_AT:
960 p_mission_arrive_at = (sar_parm_mission_arrive_at_struct *)p;
961 if(p_mission_arrive_at->name)
962 {
963 free(arrive_at_name);
964 arrive_at_name = STRDUP(p_mission_arrive_at->name);
965 }
966 break;
967
968 case SAR_PARM_MISSION_ADD_INTERCEPT:
969 p_mission_add_intercept = (sar_parm_mission_add_intercept_struct *)p;
970 if(1)
971 {
972 sar_intercept_struct intercept;
973 memset(&intercept, 0x00, sizeof(sar_intercept_struct));
974
975 /* Set intercept by reference code */
976 switch(p_mission_add_intercept->ref_code)
977 {
978 case 3: /* Arrive at location */
979 SARMissionGetInterceptNameFromScene(
980 scene_filename, arrive_at_name,
981 &intercept
982 );
983 break;
984
985 case 2: /* Begin at location */
986 SARMissionGetInterceptNameFromScene(
987 scene_filename, begin_at_name,
988 &intercept
989 );
990 break;
991
992 default: /* Standard intercept */
993 intercept.x = p_mission_add_intercept->pos.x;
994 intercept.y = p_mission_add_intercept->pos.y;
995 intercept.z = p_mission_add_intercept->pos.z;
996 intercept.radius = p_mission_add_intercept->radius;
997 intercept.urgency = p_mission_add_intercept->urgency;
998 break;
999 }
1000
1001 /* Allocate new map marking structure, note previous
1002 * marking structure should already be allocated from
1003 * another add intercept parameter or begin at name
1004 * parameter
1005 */
1006 if((marking_ptr != NULL) &&
1007 (intercept_marking_ptr != NULL)
1008 )
1009 {
1010 sar_menu_map_marking_struct *new_ptr;
1011
1012 /* Allocate new intercept marking structure and
1013 * copy over end position values from previous
1014 * marking structure
1015 */
1016 n = SARMenuMapAppendMarking(
1017 map_ptr, SAR_MENU_MAP_MARKING_TYPE_INTERCEPT_LINE,
1018 NULL, 0.0f, 0.0f, 0.0f, 0.0f,
1019 NULL, NULL
1020 );
1021 new_ptr = (n > -1) ? map_ptr->marking[n] : NULL;
1022
1023 /* Set end position on last marking structure */
1024 marking_ptr->x_end = intercept.x;
1025 marking_ptr->y_end = intercept.y;
1026
1027 intercepts_set++;
1028
1029 /* New marking structure allocated successfully? */
1030 if(new_ptr != NULL)
1031 {
1032 /* Copy over fg color from previous marking */
1033 memcpy(
1034 &new_ptr->fg_color,
1035 &marking_ptr->fg_color,
1036 sizeof(sar_menu_color_struct)
1037 );
1038 new_ptr->x = intercept.x;
1039 new_ptr->y = intercept.y;
1040
1041 intercepts_set++;
1042
1043 intercept_marking_ptr = new_ptr;
1044 marking_ptr = new_ptr;
1045 }
1046 else
1047 {
1048 intercept_marking_ptr = NULL;
1049 marking_ptr = NULL;
1050 }
1051
1052 /* Allocate another marking structure to represent
1053 * way point icon
1054 */
1055 n = SARMenuMapAppendMarking(
1056 map_ptr, SAR_MENU_MAP_MARKING_TYPE_ICON,
1057 NULL,
1058 intercept.x, intercept.y,
1059 0.0f, 0.0f,
1060 core_ptr->menumap_intercept_img, NULL
1061 );
1062 new_ptr = ((n >= 0) ? map_ptr->marking[n] : NULL);
1063 }
1064 }
1065 break;
1066 } /* Handle parm by type */
1067 } /* Iterate through loaded parms */
1068
1069
1070 /* Delete loaded parms */
1071 SARParmDeleteAll(&parm, &total_parms);
1072
1073
1074 /* Delete local context names */
1075 free(scene_filename);
1076 scene_filename = NULL;
1077
1078 free(arrive_at_name);
1079 arrive_at_name = NULL;
1080
1081 free(begin_at_name);
1082 begin_at_name = NULL;
1083
1084
1085 /* If the number of intercepts set on the map is an odd number,
1086 * then that implies that the last intercept line marking is
1087 * extraneous
1088 */
1089 if(intercepts_set & 1)
1090 {
1091 /* Delete the last marking pointer of type
1092 * SAR_MENU_MAP_MARKING_TYPE_INTERCEPT_LINE
1093 *
1094 * Iterate from last to first of all markings on the map
1095 */
1096 for(i = map_ptr->total_markings - 1; i >= 0; i--)
1097 {
1098 marking_ptr = map_ptr->marking[i];
1099 if(marking_ptr == NULL)
1100 continue;
1101
1102 /* Check marking type */
1103 if(marking_ptr->type == SAR_MENU_MAP_MARKING_TYPE_INTERCEPT_LINE)
1104 {
1105 /* Need to delete this marking on the map, set the
1106 * pointer to NULL after deleting it
1107 */
1108 free(marking_ptr);
1109 map_ptr->marking[i] = NULL;
1110
1111 /* Do not delete any more markings */
1112 break;
1113 }
1114 }
1115 }
1116
1117 }
1118
1119 /*
1120 * Procedure to load the mission log specified by filename to the
1121 * map object on the given menu.
1122 */
SARMissionLoadMissionLogToMenuMap(sar_core_struct * core_ptr,sar_menu_struct * m,const char * filename)1123 void SARMissionLoadMissionLogToMenuMap(
1124 sar_core_struct *core_ptr,
1125 sar_menu_struct *m,
1126 const char *filename /* Mission log file name */
1127 )
1128 {
1129 int i, ptype, status, total_parms;
1130 void *p, **parm;
1131 sar_position_struct *pos;
1132 sar_parm_version_struct *p_version;
1133 sar_parm_mission_log_header_struct *p_mission_log_header;
1134 sar_parm_mission_log_event_struct *p_mission_log_event;
1135 int map_num = -1;
1136 sar_menu_map_struct *map_ptr = NULL;
1137 Boolean handled_header = False;
1138 char *title = NULL,
1139 *scene_filename = NULL,
1140 *player_stats_filename = NULL;
1141 sar_menu_map_marking_struct *last_intercept_marking = NULL;
1142 int total_intercept_markings = 0;
1143 int total_events = 0;
1144
1145 if(m == NULL)
1146 return;
1147
1148 /* Get first map object on the menu */
1149 for(i = 0; i < m->total_objects; i++)
1150 {
1151 p = m->object[i];
1152 if(p == NULL)
1153 continue;
1154
1155 ptype = (*(int *)p);
1156 if(ptype == SAR_MENU_OBJECT_TYPE_MAP)
1157 {
1158 map_num = i;
1159 map_ptr = SAR_MENU_MAP(p);
1160 break;
1161 }
1162 }
1163 if(map_ptr == NULL)
1164 return;
1165
1166 /* Delete all markings on menu's map object */
1167 SARMenuMapDeleteAllMarkings(map_ptr);
1168
1169 /* If no filename was given then only delete map markings */
1170 if(STRISEMPTY(filename))
1171 return;
1172
1173 /* Load parms from mission log file */
1174 status = SARParmLoadFromFile(
1175 filename, SAR_FILE_FORMAT_MISSION_LOG,
1176 &parm, &total_parms,
1177 -1,
1178 NULL, NULL
1179 );
1180 if(status)
1181 return;
1182
1183
1184 /* Iterate through loaded parms */
1185 for(i = 0; i < total_parms; i++)
1186 {
1187 p = parm[i];
1188 if(p == NULL)
1189 continue;
1190
1191 /* Handle by parm type */
1192 ptype = *(int *)p;
1193 switch(ptype)
1194 {
1195 case SAR_PARM_VERSION:
1196 p_version = (sar_parm_version_struct *)p;
1197 if((p_version->major > PROG_VERSION_MAJOR) ||
1198 (p_version->minor > PROG_VERSION_MINOR) ||
1199 (p_version->release > PROG_VERSION_RELEASE)
1200 )
1201 {
1202 int need_warn = 0;
1203 if(p_version->major > PROG_VERSION_MAJOR)
1204 need_warn = 1;
1205 else if((p_version->major == PROG_VERSION_MAJOR) &&
1206 (p_version->minor > PROG_VERSION_MINOR)
1207 )
1208 need_warn = 1;
1209 else if((p_version->major == PROG_VERSION_MAJOR) &&
1210 (p_version->minor == PROG_VERSION_MINOR) &&
1211 (p_version->release == PROG_VERSION_RELEASE)
1212 )
1213 need_warn = 1;
1214 if(need_warn)
1215 fprintf(
1216 stderr,
1217 "%s: Warning: File format version %i.%i.%i is newer than program\
1218 version %i.%i.%i.\n",
1219 filename,
1220 p_version->major, p_version->minor,
1221 p_version->release, PROG_VERSION_MAJOR,
1222 PROG_VERSION_MINOR, PROG_VERSION_RELEASE
1223 );
1224 }
1225 break;
1226
1227 case SAR_PARM_MISSION_LOG_HEADER:
1228 p_mission_log_header = (sar_parm_mission_log_header_struct *)p;
1229
1230 free(title);
1231 title = STRDUP(p_mission_log_header->title);
1232
1233 free(scene_filename);
1234 scene_filename = STRDUP(p_mission_log_header->scene_file);
1235
1236 free(player_stats_filename);
1237 player_stats_filename = STRDUP(p_mission_log_header->player_stats_file);
1238
1239 /* Handle this header if we have not yet handled the
1240 * header earlier
1241 */
1242 if(!handled_header)
1243 {
1244 /* Got scene file name from reading the log file? */
1245 if(scene_filename != NULL)
1246 SARMissionLoadSceneMapToMenuMap(
1247 core_ptr, m, map_ptr, scene_filename
1248 );
1249
1250 /* Reset map */
1251 map_ptr->m_to_pixels_coeff = (float)SAR_MAP_DEF_MTOP_COEFF;
1252 /* Reset initial scroll position */
1253 map_ptr->scroll_x = (int)(
1254 0.0f * map_ptr->m_to_pixels_coeff
1255 );
1256 map_ptr->scroll_y = (int)(
1257 0.0f * map_ptr->m_to_pixels_coeff
1258 );
1259 /* Reset selected_marking on menu map */
1260 map_ptr->selected_marking = -1;
1261
1262 /* Title needs to be set after calling
1263 * SARMissionLoadSceneMapToMenuMap() since it will
1264 * set the title
1265 */
1266 free(map_ptr->title);
1267 map_ptr->title = STRDUP(title);
1268
1269 /* Mark that we handled the header */
1270 handled_header = True;
1271 }
1272 break;
1273
1274 case SAR_PARM_MISSION_LOG_EVENT:
1275 p_mission_log_event = (sar_parm_mission_log_event_struct *)p;
1276 pos = &p_mission_log_event->pos;
1277 if(True)
1278 {
1279 int n;
1280 sar_menu_color_struct fg_color;
1281
1282 fg_color.a = 1.0f;
1283 fg_color.r = 0.0f;
1284 fg_color.g = 1.0f;
1285 fg_color.b = 0.0f;
1286
1287 /* Handle mission log event by its type */
1288 switch(p_mission_log_event->event_type)
1289 {
1290 case SAR_MISSION_LOG_EVENT_COMMENT:
1291 SARMenuMapAppendMarking(
1292 map_ptr, SAR_MENU_MAP_MARKING_TYPE_ICON,
1293 &fg_color,
1294 pos->x, pos->y,
1295 0.0f, 0.0f,
1296 NULL, /* No icon */
1297 p_mission_log_event->message
1298 );
1299 break;
1300
1301 case SAR_MISSION_LOG_EVENT_POSITION:
1302 /* Was there a prior intercept marking? */
1303 if(last_intercept_marking != NULL)
1304 {
1305 /* Set last intercept marking's end position
1306 * to the position specified by this log event
1307 */
1308 last_intercept_marking->x_end = pos->x;
1309 last_intercept_marking->y_end = pos->y;
1310 }
1311 /* Create a new intercept line marking */
1312 n = SARMenuMapAppendMarking(
1313 map_ptr, SAR_MENU_MAP_MARKING_TYPE_INTERCEPT_LINE,
1314 &fg_color,
1315 pos->x, pos->y,
1316 pos->x, pos->y,
1317 NULL, /* No icon */
1318 NULL /* No message */
1319 );
1320 /* Record pointer to this intercept line marking */
1321 last_intercept_marking = (n > -1) ?
1322 map_ptr->marking[n] : NULL;
1323 /* Increment total number of intercept markings */
1324 total_intercept_markings++;
1325 break;
1326
1327 case SAR_MISSION_LOG_EVENT_TAKEOFF:
1328 SARMenuMapAppendMarking(
1329 map_ptr, SAR_MENU_MAP_MARKING_TYPE_ICON,
1330 &fg_color,
1331 pos->x, pos->y,
1332 0.0f, 0.0f,
1333 core_ptr->menumap_helicopter_img,
1334 p_mission_log_event->message
1335 );
1336 break;
1337
1338 case SAR_MISSION_LOG_EVENT_LAND:
1339 SARMenuMapAppendMarking(
1340 map_ptr, SAR_MENU_MAP_MARKING_TYPE_ICON,
1341 &fg_color,
1342 pos->x, pos->y,
1343 0.0f, 0.0f,
1344 core_ptr->menumap_helicopter_img,
1345 p_mission_log_event->message
1346 );
1347 break;
1348
1349 case SAR_MISSION_LOG_EVENT_CRASH:
1350 SARMenuMapAppendMarking(
1351 map_ptr, SAR_MENU_MAP_MARKING_TYPE_ICON,
1352 &fg_color,
1353 pos->x, pos->y,
1354 0.0f, 0.0f,
1355 core_ptr->menumap_crash_img,
1356 p_mission_log_event->message
1357 );
1358 break;
1359
1360 case SAR_MISSION_LOG_EVENT_PICKUP:
1361 SARMenuMapAppendMarking(
1362 map_ptr, SAR_MENU_MAP_MARKING_TYPE_ICON,
1363 &fg_color,
1364 pos->x, pos->y,
1365 0.0f, 0.0f,
1366 core_ptr->menumap_victim_img,
1367 p_mission_log_event->message
1368 );
1369 break;
1370
1371 case SAR_MISSION_LOG_EVENT_DROPOFF:
1372 SARMenuMapAppendMarking(
1373 map_ptr, SAR_MENU_MAP_MARKING_TYPE_ICON,
1374 &fg_color,
1375 pos->x, pos->y,
1376 0.0f, 0.0f,
1377 core_ptr->menumap_helicopter_img,
1378 p_mission_log_event->message
1379 );
1380 break;
1381 }
1382 }
1383
1384 /* If this is the first event then set map's scroll
1385 * position to it
1386 */
1387 if(total_events == 0)
1388 {
1389 map_ptr->scroll_x = (int)(
1390 -pos->x * map_ptr->m_to_pixels_coeff
1391 );
1392 map_ptr->scroll_y = (int)(
1393 -pos->y * map_ptr->m_to_pixels_coeff
1394 );
1395 map_ptr->selected_marking = 0;
1396 }
1397
1398 total_events++;
1399
1400 break;
1401 }
1402 }
1403
1404 /* Delete loaded parms */
1405 SARParmDeleteAll(&parm, &total_parms);
1406
1407 free(title);
1408 free(scene_filename);
1409 free(player_stats_filename);
1410 }
1411
1412 /*
1413 * Loads a new mission
1414 *
1415 * Note that the scene structure in the core structure must be
1416 * allocated and with all values reset.
1417 */
SARMissionLoadFromFile(sar_core_struct * core_ptr,const char * filename,void * client_data,int (* progress_func)(void *,long,long))1418 sar_mission_struct *SARMissionLoadFromFile(
1419 sar_core_struct *core_ptr, const char *filename,
1420 void *client_data,
1421 int (*progress_func)(void *, long, long)
1422 )
1423 {
1424 int i, status, ptype, total_parms;
1425 void *p, **parm;
1426 sar_parm_version_struct *p_version;
1427 sar_parm_name_struct *p_name;
1428 sar_parm_description_struct *p_desc;
1429 sar_parm_player_model_file_struct *p_player_model_file;
1430 sar_parm_weather_struct *p_weather;
1431 sar_parm_time_of_day_struct *p_time_of_day;
1432 sar_parm_texture_base_directory_struct *p_texture_base_directory;
1433 sar_parm_texture_load_struct *p_texture_load;
1434 sar_parm_mission_new_objective_struct *p_mission_new_objective;
1435 sar_parm_mission_scene_file_struct *p_mission_scene_file;
1436 sar_parm_mission_time_left_struct *p_mission_time_left;
1437 sar_parm_mission_begin_at_struct *p_mission_begin_at;
1438 sar_parm_mission_begin_at_pos_struct *p_mission_begin_at_pos;
1439 sar_parm_mission_arrive_at_struct *p_mission_arrive_at;
1440 sar_parm_mission_message_success_struct *p_mission_message_success;
1441 sar_parm_mission_message_fail_struct *p_mission_message_fail;
1442 sar_parm_mission_humans_tally_struct *p_mission_humans_tally;
1443 sar_parm_mission_add_intercept_struct *p_mission_add_intercept;
1444 sar_parm_new_object_struct *p_new_object;
1445 sar_parm_new_helipad_struct *p_new_helipad;
1446 sar_parm_new_runway_struct *p_new_runway;
1447 sar_parm_new_human_struct *p_new_human;
1448 sar_parm_new_fire_struct *p_new_fire;
1449 sar_parm_new_smoke_struct *p_new_smoke;
1450 sar_parm_new_premodeled_struct *p_new_premodeled;
1451 sar_parm_model_file_struct *p_model_file;
1452 sar_parm_translate_struct *p_translate;
1453 sar_parm_translate_random_struct *p_translate_random;
1454 sar_parm_rotate_struct *p_rotate;
1455 sar_parm_no_depth_test_struct *p_no_depth_test;
1456 sar_parm_polygon_offset_struct *p_polygon_offset;
1457 sar_parm_object_name_struct *p_object_name;
1458 sar_parm_runway_approach_lighting_north_struct *p_runway_applight_n;
1459 sar_parm_runway_approach_lighting_south_struct *p_runway_applight_s;
1460 sar_parm_human_message_enter_struct *p_human_message_enter;
1461 sar_parm_human_reference_struct *p_human_reference;
1462
1463 Boolean loaded_scene = False;
1464 sar_mission_struct *mission;
1465 int objective_num = -1;
1466 sar_mission_objective_struct *objective = NULL;
1467
1468 int humans_need_rescue = 0;
1469 char *begin_at_name = NULL,
1470 *arrive_at_name = NULL,
1471 *weather_preset_name = NULL;
1472
1473 int obj_num = -1;
1474 sar_object_struct *obj_ptr = NULL;
1475 sar_object_aircraft_struct *obj_aircraft_ptr = NULL;
1476 sar_object_ground_struct *obj_ground_ptr = NULL;
1477 sar_object_helipad_struct *obj_helipad_ptr = NULL;
1478 sar_object_runway_struct *obj_runway_ptr = NULL;
1479 sar_object_human_struct *obj_human_ptr = NULL;
1480 sar_object_smoke_struct *obj_smoke_ptr = NULL;
1481 sar_object_fire_struct *obj_fire_ptr = NULL;
1482 Boolean begin_at_set = False;
1483 sar_position_struct begin_pos;
1484 sar_direction_struct begin_dir;
1485
1486 sar_scene_struct *scene = core_ptr->scene;
1487 sar_object_struct ***ptr = &core_ptr->object;
1488 int *total = &core_ptr->total_objects;
1489 const sar_option_struct *opt = &core_ptr->option;
1490 if((scene == NULL) || (filename == NULL))
1491 return(NULL);
1492
1493 /* Regets object substructure pointers from the specified object */
1494 #define CONTEXT_REGET_SUBSTRUCTURE_PTRS(_o_) { \
1495 if((_o_) != NULL) { \
1496 obj_aircraft_ptr = SAR_OBJ_GET_AIRCRAFT(_o_); \
1497 obj_ground_ptr = SAR_OBJ_GET_GROUND(_o_); \
1498 obj_helipad_ptr = SAR_OBJ_GET_HELIPAD(_o_); \
1499 obj_runway_ptr = SAR_OBJ_GET_RUNWAY(_o_); \
1500 obj_human_ptr = SAR_OBJ_GET_HUMAN(_o_); \
1501 obj_smoke_ptr = SAR_OBJ_GET_SMOKE(_o_); \
1502 obj_fire_ptr = SAR_OBJ_GET_FIRE(_o_); \
1503 } \
1504 }
1505
1506 /* Note, order of which parameters appear in the mission file
1507 * is important! We expect to parse certain parameters before
1508 * others in this function.
1509 */
1510
1511 /* Load parms from mission file */
1512 status = SARParmLoadFromFile(
1513 filename, SAR_FILE_FORMAT_MISSION,
1514 &parm, &total_parms,
1515 -1,
1516 NULL, NULL
1517 );
1518 if(status)
1519 return(NULL);
1520
1521 if(opt->runtime_debug)
1522 printf(
1523 "SARMissionLoadFromFile(): Creating new mission...\n"
1524 );
1525
1526 /* Allocate a new mission structure */
1527 mission = (sar_mission_struct *)calloc(
1528 1, sizeof(sar_mission_struct)
1529 );
1530 if(mission == NULL)
1531 {
1532 SARParmDeleteAll(&parm, &total_parms);
1533 return(NULL);
1534 }
1535
1536 /* Set up default mission values */
1537 mission->state = MISSION_STATE_IN_PROGRESS;
1538 mission->title = NULL;
1539 mission->description = NULL;
1540 mission->start_location_name = NULL;
1541 mission->scene_file = NULL;
1542 mission->player_model_file = NULL;
1543 mission->player_stats_file = NULL;
1544 mission->objective = NULL;
1545 mission->total_objectives = 0;
1546 mission->cur_objective = 0; /* Always start on first objective */
1547 mission->time_spent = 0.0f;
1548 mission->check_int = 1000; /* In milliseconds */
1549 mission->next_check = cur_millitime + mission->check_int;
1550 mission->log_position_int = 10000;
1551 mission->next_log_position = cur_millitime + mission->log_position_int;
1552
1553 /* Iterate through loaded parms */
1554 for(i = 0; i < total_parms; i++)
1555 {
1556 p = parm[i];
1557 if(p == NULL)
1558 continue;
1559
1560 /* Handle by parm type */
1561 ptype = *(int *)p;
1562 switch(ptype)
1563 {
1564 case SAR_PARM_VERSION:
1565 p_version = (sar_parm_version_struct *)p;
1566 if((p_version->major > PROG_VERSION_MAJOR) ||
1567 (p_version->minor > PROG_VERSION_MINOR) ||
1568 (p_version->release > PROG_VERSION_RELEASE)
1569 )
1570 {
1571 int need_warn = 0;
1572 if(p_version->major > PROG_VERSION_MAJOR)
1573 need_warn = 1;
1574 else if((p_version->major == PROG_VERSION_MAJOR) &&
1575 (p_version->minor > PROG_VERSION_MINOR)
1576 )
1577 need_warn = 1;
1578 else if((p_version->major == PROG_VERSION_MAJOR) &&
1579 (p_version->minor == PROG_VERSION_MINOR) &&
1580 (p_version->release == PROG_VERSION_RELEASE)
1581 )
1582 need_warn = 1;
1583 if(need_warn)
1584 fprintf(
1585 stderr,
1586 "%s: Warning: File format version %i.%i.%i is newer than program\
1587 version %i.%i.%i.\n",
1588 filename,
1589 p_version->major, p_version->minor,
1590 p_version->release, PROG_VERSION_MAJOR,
1591 PROG_VERSION_MINOR, PROG_VERSION_RELEASE
1592 );
1593 }
1594 break;
1595
1596 case SAR_PARM_NAME:
1597 p_name = (sar_parm_name_struct *)p;
1598 free(mission->title);
1599 mission->title = STRDUP(p_name->name);
1600 break;
1601
1602 case SAR_PARM_DESCRIPTION:
1603 p_desc = (sar_parm_description_struct *)p;
1604 free(mission->description);
1605 mission->description = STRDUP(p_desc->description);
1606 break;
1607
1608 case SAR_PARM_PLAYER_MODEL_FILE:
1609 p_player_model_file = (sar_parm_player_model_file_struct *)p;
1610 if(loaded_scene)
1611 {
1612 const char *player_file = p_player_model_file->file;
1613 char *full_path;
1614
1615 /* Complete path */
1616 if(ISPATHABSOLUTE(player_file))
1617 {
1618 full_path = STRDUP(player_file);
1619 }
1620 else
1621 {
1622 struct stat stat_buf;
1623 full_path = STRDUP(PrefixPaths(
1624 dname.local_data, player_file
1625 ));
1626 if((full_path != NULL) ? stat(full_path, &stat_buf) : True)
1627 {
1628 free(full_path);
1629 full_path = STRDUP(PrefixPaths(
1630 dname.global_data, player_file
1631 ));
1632 }
1633 }
1634 if(full_path == NULL)
1635 fprintf(
1636 stderr,
1637 "%s: Warning: Unable to complete path \"%s\".\n",
1638 filename, player_file
1639 );
1640
1641 /* Update player model file name on mission and
1642 * core structures.
1643 */
1644 free(mission->player_model_file);
1645 mission->player_model_file = STRDUP(full_path);
1646
1647 free(core_ptr->cur_player_model_file);
1648 core_ptr->cur_player_model_file = STRDUP(full_path);
1649
1650 /* Create the player object since the model file is
1651 * now known
1652 */
1653 SARSceneAddPlayerObject(
1654 core_ptr, scene,
1655 full_path,
1656 &begin_pos, &begin_dir
1657 );
1658
1659 /* Update object context pointers */
1660 obj_num = scene->player_obj_num;
1661 obj_ptr = scene->player_obj_ptr;
1662 CONTEXT_REGET_SUBSTRUCTURE_PTRS(obj_ptr)
1663
1664 free(full_path);
1665 }
1666 else
1667 {
1668 fprintf(
1669 stderr,
1670 "%s: \"player_model_file\" may not be specified before \"mission_scene_file\".\n",
1671 filename
1672 );
1673 }
1674 break;
1675
1676 case SAR_PARM_WEATHER:
1677 p_weather = (sar_parm_weather_struct *)p;
1678 if(loaded_scene)
1679 {
1680 fprintf(
1681 stderr,
1682 "%s: \"weather\" may not be specified after \"mission_scene_file\".\n",
1683 filename
1684 );
1685 }
1686 else
1687 {
1688 free(weather_preset_name);
1689 weather_preset_name = STRDUP(p_weather->weather_preset_name);
1690 }
1691 break;
1692
1693 case SAR_PARM_TIME_OF_DAY:
1694 p_time_of_day = (sar_parm_time_of_day_struct *)p;
1695 if(loaded_scene)
1696 {
1697 scene->tod = p_time_of_day->tod;
1698 #if 0
1699 /* The tod_code is updated in SARSimUpdateScene() */
1700 scene->tod_code = SAR_TOD_CODE_UNDEFINED;
1701 #endif
1702 }
1703 else
1704 {
1705 fprintf(
1706 stderr,
1707 "%s: \"time_of_day\" may not be specified before \"mission_scene_file\".\n",
1708 filename
1709 );
1710 }
1711 break;
1712
1713 case SAR_PARM_TEXTURE_BASE_DIRECTORY:
1714 p_texture_base_directory = (sar_parm_texture_base_directory_struct *)p;
1715 break;
1716
1717 case SAR_PARM_TEXTURE_LOAD:
1718 p_texture_load = (sar_parm_texture_load_struct *)p;
1719 SARObjLoadTexture(
1720 core_ptr, scene, p_texture_load
1721 );
1722 break;
1723
1724 case SAR_PARM_MISSION_SCENE_FILE:
1725 p_mission_scene_file = (sar_parm_mission_scene_file_struct *)p;
1726 if(loaded_scene)
1727 {
1728 fprintf(
1729 stderr,
1730 "%s: Warning: Redefination of \"mission_scene_file\" ignored.\n",
1731 filename
1732 );
1733 }
1734 else
1735 {
1736 const char *scene_file = p_mission_scene_file->file;
1737 char *full_path;
1738
1739 /* Complete path */
1740 if(ISPATHABSOLUTE(scene_file))
1741 {
1742 full_path = STRDUP(scene_file);
1743 }
1744 else
1745 {
1746 struct stat stat_buf;
1747 full_path = STRDUP(PrefixPaths(
1748 dname.local_data, scene_file
1749 ));
1750 if((full_path != NULL) ? stat(full_path, &stat_buf) : True)
1751 {
1752 free(full_path);
1753 full_path = STRDUP(PrefixPaths(
1754 dname.global_data, scene_file
1755 ));
1756 }
1757 }
1758 if(full_path == NULL)
1759 fprintf(
1760 stderr,
1761 "%s: Warning: Unable to complete path \"%s\".\n",
1762 filename, scene_file
1763 );
1764
1765 /* Set new scene file on mission structure */
1766 free(mission->scene_file);
1767 mission->scene_file = STRDUP(full_path);
1768 free(full_path);
1769
1770 /* Load scene */
1771 status = SARSceneLoadFromFile(
1772 core_ptr, scene,
1773 mission->scene_file,
1774 weather_preset_name,
1775 client_data, progress_func
1776 );
1777 if(status)
1778 {
1779 /* Failed to load scene */
1780 fprintf(
1781 stderr,
1782 "%s: Error occured while loading scene \"%s\".\n",
1783 filename, mission->scene_file
1784 );
1785 SARSceneDestroy(
1786 core_ptr, scene,
1787 ptr, total
1788 );
1789 SARMissionDelete(mission);
1790 mission = NULL;
1791
1792 break;
1793 }
1794 else
1795 {
1796 loaded_scene = True;
1797 }
1798 }
1799 break;
1800
1801 case SAR_PARM_MISSION_NEW_OBJECTIVE:
1802 p_mission_new_objective = (sar_parm_mission_new_objective_struct *)p;
1803 /* Create a new objective */
1804 objective_num = mission->total_objectives;
1805 mission->total_objectives = objective_num + 1;
1806 mission->objective = (sar_mission_objective_struct *)realloc(
1807 mission->objective,
1808 mission->total_objectives * sizeof(sar_mission_objective_struct)
1809 );
1810 if(mission->objective == NULL)
1811 {
1812 mission->total_objectives = 0;
1813 objective_num = -1;
1814 objective = NULL;
1815 }
1816 else
1817 {
1818 objective = &mission->objective[objective_num];
1819
1820 /* Clear and then set default objective structure values */
1821 memset(objective, 0x00, sizeof(sar_mission_objective_struct));
1822 objective->type = p_mission_new_objective->objective_type;
1823 objective->state = SAR_MISSION_OBJECTIVE_STATE_INCOMPLETE;
1824 objective->time_left = 0.0f;
1825 objective->humans_need_rescue = 0;
1826 objective->total_humans = 0;
1827 objective->arrive_at_name = NULL;
1828 objective->message_success = NULL;
1829 objective->message_fail = NULL;
1830
1831 if(opt->runtime_debug)
1832 printf(
1833 "SARMissionLoadFromFile(): Creating new mission objective of type %i.\n",
1834 p_mission_new_objective->objective_type
1835 );
1836 }
1837 break;
1838
1839 case SAR_PARM_MISSION_TIME_LEFT:
1840 p_mission_time_left = (sar_parm_mission_time_left_struct *)p;
1841 if(objective != NULL)
1842 {
1843 objective->time_left = p_mission_time_left->time_left;
1844 }
1845 break;
1846
1847 case SAR_PARM_MISSION_BEGIN_AT:
1848 p_mission_begin_at = (sar_parm_mission_begin_at_struct *)p;
1849 if(p_mission_begin_at->name != NULL)
1850 {
1851 sar_object_struct *begin_obj_ptr;
1852
1853 /* Update mission begin at name */
1854 free(begin_at_name);
1855 begin_at_name = STRDUP(p_mission_begin_at->name);
1856
1857 free(mission->start_location_name);
1858 mission->start_location_name = STRDUP(p_mission_begin_at->name);
1859
1860 if(!begin_at_set)
1861 {
1862 /* Match the object with the name specified by
1863 * begin_at_name.
1864 */
1865 begin_obj_ptr = SARObjMatchPointerByName(
1866 scene, *ptr, *total,
1867 begin_at_name, NULL
1868 );
1869 /* Got match? */
1870 if(begin_obj_ptr != NULL)
1871 {
1872 /* Record begin at position and direction */
1873 memcpy(
1874 &begin_pos, &begin_obj_ptr->pos,
1875 sizeof(sar_position_struct)
1876 );
1877 /* TODO Need to work on getting begin_dir based on location of matched
1878 * begin_at_name object
1879 */
1880 memcpy(
1881 &begin_dir, &begin_obj_ptr->dir,
1882 sizeof(sar_direction_struct)
1883 );
1884 }
1885 else
1886 {
1887 fprintf(
1888 stderr,
1889 "%s: Warning: \"mission_begin_at\" object name \"%s\" not found.\n",
1890 filename, begin_at_name
1891 );
1892 }
1893
1894 begin_at_set = True;
1895 }
1896 }
1897 break;
1898
1899 case SAR_PARM_MISSION_BEGIN_AT_POS:
1900 p_mission_begin_at_pos = (sar_parm_mission_begin_at_pos_struct *)p;
1901 if(!begin_at_set)
1902 {
1903 /* Record begin at position and direction */
1904 memcpy(
1905 &begin_pos, &p_mission_begin_at_pos->pos,
1906 sizeof(sar_position_struct)
1907 );
1908 memcpy(
1909 &begin_dir, &p_mission_begin_at_pos->dir,
1910 sizeof(sar_direction_struct)
1911 );
1912 begin_at_set = True;
1913 }
1914 break;
1915
1916 case SAR_PARM_MISSION_ARRIVE_AT:
1917 p_mission_arrive_at = (sar_parm_mission_arrive_at_struct *)p;
1918 if(p_mission_arrive_at->name != NULL)
1919 {
1920 sar_object_struct *arrive_obj_ptr;
1921
1922 /* Update arrive_at_name context */
1923 free(arrive_at_name);
1924 arrive_at_name = STRDUP(p_mission_arrive_at->name);
1925
1926 /* Update arrive_at_name on current objective (if any) */
1927 if(objective != NULL)
1928 {
1929 free(objective->arrive_at_name);
1930 objective->arrive_at_name = STRDUP(p_mission_arrive_at->name);
1931 }
1932
1933 /* Match arrive at object (just to verify) */
1934 arrive_obj_ptr = SARObjMatchPointerByName(
1935 scene, *ptr, *total,
1936 arrive_at_name, NULL
1937 );
1938 if(arrive_obj_ptr == NULL)
1939 {
1940 fprintf(
1941 stderr,
1942 "%s: Warning: \"mission_arrive_at\" object name \"%s\" not found.\n",
1943 filename, arrive_at_name
1944 );
1945 }
1946 }
1947 break;
1948
1949 case SAR_PARM_MISSION_MESSAGE_SUCCESS:
1950 p_mission_message_success = (sar_parm_mission_message_success_struct *)p;
1951 if(p_mission_message_success->message != NULL)
1952 {
1953 /* Update message_success on current objective (if any) */
1954 if(objective != NULL)
1955 {
1956 free(objective->message_success);
1957 objective->message_success = STRDUP(p_mission_message_success->message);
1958 }
1959 }
1960 break;
1961
1962 case SAR_PARM_MISSION_MESSAGE_FAIL:
1963 p_mission_message_fail = (sar_parm_mission_message_fail_struct *)p;
1964 if(p_mission_message_fail->message != NULL)
1965 {
1966 /* Update message_fail on current objective (if any) */
1967 if(objective != NULL)
1968 {
1969 free(objective->message_fail);
1970 objective->message_fail = STRDUP(p_mission_message_fail->message);
1971 }
1972 }
1973 break;
1974
1975 case SAR_PARM_MISSION_HUMANS_TALLY:
1976 p_mission_humans_tally = (sar_parm_mission_humans_tally_struct *)p;
1977 if(objective != NULL)
1978 {
1979 objective->humans_need_rescue =
1980 p_mission_humans_tally->humans_need_rescue;
1981 objective->total_humans =
1982 p_mission_humans_tally->total_humans;
1983
1984 /* Initial value humans_need_rescue cannot be
1985 * greater than total_humans.
1986 */
1987 if(objective->humans_need_rescue > objective->total_humans)
1988 objective->humans_need_rescue = objective->total_humans;
1989 }
1990 break;
1991
1992 case SAR_PARM_MISSION_ADD_INTERCEPT:
1993 p_mission_add_intercept = (sar_parm_mission_add_intercept_struct *)p;
1994 if(obj_ptr != NULL)
1995 {
1996 sar_intercept_struct intercept;
1997 sar_object_struct *tar_obj_ptr;
1998
1999
2000 /* Reset intercept structure */
2001 memset(&intercept, 0x00, sizeof(sar_intercept_struct));
2002
2003 /* Handle by intercept reference code */
2004 switch(p_mission_add_intercept->ref_code)
2005 {
2006 case 3: /* Intercept arrive at location */
2007 tar_obj_ptr = SARObjMatchPointerByName(
2008 scene,
2009 *ptr, *total,
2010 arrive_at_name, NULL
2011 );
2012 if(tar_obj_ptr != NULL)
2013 {
2014 intercept.x = tar_obj_ptr->pos.x;
2015 intercept.y = tar_obj_ptr->pos.y;
2016 intercept.z = tar_obj_ptr->pos.z;
2017 intercept.radius = p_mission_add_intercept->radius;
2018 intercept.urgency = p_mission_add_intercept->urgency;
2019 }
2020 break;
2021
2022 case 2: /* Intercept begin at location */
2023 tar_obj_ptr = SARObjMatchPointerByName(
2024 scene,
2025 *ptr, *total,
2026 begin_at_name, NULL
2027 );
2028 if(tar_obj_ptr != NULL)
2029 {
2030 intercept.x = tar_obj_ptr->pos.x;
2031 intercept.y = tar_obj_ptr->pos.y;
2032 intercept.z = tar_obj_ptr->pos.z;
2033 intercept.radius = p_mission_add_intercept->radius;
2034 intercept.urgency = p_mission_add_intercept->urgency;
2035 }
2036 break;
2037
2038 default: /* Standard intercept */
2039 intercept.x = p_mission_add_intercept->pos.x;
2040 intercept.y = p_mission_add_intercept->pos.y;
2041 intercept.z = p_mission_add_intercept->pos.z;
2042 intercept.radius = p_mission_add_intercept->radius;
2043 intercept.urgency = p_mission_add_intercept->urgency;
2044 break;
2045 }
2046
2047 /* Allocate new intercept structure on object */
2048 if(obj_aircraft_ptr != NULL)
2049 {
2050 SARObjInterceptNew(
2051 scene,
2052 &obj_aircraft_ptr->intercept,
2053 &obj_aircraft_ptr->total_intercepts,
2054 intercept.flags,
2055 intercept.x, intercept.y, intercept.z,
2056 intercept.radius, intercept.urgency,
2057 intercept.name
2058 );
2059 }
2060 }
2061 break;
2062
2063 case SAR_PARM_NEW_OBJECT:
2064 p_new_object = (sar_parm_new_object_struct *)p;
2065 /* Create new object of the specified type */
2066 obj_num = SARObjNew(
2067 scene, ptr, total,
2068 p_new_object->object_type
2069 );
2070 /* Update object context pointers */
2071 obj_ptr = (obj_num > -1) ? (*ptr)[obj_num] : NULL;
2072 CONTEXT_REGET_SUBSTRUCTURE_PTRS(obj_ptr)
2073 break;
2074
2075 case SAR_PARM_NEW_HELIPAD:
2076 p_new_helipad = (sar_parm_new_helipad_struct *)p;
2077 /* Create new helipad */
2078 obj_num = SARObjLoadHelipad(
2079 core_ptr, scene, p_new_helipad
2080 );
2081 /* Update object context pointers */
2082 obj_ptr = (obj_num > -1) ? (*ptr)[obj_num] : NULL;
2083 CONTEXT_REGET_SUBSTRUCTURE_PTRS(obj_ptr)
2084 break;
2085
2086 case SAR_PARM_NEW_RUNWAY:
2087 p_new_runway = (sar_parm_new_runway_struct *)p;
2088 /* Create new runway */
2089 obj_num = SARObjLoadRunway(
2090 core_ptr, scene, p_new_runway
2091 );
2092 /* Update object context pointers */
2093 obj_ptr = (obj_num > -1) ? (*ptr)[obj_num] : NULL;
2094 CONTEXT_REGET_SUBSTRUCTURE_PTRS(obj_ptr)
2095 break;
2096
2097 case SAR_PARM_NEW_HUMAN:
2098 p_new_human = (sar_parm_new_human_struct *)p;
2099 /* Create new human */
2100 obj_num = SARObjLoadHuman(
2101 core_ptr, scene, p_new_human
2102 );
2103 /* Update object context pointers */
2104 obj_ptr = (obj_num > -1) ? (*ptr)[obj_num] : NULL;
2105 CONTEXT_REGET_SUBSTRUCTURE_PTRS(obj_ptr)
2106 if((obj_ptr != NULL) && (obj_human_ptr != NULL))
2107 {
2108 /* Increment number of humans that need rescue that
2109 * this mission file has specified.
2110 */
2111 if(obj_human_ptr->flags & SAR_HUMAN_FLAG_NEED_RESCUE)
2112 humans_need_rescue++;
2113 }
2114 break;
2115
2116 case SAR_PARM_NEW_FIRE:
2117 p_new_fire = (sar_parm_new_fire_struct *)p;
2118 /* Create new fire object */
2119 obj_num = SARObjLoadFire(
2120 core_ptr, scene, p_new_fire
2121 );
2122 /* Update object context pointers */
2123 obj_ptr = (obj_num > -1) ? (*ptr)[obj_num] : NULL;
2124 CONTEXT_REGET_SUBSTRUCTURE_PTRS(obj_ptr)
2125 break;
2126
2127 case SAR_PARM_NEW_SMOKE:
2128 p_new_smoke = (sar_parm_new_smoke_struct *)p;
2129 /* Create new smoke trails object */
2130 obj_num = SARObjLoadSmoke(
2131 core_ptr, scene, p_new_smoke
2132 );
2133 /* Update object context pointers */
2134 obj_ptr = (obj_num > -1) ? (*ptr)[obj_num] : NULL;
2135 CONTEXT_REGET_SUBSTRUCTURE_PTRS(obj_ptr)
2136 break;
2137
2138 case SAR_PARM_NEW_PREMODELED:
2139 p_new_premodeled = (sar_parm_new_premodeled_struct *)p;
2140 /* Create new premodeled object */
2141 obj_num = SARObjPremodeledNew(
2142 core_ptr, scene,
2143 p_new_premodeled->model_type,
2144 p_new_premodeled->argc,
2145 p_new_premodeled->argv
2146 );
2147 /* Reget object context pointers */
2148 obj_ptr = (obj_num > -1) ? (*ptr)[obj_num] : NULL;
2149 CONTEXT_REGET_SUBSTRUCTURE_PTRS(obj_ptr)
2150 break;
2151
2152 case SAR_PARM_MODEL_FILE:
2153 p_model_file = (sar_parm_model_file_struct *)p;
2154 if((p_model_file->file != NULL) && (obj_ptr != NULL))
2155 SARObjLoadFromFile(core_ptr, obj_num, p_model_file->file);
2156 break;
2157
2158 #if 0
2159 case SAR_PARM_SELECT_OBJECT_BY_NAME:
2160 p_select_object_by_name = (sar_parm_select_object_by_name_struct *)p;
2161 if(p_select_object_by_name->name != NULL)
2162 {
2163 obj_ptr = SARObjMatchPointerByName(
2164 scene,
2165 core_ptr->object, core_ptr->total_objects,
2166 p_select_object_by_name->name, &obj_num
2167 );
2168 }
2169 break;
2170 #endif
2171 case SAR_PARM_TRANSLATE:
2172 p_translate = (sar_parm_translate_struct *)p;
2173 SARObjLoadTranslate(
2174 core_ptr, scene,
2175 obj_ptr, p_translate
2176 );
2177 break;
2178
2179 case SAR_PARM_TRANSLATE_RANDOM:
2180 p_translate_random = (sar_parm_translate_random_struct *)p;
2181 SARObjLoadTranslateRandom(
2182 core_ptr, scene,
2183 obj_ptr, p_translate_random
2184 );
2185 break;
2186
2187 case SAR_PARM_ROTATE:
2188 p_rotate = (sar_parm_rotate_struct *)p;
2189 if(obj_ptr != NULL)
2190 SARSimWarpObject(
2191 scene, obj_ptr,
2192 NULL, &p_rotate->rotate
2193 );
2194 break;
2195
2196 case SAR_PARM_NO_DEPTH_TEST:
2197 p_no_depth_test = (sar_parm_no_depth_test_struct *)p;
2198 if(obj_ptr != NULL)
2199 {
2200 obj_ptr->flags |= SAR_OBJ_FLAG_NO_DEPTH_TEST;
2201 }
2202 break;
2203
2204 case SAR_PARM_POLYGON_OFFSET:
2205 p_polygon_offset = (sar_parm_polygon_offset_struct *)p;
2206 if(obj_ptr != NULL)
2207 {
2208 obj_ptr->flags |= p_polygon_offset->flags;
2209 }
2210 break;
2211
2212 case SAR_PARM_OBJECT_NAME:
2213 p_object_name = (sar_parm_object_name_struct *)p;
2214 if(obj_ptr != NULL)
2215 {
2216 free(obj_ptr->name);
2217 obj_ptr->name = STRDUP(p_object_name->name);
2218 }
2219 break;
2220
2221 case SAR_PARM_RUNWAY_APPROACH_LIGHTING_NORTH:
2222 p_runway_applight_n =
2223 (sar_parm_runway_approach_lighting_north_struct *)p;
2224 if((obj_ptr != NULL) && (obj_runway_ptr != NULL))
2225 {
2226 obj_runway_ptr->north_approach_lighting_flags =
2227 p_runway_applight_n->flags;
2228 }
2229 break;
2230
2231 case SAR_PARM_RUNWAY_APPROACH_LIGHTING_SOUTH:
2232 p_runway_applight_s =
2233 (sar_parm_runway_approach_lighting_south_struct *)p;
2234 if((obj_ptr != NULL) && (obj_runway_ptr != NULL))
2235 {
2236 obj_runway_ptr->south_approach_lighting_flags =
2237 p_runway_applight_s->flags;
2238 }
2239 break;
2240
2241 case SAR_PARM_HUMAN_MESSAGE_ENTER:
2242 p_human_message_enter = (sar_parm_human_message_enter_struct *)p;
2243 if((obj_ptr != NULL) && (obj_human_ptr != NULL))
2244 {
2245 free(obj_human_ptr->mesg_enter);
2246 obj_human_ptr->mesg_enter = STRDUP(
2247 p_human_message_enter->message
2248 );
2249 }
2250 break;
2251
2252 case SAR_PARM_HUMAN_REFERENCE:
2253 p_human_reference = (sar_parm_human_reference_struct *)p;
2254 if((obj_ptr != NULL) && (obj_human_ptr != NULL) &&
2255 (p_human_reference->reference_name != NULL)
2256 )
2257 {
2258 int human_ref_obj_num = -1;
2259 const char *ref_name = p_human_reference->reference_name;
2260
2261 /* Run towards? */
2262 if(p_human_reference->flags & SAR_HUMAN_FLAG_RUN_TOWARDS)
2263 {
2264 obj_human_ptr->flags |= SAR_HUMAN_FLAG_RUN_TOWARDS;
2265 }
2266 /* Run away? */
2267 else if(p_human_reference->flags & SAR_HUMAN_FLAG_RUN_AWAY)
2268 {
2269 obj_human_ptr->flags |= SAR_HUMAN_FLAG_RUN_AWAY;
2270 }
2271
2272 /* Handle reference object name */
2273 if(!strcasecmp(ref_name, "player"))
2274 {
2275 /* Set special intercept code to intercept the player */
2276 obj_human_ptr->intercepting_object = -2;
2277 }
2278 else
2279 {
2280 /* All else match by object name */
2281 SARObjMatchPointerByName(
2282 scene, *ptr, *total,
2283 ref_name, &human_ref_obj_num
2284 );
2285 obj_human_ptr->intercepting_object = human_ref_obj_num;
2286 }
2287 }
2288 break;
2289
2290 default:
2291 break;
2292
2293 } /* Handle by parm type */
2294
2295
2296 /* If we lost the mission structure then we need to
2297 * give up, there was probably some fatal error
2298 * encountered above
2299 */
2300 if(mission == NULL)
2301 break;
2302
2303 } /* Iterate through loaded parms */
2304
2305
2306 /* Delete loaded parms */
2307 SARParmDeleteAll(&parm, &total_parms);
2308
2309 if(opt->runtime_debug)
2310 printf(
2311 "SARMissionLoadFromFile():\
2312 Loaded new mission with %i objectives.\n",
2313 mission->total_objectives
2314 );
2315
2316 free(begin_at_name);
2317 free(arrive_at_name);
2318 free(weather_preset_name);
2319
2320 #undef CONTEXT_REGET_SUBSTRUCTURE_PTRS
2321
2322 return(mission);
2323 }
2324
2325 /*
2326 * Resets the mission log file specified by filename and rewrites
2327 * its header with the information given by the mission structure.
2328 *
2329 * This will overwrite the previous log file (if any) specified
2330 * by filename.
2331 */
SARMissionLogReset(sar_core_struct * core_ptr,sar_mission_struct * mission,const char * filename)2332 void SARMissionLogReset(
2333 sar_core_struct *core_ptr, sar_mission_struct *mission,
2334 const char *filename /* Mission log file name */
2335 )
2336 {
2337 void *p, **parm = NULL;
2338 int total_parms = 0;
2339
2340 if((mission == NULL) || STRISEMPTY(filename))
2341 return;
2342
2343 /* Begin generating parameters for writing mission log */
2344 p = SARParmNewAppend(
2345 SAR_PARM_MISSION_LOG_HEADER,
2346 &parm, &total_parms
2347 );
2348 if(p != NULL)
2349 {
2350 sar_parm_mission_log_header_struct *pv =
2351 (sar_parm_mission_log_header_struct *)p;
2352 pv->version_major = PROG_VERSION_MAJOR;
2353 pv->version_minor = PROG_VERSION_MINOR;
2354 pv->version_release = PROG_VERSION_RELEASE;
2355 free(pv->title);
2356 pv->title = STRDUP(mission->title);
2357 free(pv->scene_file);
2358 pv->scene_file = STRDUP(mission->scene_file);
2359 free(pv->player_stats_file);
2360 pv->player_stats_file = STRDUP(mission->player_stats_file);
2361 }
2362
2363 /* Write mission log file, this will overwrite the existing
2364 * mission log file (if any).
2365 */
2366 SARParmSaveToFile(
2367 filename, SAR_FILE_FORMAT_MISSION_LOG,
2368 parm, total_parms,
2369 NULL, NULL
2370 );
2371
2372 /* Delete loaded parms */
2373 SARParmDeleteAll(&parm, &total_parms);
2374 }
2375
2376 /*
2377 * Appends a log entry to the given log file, the log file will be
2378 * opened for writing (append) and then closed during this call.
2379 *
2380 * The event_type must be given and cannot be -1.
2381 *
2382 * The tod (time of day) can be either a valid time or -1.0 to indicate
2383 * use current time on core's scene structure.
2384 *
2385 * The given file name must reffer to valid file which is writeable.
2386 *
2387 * All other inputs are optional.
2388 */
SARMissionLogEvent(sar_core_struct * core_ptr,sar_mission_struct * mission,int event_type,float tod,sar_position_struct * pos,const float * value,int total_values,const char * message,const char * filename)2389 void SARMissionLogEvent(
2390 sar_core_struct *core_ptr, sar_mission_struct *mission,
2391 int event_type, /* One of SAR_LOG_EVENT_* */
2392 float tod, /* Time of day in seconds since midnight */
2393 sar_position_struct *pos, /* Position of event */
2394 const float *value, /* Additional values */
2395 int total_values, /* Total number of additional values */
2396 const char *message, /* The message */
2397 const char *filename /* Mission log file name */
2398 )
2399 {
2400 int i;
2401 FILE *fp;
2402 sar_scene_struct *scene = core_ptr->scene;
2403 if((scene == NULL) || (mission == NULL) ||
2404 STRISEMPTY(filename)
2405 )
2406 return;
2407
2408 /* Open mission log file for append writing */
2409 fp = FOpen(filename, "ab");
2410 if(fp == NULL)
2411 return;
2412
2413 /* Write event type, time and coordinates */
2414 fprintf(
2415 fp,
2416 "%i %f %f %f %f%s",
2417 event_type,
2418 (tod < 0.0f) ? scene->tod : tod,
2419 (pos != NULL) ? pos->x : 0.0f,
2420 (pos != NULL) ? pos->y : 0.0f,
2421 (pos != NULL) ? pos->z : 0.0f,
2422 (total_values > 0) ? " " : ""
2423 );
2424
2425 /* Write any additional arguments */
2426 for(i = 0; i < total_values; i++)
2427 fprintf(
2428 fp,
2429 "%f%s",
2430 value[i],
2431 (i < (total_values - 1)) ? " " : ""
2432 );
2433
2434 /* Write values and message deliminator character */
2435 fputc(':', fp);
2436
2437 /* Write message? */
2438 if(message != NULL)
2439 fputs(message, fp);
2440
2441 /* End this log event line with a newline character */
2442 fputc('\n', fp);
2443
2444 /* Close mission log file */
2445 FClose(fp);
2446 }
2447