1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 
6 #include "../include/string.h"
7 
8 #include "obj.h"
9 #include "objutils.h"
10 #include "messages.h"
11 #include "mission.h"
12 #include "missionio.h"
13 #include "simutils.h"
14 #include "sar.h"
15 #include "config.h"
16 
17 
18 #ifdef __MSW__
19 static double rint(double x);
20 #endif	/* __MSW__ */
21 static sar_mission_objective_struct *SARMissionObjectiveGetCurrentPtr(
22 	sar_mission_struct *mission
23 );
24 static int SARMissionGetObjectPassengers(
25 	sar_core_struct *core_ptr, sar_object_struct *obj_ptr
26 );
27 static Boolean SARMissionGroundContactMatchName(
28 	sar_core_struct *core_ptr, sar_scene_struct *scene,
29 	sar_object_struct **ptr, int total,
30 	const int *ground_contact, int total_ground_contacts,
31 	const char *name
32 );
33 
34 sar_mission_struct *SARMissionNew(void);
35 void SARMissionDelete(sar_mission_struct *mission);
36 
37 void SARMissionPrintStats(
38 	sar_core_struct *core_ptr,
39 	sar_scene_struct *scene,
40 	sar_mission_struct *mission,
41 	sar_object_struct *obj_ptr
42 );
43 
44 static int SARMissionDoObjectiveSuccess(
45 	sar_mission_struct *mission, sar_scene_struct *scene
46 );
47 static int SARMissionDoObjectiveFailed(
48 	sar_mission_struct *mission, sar_scene_struct *scene
49 );
50 
51 void SARMissionDestroyNotify(
52 	sar_core_struct *core_ptr, sar_object_struct *obj_ptr
53 );
54 void SARMissionHoistInNotify(
55 	sar_core_struct *core_ptr, sar_object_struct *obj_ptr,
56 	int hoisted_in		/* Number of humans hoisted in */
57 );
58 void SARMissionPassengersEnterNotify(
59 	sar_core_struct *core_ptr, sar_object_struct *obj_ptr,
60 	int passengers_entered  /* Number of passengers entered */
61 );
62 void SARMissionPassengersLeaveNotify(
63 	sar_core_struct *core_ptr, sar_object_struct *obj_ptr,
64 	int passengers_left	/* Number of passengers that left */
65 );
66 void SARMissionLandNotify(
67 	sar_core_struct *core_ptr, sar_object_struct *obj_ptr,
68 	const int *ground_contact, int total_ground_contacts
69 );
70 
71 static void SARMissionObjectiveManage(
72 	sar_core_struct *core_ptr, sar_mission_struct *mission,
73 	sar_mission_objective_struct *objective
74 );
75 int SARMissionManage(sar_core_struct *core_ptr);
76 
77 
78 #define ATOI(s)         (((s) != NULL) ? atoi(s) : 0)
79 #define ATOL(s)         (((s) != NULL) ? atol(s) : 0)
80 #define ATOF(s)         (((s) != NULL) ? atof(s) : 0.0f)
81 #define STRDUP(s)       (((s) != NULL) ? strdup(s) : NULL)
82 
83 #define MAX(a,b)        (((a) > (b)) ? (a) : (b))
84 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
85 #define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))
86 #define STRLEN(s)	(((s) != NULL) ? ((int)strlen(s)) : 0)
87 
88 #define ISCOMMENT(c)    ((c) == SAR_COMMENT_CHAR)
89 #define ISCR(c)         (((c) == '\n') || ((c) == '\r'))
90 
91 
92 /*
93  *	Interval between mission end check and leaving simulation to
94  *	go back to the menus (in milliseconds):
95  */
96 #define DEF_MISSION_END_INT	5000
97 
98 
99 
100 #ifdef __MSW__
rint(double x)101 static double rint(double x)
102 {
103 	if((double)((double)x - (int)x) > (double)0.5)
104 	    return((double)((int)x + (int)1));
105 	else
106 	    return((double)((int)x));
107 }
108 #endif	/* __MSW__ */
109 
110 
111 /*
112  *	Returns the pointer to the current mission objective structure on
113  *	the given mission structure. Can return NULL on error.
114  */
SARMissionObjectiveGetCurrentPtr(sar_mission_struct * mission)115 static sar_mission_objective_struct *SARMissionObjectiveGetCurrentPtr(
116 	sar_mission_struct *mission
117 )
118 {
119 	int i;
120 
121 	if(mission == NULL)
122 	    return(NULL);
123 
124 	i = mission->cur_objective;
125 	if((i < 0) || (i >= mission->total_objectives))
126 	    return(NULL);
127 	else
128 	    return(&mission->objective[i]);
129 }
130 
131 /*
132  *	Returns the number of passengers on the object, depending on the
133  *	object type it may not have any objects. Does not include crew
134  *	or any fixed on-board `individuals'.
135  *
136  *	For any object that has a hoist and rescue basket, any passengers
137  *	in the rescue basket are NOT counted.
138  *
139  *	The object is assumed valid.
140  */
SARMissionGetObjectPassengers(sar_core_struct * core_ptr,sar_object_struct * obj_ptr)141 static int SARMissionGetObjectPassengers(
142 	sar_core_struct *core_ptr, sar_object_struct *obj_ptr
143 )
144 {
145 	int *passengers;
146 
147 	if(obj_ptr == NULL)
148 	    return(0);
149 
150 	if(SARObjGetOnBoardPtr(
151 	    obj_ptr,
152 	    NULL, &passengers, NULL,
153 	    NULL,
154 	    NULL, NULL
155 	))
156 	    return(0);
157 
158 	if(passengers != NULL)
159 	     return(MAX(*passengers, 0));
160 	else
161 	    return(0);
162 }
163 
164 /*
165  *	Checks for all objects in the given objects list who's name
166  *	matches the given name and who's index is found on the given
167  *	ground_contact list.
168  *
169  *	Any special object numbers in the given ground_contact list will
170  *	be ignored.
171  *
172  *	Returns True on match or False on no match or error.
173  */
SARMissionGroundContactMatchName(sar_core_struct * core_ptr,sar_scene_struct * scene,sar_object_struct ** ptr,int total,const int * ground_contact,int total_ground_contacts,const char * name)174 static Boolean SARMissionGroundContactMatchName(
175 	sar_core_struct *core_ptr, sar_scene_struct *scene,
176 	sar_object_struct **ptr, int total,
177 	const int *ground_contact, int total_ground_contacts,
178 	const char *name
179 )
180 {
181 	int i, obj_num;
182 	sar_object_struct *obj_ptr;
183 
184 
185 	if((name == NULL) || (ground_contact == NULL) || (ptr == NULL))
186 	    return(False);
187 
188 	/* Check if landed at right place, iterate through list of
189 	 * ground contact objects for matching name
190 	 */
191 	for(i = 0; i < total_ground_contacts; i++)
192 	{
193 	    obj_num = ground_contact[i];
194 	    obj_ptr = SARObjGetPtr(ptr, total, obj_num);
195 	    if((obj_ptr == NULL) ? 1 : (obj_ptr->name == NULL))
196 		continue;
197 
198 	    /* Names match? */
199 	    if(!strcasecmp(obj_ptr->name, name))
200 		break;
201 	}
202 	/* No match? */
203 	if(i >= total_ground_contacts)
204 	    return(False);
205 	else
206 	    return(True);
207 }
208 
209 
210 /*
211  *	Allocates a new mission structure with all its members
212  *	reset.
213  */
SARMissionNew(void)214 sar_mission_struct *SARMissionNew(void)
215 {
216 	return(
217 	    (sar_mission_struct *)calloc(1, sizeof(sar_mission_struct))
218 	);
219 }
220 
221 /*
222  *	Deletes the given mission structure and all its substructures,
223  *      including the mission structure itself.
224  */
SARMissionDelete(sar_mission_struct * mission)225 void SARMissionDelete(sar_mission_struct *mission)
226 {
227 	if(mission == NULL)
228 	    return;
229 
230 	/* Need to delete objective(s)? */
231 	if(mission->objective != NULL)
232 	{
233 	    int i;
234 	    sar_mission_objective_struct *objective;
235 
236 	    /* Iterate through each objective and delete its members */
237 	    for(i = mission->total_objectives - 1; i >= 0; i--)
238 	    {
239 		objective = &mission->objective[i];
240 
241 		free(objective->arrive_at_name);
242 		free(objective->message_success);
243 		free(objective->message_fail);
244 	    }
245 
246 	    /* Delete all objectives */
247 	    free(mission->objective);
248 	    mission->objective = NULL;
249 	    mission->total_objectives = 0;
250 	}
251 
252 	/* Delete the rest of the mission structure */
253 	free(mission->title);
254 	free(mission->description);
255 
256 	free(mission->start_location_name);
257 
258 	free(mission->scene_file);
259 	free(mission->player_model_file);
260 	free(mission->player_stats_file);
261 
262 	free(mission->objective);
263 
264 	free(mission);
265 }
266 
267 
268 /*
269  *	Prints mission stats to the scene's message output with respect
270  *	to the given object and mission structures.
271  */
SARMissionPrintStats(sar_core_struct * core_ptr,sar_scene_struct * scene,sar_mission_struct * mission,sar_object_struct * obj_ptr)272 void SARMissionPrintStats(
273 	sar_core_struct *core_ptr, sar_scene_struct *scene,
274 	sar_mission_struct *mission,
275 	sar_object_struct *obj_ptr
276 )
277 {
278 	int	*passengers = NULL,
279 		*passengers_max = NULL;
280 	char text[1024];
281 
282 
283 	/* First print object statistics if object is valid */
284 	SARObjGetOnBoardPtr(
285 	    obj_ptr,
286 	    NULL, &passengers, &passengers_max,
287 	    NULL,
288 	    NULL, NULL
289 	);
290 
291 	/* Format passengers on board string */
292 	sprintf(
293 	    text,
294 	    "%s: %i(%i)",
295 	    SAR_MESG_PASSENGERS,
296 	    (passengers != NULL) ? *passengers : 0,
297 	    (passengers_max != NULL) ? *passengers_max : 0
298 	);
299 	SARMessageAdd(scene, text);
300 
301 	/* Valid mission structure given? */
302 	if(mission != NULL)
303 	{
304 	    sar_mission_objective_struct *objective = SARMissionObjectiveGetCurrentPtr(mission);
305 
306 	    /* Is there a current mission objective? */
307 	    if(objective != NULL)
308 	    {
309 #define tmp_name_len    80
310 		char tmp_name[tmp_name_len];
311 
312 		/* Handle by mission objective type */
313 		switch(objective->type)
314 		{
315 		  case SAR_MISSION_OBJECTIVE_ARRIVE_AT:
316 		    strncpy(
317 			tmp_name,
318 			(objective->arrive_at_name != NULL) ?
319 			    objective->arrive_at_name : "(null)",
320 			tmp_name_len
321 		    );
322 		    tmp_name[tmp_name_len - 1] = '\0';
323 
324 		    /* Print arrive mission status */
325 		    sprintf(
326 			text,
327 			"%s %s",
328 			SAR_MESG_MISSION_IN_PROGRESS_ENROUTE, tmp_name
329 		    );
330 		    SARMessageAdd(scene, text);
331 
332 		    /* Is there a time limit? */
333 		    if(objective->time_left > 0.0)
334 		    {
335 			sprintf(text,
336 			    "%s %s",
337 			    SAR_MESG_TIME_LEFT,
338 			    SARDeltaTimeString(
339 				core_ptr,
340 				(time_t)objective->time_left
341 			    )
342 			);
343 			SARMessageAdd(scene, text);
344 		    }
345 		    break;
346 
347 		  case SAR_MISSION_OBJECTIVE_PICK_UP:
348 		  case SAR_MISSION_OBJECTIVE_PICK_UP_ARRIVE_AT:
349 		    /* Print how many more we need to find */
350 		    if(objective->humans_need_rescue > 0)
351 			sprintf(
352 			    text,
353 			    "%s, %i %s",
354 			    SAR_MESG_MISSION_RESCUE_IN_PROGRESS,
355 			    objective->humans_need_rescue,
356 			    SAR_MESG_MISSION_MORE_TO_FIND
357 			);
358 		    else
359 			sprintf(
360 			    text,
361 			    "%s, %s",
362 			    SAR_MESG_MISSION_RESCUE_IN_PROGRESS,
363 			    SAR_MESG_MISSION_ALL_FOUND
364 			);
365 		    SARMessageAdd(scene, text);
366 
367 		    /* Is there a time limit? */
368 		    if(objective->time_left > 0.0)
369 		    {
370 			/* Need to check objective type again */
371 			switch(objective->type)
372 			{
373 			  /* Pick up all and get them to safety */
374 			  case SAR_MISSION_OBJECTIVE_PICK_UP_ARRIVE_AT:
375 			    sprintf(
376 				text,
377 				"%s %s %s",
378 				SAR_MESG_TIME_LEFT,
379 				SARDeltaTimeString(
380 				    core_ptr,
381 				    (time_t)objective->time_left
382 				),
383 				SAR_MESG_MISSION_TO_GET_ALL_TO_SAFETY
384 			    );
385 			    SARMessageAdd(scene, text);
386 			    break;
387 
388 			  /* Just pick up all */
389 			  case SAR_MISSION_OBJECTIVE_PICK_UP:
390 			    sprintf(
391 				text,
392 				"%s %s %s",
393 				SAR_MESG_TIME_LEFT,
394 				SARDeltaTimeString(
395 				    core_ptr,
396 				    (time_t)objective->time_left
397 				),
398 				SAR_MESG_MISSION_TO_PICK_UP_ALL
399 			    );
400 			    SARMessageAdd(scene, text);
401 			    break;
402 			}
403 		    }
404 		    break;
405 		}
406 
407 #undef tmp_name_len
408 	    }	/* Is there a current mission objective? */
409 	    else
410 	    {
411 		/* No current mission objective, implying mission is
412 		 * completed or failed. Check master mission state.
413 		 */
414 		switch(mission->state)
415 		{
416 		  case MISSION_STATE_IN_PROGRESS:
417 		    /* Still in progress but no current objectives? Must be
418 		     * a delay in the updates (hopefully), print a standby
419 		     * message.
420 		     */
421 		    SARMessageAdd(scene, SAR_MESG_MISSION_STANDBY);
422 		    break;
423 
424 		  case MISSION_STATE_FAILED:
425 		    /* Print generic mission objectives failed message */
426 		    SARMessageAdd(scene, SAR_MESG_MISSION_FAILED);
427 		    break;
428 
429 		  case MISSION_STATE_ACCOMPLISHED:
430 		    /* Print generic mission accomplished message */
431 		    SARMessageAdd(scene, SAR_MESG_MISSION_RESCUE_COMPLETE);
432 		    break;
433 		}
434 	    }
435 	}	/* Valid mission structure given? */
436 }
437 
438 
439 /*
440  *	Procedure to mark current objective on the given mission structure
441  *	as success and go on to the next objective. If there are no more
442  *	objectives then the entire mission has been accomplished.
443  *
444  *	Returns:
445  *
446  *	-1	General error
447  *	0	Went on to next objective
448  *	1	All objectives completed, mission accomplished
449  */
SARMissionDoObjectiveSuccess(sar_mission_struct * mission,sar_scene_struct * scene)450 static int SARMissionDoObjectiveSuccess(
451 	sar_mission_struct *mission, sar_scene_struct *scene
452 )
453 {
454 	int player_obj_num;
455 	sar_object_struct *player_obj_ptr;
456 	sar_mission_objective_struct *objective;
457 
458 	if((mission == NULL) || (scene == NULL))
459 	    return(-1);
460 
461 	/* Get player object references from scene structure */
462 	player_obj_num = scene->player_obj_num;
463 	player_obj_ptr = scene->player_obj_ptr;
464 
465 	/* Get current mission objective */
466 	objective = SARMissionObjectiveGetCurrentPtr(mission);
467 	if(objective != NULL)
468 	{
469 	    sar_object_aircraft_struct *obj_aircraft_ptr;
470 	    const char *mesg_ptr = objective->message_success;
471 
472 	    /* Mark current objective as success */
473 	    objective->state = SAR_MISSION_OBJECTIVE_STATE_SUCCESS;
474 
475 	    /* Print success message? */
476 	    if(mesg_ptr != NULL)
477 		SARMessageAdd(scene, mesg_ptr);
478 
479 	    /* Update way point on player object */
480 	    obj_aircraft_ptr = SAR_OBJ_GET_AIRCRAFT(player_obj_ptr);
481 	    if(obj_aircraft_ptr != NULL)
482 	    {
483 		obj_aircraft_ptr->cur_intercept++;
484 		if(obj_aircraft_ptr->cur_intercept >= obj_aircraft_ptr->total_intercepts)
485 		    obj_aircraft_ptr->cur_intercept = obj_aircraft_ptr->total_intercepts - 1;
486 	    }
487 
488 	    /* Increment to next objective */
489 	    mission->cur_objective++;
490 	}
491 
492 	/* All objectives completed? */
493 	if((mission->cur_objective >= mission->total_objectives) ||
494 	   (objective == NULL)
495 	)
496 	{
497 	    /* Mark mission progress state as accomplished */
498 	    mission->state = MISSION_STATE_ACCOMPLISHED;
499 
500 	    /* Set mission accomplished banner */
501 	    SARBannerMessageAppend(scene, NULL);
502 	    SARBannerMessageAppend(scene,
503 		SAR_MESG_MISSION_ACCOMPLISHED_BANNER
504 	    );
505 #if 0
506 	    SARBannerMessageAppend(
507 		scene,
508 		((mesg_ptr != NULL) ? mesg_ptr :
509 		    SAR_MESG_MISSION_ARRIVE_COMPLETE
510 		)
511 	    );
512 #endif
513 
514 	    /* Do not set continue banner message for mission accomplished */
515 
516 	    /* Schedual next mission check in 5 seconds which will
517 	     * detect acomplished state
518 	     */
519 	    mission->next_check = cur_millitime + DEF_MISSION_END_INT;
520 
521 	    /* Return indicating all objectives completed, mission
522 	     * accomplished
523 	     */
524 	    return(1);
525 	}
526 	else
527 	{
528 	    /* Return indicating went on to next objective */
529 	    return(0);
530 	}
531 }
532 
533 /*
534  *	Procedure to mark current objective on the given mission structure
535  *	as failed and mark the entire mission as failed.
536  *
537  *	Returns:
538  *
539  *	-1	General error
540  *	0	Went on to next objective
541  *	1	Entire mission failed
542  */
SARMissionDoObjectiveFailed(sar_mission_struct * mission,sar_scene_struct * scene)543 static int SARMissionDoObjectiveFailed(
544 	sar_mission_struct *mission, sar_scene_struct *scene
545 )
546 {
547 	sar_mission_objective_struct *objective;
548 
549 	if((mission == NULL) || (scene == NULL))
550 	    return(-1);
551 
552 	/* Get current mission objective */
553 	objective = SARMissionObjectiveGetCurrentPtr(mission);
554 	if(objective != NULL)
555 	{
556 	    const char *mesg_ptr = objective->message_fail;
557 
558 	    /* Mark current objective as failed */
559 	    objective->state = SAR_MISSION_OBJECTIVE_STATE_FAILED;
560 
561 	    /* Print failed message? */
562 	    if(mesg_ptr != NULL)
563 		SARMessageAdd(scene, mesg_ptr);
564 
565 	    /* For now, set current objective to reffer past the
566 	     * highest objective
567 	     */
568 /* This might change later, some objectives might allow fail in
569  * the future, thus allowing the next objective to be playable and
570  * not have the entire mission fail
571  *
572  * Check if player has crashed on the scene structure?
573  */
574 	    mission->cur_objective = mission->total_objectives;
575 	}
576 
577 	/* All objectives failed? */
578 	if((mission->cur_objective >= mission->total_objectives) ||
579 	   (objective == NULL)
580 	)
581 	{
582 	    /* Mark mission progress state as failed */
583 	    mission->state = MISSION_STATE_FAILED;
584 
585 	    /* Set mission failed banner */
586 	    SARBannerMessageAppend(scene, NULL);
587 	    SARBannerMessageAppend(scene,
588 		SAR_MESG_MISSION_FAILED_BANNER
589 	    );
590 #if 0
591 	    SARBannerMessageAppend(
592 		scene,
593 		(mesg_ptr != NULL) ? mesg_ptr :
594 		    SAR_MESG_MISSION_ARRIVE_FAILED_TIME
595 	    );
596 #endif
597 
598 	    /* Set continue message */
599 	    SARBannerMessageAppend(
600 		scene,
601 		SAR_MESG_MISSION_POST_FAILED_BANNER
602 	    );
603 
604 	    /* Schedual next mission check in 5 seconds which will
605 	     * detect failed state.
606 	     */
607 	    mission->next_check = cur_millitime + DEF_MISSION_END_INT;
608 
609 	    /* Return indicating entire mission failed */
610 	    return(1);
611 	}
612 	else
613 	{
614 	    /* Return indicating went on to next objective */
615 	    return(0);
616 	}
617 }
618 
619 
620 /*
621  *	Destroy notify. This function should be called whenever an
622  *	object is *about* to be destroyed.
623  */
SARMissionDestroyNotify(sar_core_struct * core_ptr,sar_object_struct * obj_ptr)624 void SARMissionDestroyNotify(
625 	sar_core_struct *core_ptr, sar_object_struct *obj_ptr
626 )
627 {
628 	int player_obj_num;
629 	sar_object_struct *player_obj_ptr;
630 	sar_mission_objective_struct *objective;
631 	sar_mission_struct *mission = core_ptr->mission;
632 	sar_scene_struct *scene = core_ptr->scene;
633 	const sar_option_struct *opt = &core_ptr->option;
634 	if((scene == NULL) || (mission == NULL) || (obj_ptr == NULL))
635 	    return;
636 
637 	if(opt->runtime_debug)
638 	    printf(
639 "SARMissionDestroyNotify():\
640  Got destroy notify for object \"%s\".\n",
641 		obj_ptr->name
642 	    );
643 
644 	/* Get references to player object */
645 	player_obj_num = scene->player_obj_num;
646 	player_obj_ptr = scene->player_obj_ptr;
647 
648 	/* Get current mission objective, return if there isn't one */
649 	objective = SARMissionObjectiveGetCurrentPtr(mission);
650 	if(objective == NULL)
651 	    return;
652 
653 	/* Log object crash event */
654 	if(True)
655 	{
656 	    char *s;
657 	    const char *name = obj_ptr->name;
658 
659 	    /* If this is the player object then get player's name */
660 	    if(player_obj_ptr == obj_ptr)
661 	    {
662 		sar_player_stat_struct *pstat = SARPlayerStatCurrent(
663 		    core_ptr, NULL
664 		);
665 		if(pstat != NULL)
666 		{
667 		    pstat->crashes++;
668 		    name = pstat->name;
669 		}
670 	    }
671 
672 	    s = (char *)malloc(
673 		(80 + STRLEN(name)) * sizeof(char)
674 	    );
675 	    sprintf(
676 		s,
677 		"%s crashed",
678 		name
679 	    );
680 	    SARMissionLogEvent(
681 		core_ptr, mission,
682 		SAR_MISSION_LOG_EVENT_CRASH,
683 		-1.0,
684 		&obj_ptr->pos,
685 		NULL, 0,
686 		s,
687 		fname.mission_log
688 	    );
689 	    free(s);
690 	}
691 
692 
693 	/* Handle by current objective type */
694 	switch(objective->type)
695 	{
696 	  case SAR_MISSION_OBJECTIVE_ARRIVE_AT:
697 	  case SAR_MISSION_OBJECTIVE_PICK_UP:
698 	  case SAR_MISSION_OBJECTIVE_PICK_UP_ARRIVE_AT:
699 	    /* Is the player object the object that was destroyed? */
700 	    if(player_obj_ptr == obj_ptr)
701 	    {
702 		/* Player object has been destroyed, this means that for
703 		 * this type of objective the objective has failed.
704 		 * Mark this objective as failed and go on to the next
705 		 * objective or possibly fail the entire mission
706 		 */
707 		SARMissionDoObjectiveFailed(mission, scene);
708 	    }
709 	    break;
710 	}
711 }
712 
713 /*
714  *	Hoist in notify, this function should be called whenever a number
715  *	of human objects have been deleted because they were hoisted
716  *	into the object specified by obj_ptr.
717  *
718  *	Note that for events of humans entering an object, should call
719  *	the notify function SARMissionPassengerEnterNotify().
720  */
SARMissionHoistInNotify(sar_core_struct * core_ptr,sar_object_struct * obj_ptr,int hoisted_in)721 void SARMissionHoistInNotify(
722 	sar_core_struct *core_ptr, sar_object_struct *obj_ptr,
723 	int hoisted_in          /* Number of humans hoisted in */
724 )
725 {
726 	char *s;
727 	const char *name;
728 	sar_mission_objective_struct *objective;
729 	sar_mission_struct *mission = core_ptr->mission;
730 	sar_scene_struct *scene = core_ptr->scene;
731 	const sar_option_struct *opt = &core_ptr->option;
732 	if((scene == NULL) || (mission == NULL) || (obj_ptr == NULL) ||
733 	   (hoisted_in <= 0)
734 	)
735 	    return;
736 
737 	if(opt->runtime_debug)
738 	    printf(
739 "SARMissionHoistInNotify(): Got hoist in notify for object \"%s\" for %i humans.\n",
740 		obj_ptr->name, hoisted_in
741 	    );
742 
743 	/* Get current mission objective, return if there isn't one */
744 	objective = SARMissionObjectiveGetCurrentPtr(mission);
745 	if(objective == NULL)
746 	    return;
747 
748 	name = obj_ptr->name;
749 
750 	/* If this is the player then add score */
751 	if(scene->player_obj_ptr == obj_ptr)
752 	{
753 	    sar_player_stat_struct *pstat = SARPlayerStatCurrent(
754 		core_ptr, NULL
755 	    );
756 	    if(pstat != NULL)
757 	    {
758 		pstat->score += SAR_POINTS_VICTIM_PICKED_UP * hoisted_in;
759 		name = pstat->name;
760 	    }
761 	}
762 
763 	/* Log human picked up event */
764 	s = (char *)malloc((80 + STRLEN(name)) * sizeof(char));
765 	sprintf(
766 	    s,
767 	    "%s picked up %i passenger%s",
768 	    name,
769 	    hoisted_in,
770 	    (hoisted_in == 1) ? "" : "s"
771 	);
772 	SARMissionLogEvent(
773 	    core_ptr, mission,
774 	    SAR_MISSION_LOG_EVENT_PICKUP,
775 	    -1.0,
776 	    &obj_ptr->pos,
777 	    NULL, 0,
778 	    s,
779 	    fname.mission_log
780 	);
781 	free(s);
782 
783 	/* Handle by current objective type */
784 	switch(objective->type)
785 	{
786 	  /* Only need to check for objectives of type
787 	   * SAR_MISSION_OBJECTIVE_PICK_UP since they get passed the
788 	   * instant all humans have been picked up.
789 	   */
790 	  case SAR_MISSION_OBJECTIVE_PICK_UP:
791 	    /* Reduce number of humans that still need rescue, note that
792 	     * we do not care which object hoisted in these humans.
793 	     */
794 	    objective->humans_need_rescue -= hoisted_in;
795 
796 	    /* All humans picked up? */
797 	    if(objective->humans_need_rescue <= 0)
798 	    {
799 		/* This objective has been passed with success, call
800 		 * procedure to go on to the next objective.
801 		 */
802 		SARMissionDoObjectiveSuccess(mission, scene);
803 	    }
804 	    break;
805 	}
806 }
807 
808 /*
809  *      Passengers enter notify, this function should be called
810  *      whenever a number of people have volentarly (not hoisted in)
811  *	entered the object specified by obj_ptr.
812  *
813  *      The value passengers_entered indicates how many passengers
814  *      entered the given object (since the object's current passenger
815  *      count is not checked).
816  */
SARMissionPassengersEnterNotify(sar_core_struct * core_ptr,sar_object_struct * obj_ptr,int passengers_entered)817 void SARMissionPassengersEnterNotify(
818 	sar_core_struct *core_ptr, sar_object_struct *obj_ptr,
819 	int passengers_entered	/* Number of passengers entered */
820 )
821 {
822 	char *s;
823 	const char *name;
824 	sar_mission_objective_struct *objective;
825 	sar_mission_struct *mission = core_ptr->mission;
826 	sar_scene_struct *scene = core_ptr->scene;
827 	const sar_option_struct *opt = &core_ptr->option;
828 	if((scene == NULL) || (mission == NULL) || (obj_ptr == NULL) ||
829 	   (passengers_entered <= 0)
830 	)
831 	    return;
832 
833 	if(opt->runtime_debug)
834 	    printf(
835 "SARMissionPassengersEnterNotify(): Got enter notify for object \"%s\" for %i humans.\n",
836 		obj_ptr->name, passengers_entered
837 	    );
838 
839 	/* Get current mission objective, return if there isn't one */
840 	objective = SARMissionObjectiveGetCurrentPtr(mission);
841 	if(objective == NULL)
842 	    return;
843 
844 	name = obj_ptr->name;
845 
846 	/* If this is the player then add score */
847 	if(scene->player_obj_ptr == obj_ptr)
848 	{
849 	    sar_player_stat_struct *pstat = SARPlayerStatCurrent(
850 		core_ptr, NULL
851 	    );
852 	    if(pstat != NULL)
853 	    {
854 		pstat->score += SAR_POINTS_VICTIM_PICKED_UP * passengers_entered;
855 		name = pstat->name;
856 	    }
857 	}
858 
859 	/* Log human enter event */
860 	s = (char *)malloc((80 + STRLEN(name)) * sizeof(char));
861 	sprintf(
862 	    s,
863 	    "%s picked up %i passenger%s",
864 	    name,
865 	    passengers_entered,
866 	    (passengers_entered == 1) ? "" : "s"
867 	);
868 	SARMissionLogEvent(
869 	    core_ptr, mission,
870 	    SAR_MISSION_LOG_EVENT_PICKUP,
871 	    -1.0,
872 	    &obj_ptr->pos,
873 	    NULL, 0,
874 	    s,
875 	    fname.mission_log
876 	);
877 	free(s);
878 
879 	/* Handle by current objective type */
880 	switch(objective->type)
881 	{
882 	  /* Only need to check for objectives of type
883 	   * SAR_MISSION_OBJECTIVE_PICK_UP since they get passed the
884 	   * instant all humans have been picked up.
885 	   */
886 	  case SAR_MISSION_OBJECTIVE_PICK_UP:
887 	    /* Reduce number of humans that still need rescue, note that
888 	     * we do not care which object hoisted in these humans.
889 	     */
890 	    objective->humans_need_rescue -= passengers_entered;
891 
892 	    /* All humans picked up? */
893 	    if(objective->humans_need_rescue <= 0)
894 	    {
895 		/* This objective has been passed with success, call
896 		 * procedure to go on to the next objective.
897 		 */
898 		SARMissionDoObjectiveSuccess(mission, scene);
899 	    }
900 	    break;
901 	}
902 }
903 
904 /*
905  *      Passengers leave notify, this function should be called
906  *      whenever the given object safely lets off passengers.
907  *
908  *      The value passengers_left indicates how many passengers
909  *      left the given object (since the object's current passenger
910  *      count is not checked).
911  */
SARMissionPassengersLeaveNotify(sar_core_struct * core_ptr,sar_object_struct * obj_ptr,int passengers_left)912 void SARMissionPassengersLeaveNotify(
913 	sar_core_struct *core_ptr, sar_object_struct *obj_ptr,
914 	int passengers_left	/* Number of passengers that left */
915 )
916 {
917 	sar_mission_struct *mission = core_ptr->mission;
918 	if((mission == NULL) || (obj_ptr == NULL))
919 	    return;
920 
921 /* This is not implemented yet, when it does however it will check if
922  * the number of passengers let off meets the mission requirements
923  * (if this is a rescue mission) and in which case then mark the
924  * mission as successfully ended.
925  */
926 
927 }
928 
929 /*
930  *	Land notify callback, this function should be called whenever an
931  *	object specified by obj_ptr has landed.
932  *
933  *	The ground_contact is an array of object indices that are the
934  *	indices of objects that the given object has landed on. This value
935  *	can be NULL if there are no objects that the given object has
936  *	landed on.
937  */
SARMissionLandNotify(sar_core_struct * core_ptr,sar_object_struct * obj_ptr,const int * ground_contact,int total_ground_contacts)938 void SARMissionLandNotify(
939 	sar_core_struct *core_ptr, sar_object_struct *obj_ptr,
940 	const int *ground_contact, int total_ground_contacts
941 )
942 {
943 	int passengers_unloaded;
944 	sar_mission_objective_struct *objective;
945 	sar_mission_struct *mission = core_ptr->mission;
946 	sar_scene_struct *scene = core_ptr->scene;
947 	const sar_option_struct *opt = &core_ptr->option;
948 	if((scene == NULL) || (mission == NULL) || (obj_ptr == NULL))
949 	    return;
950 
951 	if(opt->runtime_debug)
952 	    printf(
953 "SARMissionLandNotify(): Got land notify for object \"%s\".\n",
954 		    obj_ptr->name
955 	    );
956 
957 	/* Get current mission objective, return if there isn't one */
958 	objective = SARMissionObjectiveGetCurrentPtr(mission);
959 	if(objective == NULL)
960 	    return;
961 
962 #define ACCOUNT_PASSENGERS_DROPPED(i)		\
963 { if(obj_ptr != NULL) {				\
964   char *s;					\
965   const char *name = obj_ptr->name;		\
966 						\
967   /* Add score if this is the player */		\
968   if(scene->player_obj_ptr == obj_ptr)		\
969   {						\
970    sar_player_stat_struct *pstat = SARPlayerStatCurrent(core_ptr, NULL); \
971    if(pstat != NULL)				\
972    {						\
973     pstat->rescues += i;			\
974     pstat->score += SAR_POINTS_VICTIM_RESCUED * i;	\
975     name = pstat->name;				\
976    }						\
977   }						\
978 						\
979   /* Log the number of passengers dropped */	\
980   s = (char *)malloc(				\
981    (256 + STRLEN(obj_ptr->name)) * sizeof(char)	\
982   );						\
983   sprintf(					\
984    s,						\
985    "%s dropped off %i passenger%s",		\
986    name, i, (i == 1) ? "" : "s"			\
987   );						\
988   SARMissionLogEvent(				\
989    core_ptr, mission,				\
990    SAR_MISSION_LOG_EVENT_DROPOFF,		\
991    -1.0f,					\
992    (obj_ptr != NULL) ? &obj_ptr->pos : NULL,	\
993    NULL, 0,					\
994    s,						\
995    fname.mission_log				\
996   );						\
997   free(s);					\
998 } }
999 
1000 	/* Handle by current objective type */
1001 	switch(objective->type)
1002 	{
1003 	  case SAR_MISSION_OBJECTIVE_ARRIVE_AT:
1004 	    /* Not landed at right place? */
1005 	    if(!SARMissionGroundContactMatchName(
1006 		core_ptr, scene,
1007 		core_ptr->object, core_ptr->total_objects,
1008 		ground_contact, total_ground_contacts,
1009 		objective->arrive_at_name
1010 	    ))
1011 		break;
1012 
1013 	    /* Unload passengers */
1014 /* We may need to do a more prettier unload and also check for when
1015  * exactly the passengers are actually unloaded
1016  */
1017 	    passengers_unloaded = SARSimOpPassengersUnloadAll(
1018 		scene, obj_ptr
1019 	    );
1020 	    if(passengers_unloaded > 0)
1021 	    {
1022 		ACCOUNT_PASSENGERS_DROPPED(passengers_unloaded);
1023 	    }
1024 
1025 	    /* Is the given object the player object? */
1026 	    if((scene->player_obj_ptr == obj_ptr) &&
1027 	       (objective->state == SAR_MISSION_OBJECTIVE_STATE_INCOMPLETE) &&
1028 	       (mission->state == MISSION_STATE_IN_PROGRESS)
1029 	    )
1030 	    {
1031 		/* This objective has been passed with success, call
1032 		 * procedure to go on to the next objective.
1033 		 */
1034 		SARMissionDoObjectiveSuccess(mission, scene);
1035 	    }
1036 	    break;
1037 
1038 	  case SAR_MISSION_OBJECTIVE_PICK_UP:
1039 	    /* Skip this case, since it has no arrive at object there
1040 	     * is no way to check if landed at the correct place.
1041 	     * Do not unload passengers either.
1042 	     */
1043 	    break;
1044 
1045 	  case SAR_MISSION_OBJECTIVE_PICK_UP_ARRIVE_AT:
1046 	    /* Landed at the right place? */
1047 	    if(SARMissionGroundContactMatchName(
1048 		core_ptr, scene,
1049 		core_ptr->object, core_ptr->total_objects,
1050 		ground_contact, total_ground_contacts,
1051 		objective->arrive_at_name
1052 	    ))
1053 	    {
1054 		int	*passengers = NULL,
1055 			*total_passengers = NULL;
1056 		int passengers_onboard;
1057 
1058 		/* Get number of passengers on board the given object,
1059 		 * note that the given object may not be the player object
1060 		 * but it is okay because any object is accepted to unload
1061 		 * passengers for this kind of objective
1062 		 */
1063 		SARObjGetOnBoardPtr(
1064 		    obj_ptr,
1065 		    NULL, &passengers, &total_passengers,
1066 		    NULL,
1067 		    NULL, NULL
1068 		);
1069 		passengers_onboard = ((passengers != NULL) ?
1070 		    *passengers : 0
1071 		);
1072 
1073 		/* Unload passengers */
1074 /* We may need to do a more prettier unload, letting passengers leave
1075  * and also check for *when* passengers have all left (but not in this
1076  * land notify function)
1077  */
1078 		passengers_unloaded = SARSimOpPassengersUnloadAll(
1079 		    scene, obj_ptr
1080 		);
1081 		if(passengers_unloaded > 0)
1082 		{
1083 		    ACCOUNT_PASSENGERS_DROPPED(passengers_unloaded);
1084 		}
1085 
1086 		/* Reduce number of humans that need rescue on the
1087 		 * objective structure
1088 		 */
1089 		objective->humans_need_rescue -= passengers_onboard;
1090 
1091 		/* If no more humans need rescue then this objective is
1092 		 * done and will be marked as success
1093 		 */
1094 		if((objective->humans_need_rescue <= 0) &&
1095 		   (objective->state == SAR_MISSION_OBJECTIVE_STATE_INCOMPLETE) &&
1096 		   (mission->state == MISSION_STATE_IN_PROGRESS)
1097 		)
1098 		{
1099 		    /* This objective has been passed with success, call
1100 		     * procedure to go on to the next objective.
1101 		     */
1102 		    SARMissionDoObjectiveSuccess(mission, scene);
1103 		}
1104 	    }
1105 	    break;
1106 
1107 	}	/* Handle by current objective type */
1108 
1109 #undef ACCOUNT_PASSENGERS_DROPPED
1110 }
1111 
1112 
1113 /*
1114  *	Manages the given mission objective. This function should be
1115  *	called from SARMissionManage().
1116  */
SARMissionObjectiveManage(sar_core_struct * core_ptr,sar_mission_struct * mission,sar_mission_objective_struct * objective)1117 static void SARMissionObjectiveManage(
1118 	sar_core_struct *core_ptr, sar_mission_struct *mission,
1119 	sar_mission_objective_struct *objective
1120 )
1121 {
1122 	int player_obj_num;
1123 	sar_object_struct *player_obj_ptr;
1124 	sar_scene_struct *scene = core_ptr->scene;
1125 	const sar_option_struct *opt = &core_ptr->option;
1126 	if((scene == NULL) || (mission == NULL) || (objective == NULL))
1127 	    return;
1128 
1129 	/* Get pointer to player object */
1130 	player_obj_num = scene->player_obj_num;
1131 	player_obj_ptr = scene->player_obj_ptr;
1132 
1133 	/* Handle by objective type */
1134 	switch(objective->type)
1135 	{
1136 	  case SAR_MISSION_OBJECTIVE_ARRIVE_AT:
1137 	    /* Is there a time limit? */
1138 	    if(objective->time_left > 0.0f)
1139 	    {
1140 		/* Reduce time left */
1141 		objective->time_left -= (float)lapsed_millitime *
1142 		    time_compression / 1000.0f;
1143 
1144 		/* Time limit exceeded? */
1145 		if(objective->time_left <= 0.0f)
1146 		{
1147 		    if(opt->runtime_debug)
1148 			printf(
1149 "SARMissionObjectiveManage(): Mission objective time expired to arrive.\n"
1150 			);
1151 
1152 		    /* Time limit exceeded and did not reach arrive at
1153 		     * object. Mark this objective as failed and go on to
1154 		     * the next objective or possibly fail entire mission.
1155 		     */
1156 		    SARMissionDoObjectiveFailed(mission, scene);
1157 		}
1158 	    }
1159 	    break;
1160 
1161 	  case SAR_MISSION_OBJECTIVE_PICK_UP:
1162 	    /* Is there a time limit? */
1163 	    if(objective->time_left > 0.0f)
1164 	    {
1165 		/* Reduce time left */
1166 		objective->time_left -= (float)lapsed_millitime *
1167 		    time_compression / 1000.0f;
1168 
1169 		/* Time limit exceeded? */
1170 		if(objective->time_left <= 0.0f)
1171 		{
1172 		    /* Time limit has exceeded, check if all humans that
1173 		     * still need to be brought to safety are in the
1174 		     * player object.
1175 		     */
1176 		    int passengers = SARMissionGetObjectPassengers(
1177 			core_ptr, player_obj_ptr
1178 		    );
1179 		    if((objective->humans_need_rescue - passengers) > 0)
1180 		    {
1181 			if(opt->runtime_debug)
1182 			    printf(
1183 "SARMissionObjectiveManage(): Mission objective time expired to pick up.\n"
1184 			    );
1185 
1186 			/* There are still more unpicked up humans out
1187 			 * there. Mark this objective as failed and go on
1188 			 * to the next objective or possibly fail entire
1189 			 * mission.
1190 			 */
1191 			SARMissionDoObjectiveFailed(mission, scene);
1192 		    }
1193 		}
1194 	    }
1195 	    break;
1196 
1197 	  case SAR_MISSION_OBJECTIVE_PICK_UP_ARRIVE_AT:
1198 	    /* Is there a time limit? */
1199 	    if(objective->time_left > 0.0f)
1200 	    {
1201 		/* Reduce time left */
1202 		objective->time_left -= (float)lapsed_millitime *
1203 		    time_compression / 1000.0f;
1204 
1205 		/* Time limit exceeded? */
1206 		if(objective->time_left <= 0.0f)
1207 		{
1208 		    if(opt->runtime_debug)
1209 			printf(
1210 "SARMissionObjectiveManage(): Mission objective time expired to pick up and arrive.\n"
1211 			);
1212 
1213 		    /* Time limit exceeded and not all have been rescued
1214 		     * and brought to safety. Mark this objective as
1215 		     * failed and go on to the next objective or possibly
1216 		     * fail entire mission.
1217 		     */
1218 		    SARMissionDoObjectiveFailed(mission, scene);
1219 		}
1220 	    }
1221 	    break;
1222 	}
1223 }
1224 
1225 /*
1226  *	Manages mission, this function should be called once per loop.
1227  *
1228  *	Return codes are as follows:
1229  *
1230  *	-1	Error.
1231  *	0	Nothing happened or not time to manage.
1232  *	1	Mission end success.
1233  *	2	Mission end failure.
1234  */
SARMissionManage(sar_core_struct * core_ptr)1235 int SARMissionManage(sar_core_struct *core_ptr)
1236 {
1237 	sar_mission_struct *mission = core_ptr->mission;
1238 	sar_mission_objective_struct *objective;
1239 	if(mission == NULL)
1240 	    return(-1);
1241 
1242 	/* Update time spent on mission */
1243 	mission->time_spent += (float)lapsed_millitime *
1244 	    time_compression / 1000.0f;
1245 
1246 	/* Not time to manage mission yet? */
1247 	if(mission->next_check > cur_millitime)
1248 	{
1249 	    /* Skip and return success */
1250 	    return(0);
1251 	}
1252 	else
1253 	{
1254 	    /* Yes its time to check mission status */
1255 
1256 	    /* Schedual next time to check mission.
1257 	     *
1258 	     * Note that mission->next_check may be modified again by
1259 	     * one of the mission manage handler functions farther
1260 	     * below.
1261 	     */
1262 	    mission->next_check = cur_millitime + mission->check_int;
1263 	}
1264 
1265 	/* Get current mission objective */
1266 	objective = SARMissionObjectiveGetCurrentPtr(mission);
1267 
1268 
1269 	/* Mission no longer in progress? */
1270 	if((mission->state != MISSION_STATE_IN_PROGRESS) ||
1271 	   (objective == NULL)
1272 	)
1273 	{
1274 	    /* Check the resulting state of the mission */
1275 	    switch(mission->state)
1276 	    {
1277 	      case MISSION_STATE_ACCOMPLISHED:
1278 		return(1);
1279 		break;
1280 
1281 	      case MISSION_STATE_FAILED:
1282 		return(2);
1283 		break;
1284 
1285 	      default:
1286 		/* Unsupported mission state, return error */
1287 		fprintf(
1288 		    stderr,
1289 "SARMissionManage(): Unsupported mission state %i, returning as error.\n",
1290 		    mission->state
1291 		);
1292 		return(-1);
1293 		break;
1294 	    }
1295 	}
1296 
1297 	/* Mission still in progress, manage current mission objective */
1298 	SARMissionObjectiveManage(core_ptr, mission, objective);
1299 
1300 	return(0);
1301 }
1302