1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <sys/types.h>
5 #include <time.h>
6
7 #ifdef __MSW__
8 # include <windows.h>
9 #else
10 # include <sys/time.h>
11 # include <unistd.h>
12 #endif
13
14 #include "gw.h"
15 #include "messages.h"
16 #include "sarreality.h"
17 #include "obj.h"
18 #include "mission.h"
19 #include "sar.h"
20 #include "sartime.h"
21 #include "sarmusic.h"
22 #include "scenesound.h"
23 #include "objio.h"
24 #include "missionio.h"
25 #include "sceneio.h"
26 #include "sarmenuop.h"
27 #include "sarmenucodes.h"
28 #include "sarsimbegin.h"
29
30
31 static void SARSimBeginResetOptions(sar_core_struct *core_ptr);
32
33 int SARSimBeginMission(
34 sar_core_struct *core_ptr,
35 const char *mission_file
36 );
37 int SARSimBeginFreeFlight(
38 sar_core_struct *core_ptr,
39 const char *scene_file,
40 const char *player_file, /* Player aircraft. */
41 sar_position_struct *start_pos,
42 sar_direction_struct *start_dir,
43 const char *weather_preset_name,
44 Boolean free_flight_system_time
45 );
46
47
48 #define ATOI(s) (((s) != NULL) ? atoi(s) : 0)
49 #define ATOL(s) (((s) != NULL) ? atol(s) : 0)
50 #define ATOF(s) (((s) != NULL) ? atof(s) : 0.0f)
51 #define STRDUP(s) (((s) != NULL) ? strdup(s) : NULL)
52
53 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
54 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
55 #define CLIP(a,l,h) (MIN(MAX((a),(l)),(h)))
56 #define STRLEN(s) (((s) != NULL) ? ((int)strlen(s)) : 0)
57
58
59 /*
60 * Resets options for simulation.
61 */
SARSimBeginResetOptions(sar_core_struct * core_ptr)62 static void SARSimBeginResetOptions(sar_core_struct *core_ptr)
63 {
64 sar_option_struct *opt = &core_ptr->option;
65
66 core_ptr->display_help = 0;
67 core_ptr->flir = False;
68
69 opt->show_hud_text = True;
70 opt->show_outside_text = True;
71
72 time_compression = 1.0f;
73 }
74
75 /*
76 * Enters mission simulation from the menu system.
77 *
78 * Returns 0 on success or -1 on failure. On failure this function
79 * will return the menu system.
80 */
SARSimBeginMission(sar_core_struct * core_ptr,const char * mission_file)81 int SARSimBeginMission(
82 sar_core_struct *core_ptr,
83 const char *mission_file
84 )
85 {
86 gw_display_struct *display;
87 sar_scene_struct *scene;
88 sar_mission_struct *mission;
89 sar_progress_cb_struct *cb_data;
90 const sar_option_struct *opt;
91
92
93 if(core_ptr == NULL)
94 return(-1);
95
96 display = core_ptr->display;
97 if(display == NULL)
98 return(-1);
99
100 opt = &core_ptr->option;
101
102 /* Check inputs */
103 if(mission_file == NULL)
104 {
105 GWOutputMessage(
106 display,
107 GWOutputMessageTypeWarning,
108 "Missing Information",
109 "No mission selected",
110 "You need to select a mission"
111 );
112 return(-1);
113 }
114
115
116 /* Begin switching from menus to mission simulation */
117
118 /* Switch to load simulation progress menu */
119 SARMenuSwitchToMenu(
120 core_ptr, SAR_MENU_NAME_LOADING_SIMULATION
121 );
122 /* Check if music needs to be updated and update it as needed.
123 * This will detect that the current menu is the loading
124 * simulation menu and switch to the loading simulation music.
125 */
126 SARMusicUpdate(core_ptr);
127
128 GWSetInputBusy(display);
129
130 core_ptr->stop_count = 0;
131
132 /* Allocate scene structure as needed */
133 if(core_ptr->scene == NULL)
134 {
135 core_ptr->scene = (sar_scene_struct *)calloc(
136 1, sizeof(sar_scene_struct)
137 );
138 if(core_ptr->scene == NULL)
139 {
140 /* Scene allocation failed, switch back to main menu,
141 * mark input as ready, and return
142 */
143 SARMenuSwitchToMenu(
144 core_ptr, SAR_MENU_NAME_MAIN
145 );
146 GWSetInputReady(display);
147 return(-1);
148 }
149 }
150 scene = core_ptr->scene;
151
152 /* Unload mission (in case it's already loaded) */
153 SARMissionDelete(core_ptr->mission);
154 core_ptr->mission = NULL;
155
156 /* Unload scene (in case it's already loaded) */
157 SARSceneDestroy(
158 core_ptr, scene,
159 &core_ptr->object, &core_ptr->total_objects
160 );
161
162 /* Reset game controller values */
163 GCtlResetValues(core_ptr->gctl);
164
165 /* Set up load progress callback data */
166 cb_data = SAR_PROGRESS_CB(calloc(1, sizeof(sar_progress_cb_struct)));
167 cb_data->core_ptr = core_ptr;
168 cb_data->coeff_offset = 0.0f;
169 cb_data->coeff_range = 1.0f;
170 cb_data->can_abort = False;
171
172 /* Load mission */
173 core_ptr->mission = mission = SARMissionLoadFromFile(
174 core_ptr, mission_file,
175 cb_data, SARLoadProgressCB
176 );
177
178 /* Failed to load mission? */
179 if(mission == NULL)
180 {
181 /* Failed to load mission */
182 SARMissionDelete(mission);
183 core_ptr->mission = mission = NULL;
184
185 SARSceneDestroy(
186 core_ptr, scene,
187 &core_ptr->object, &core_ptr->total_objects
188 );
189 free(core_ptr->scene);
190 core_ptr->scene = scene = NULL;
191
192 free(cb_data);
193
194 SARMenuSwitchToMenu(
195 core_ptr, SAR_MENU_NAME_MAIN
196 );
197 GWSetInputReady(display);
198 return(-1);
199 }
200 else
201 {
202 char *s;
203 const char *name;
204 sar_player_stat_struct *pstat = SARPlayerStatCurrent(core_ptr, NULL);
205 sar_object_struct *player_obj_ptr = scene->player_obj_ptr;
206
207 if(pstat != NULL)
208 name = pstat->name;
209 else
210 name = (player_obj_ptr != NULL) ? player_obj_ptr->name : NULL;
211
212 /* Reset mission log file, erasing the old log file and
213 * generating a new one with a header based on the values
214 * from the specified mission
215 */
216 SARMissionLogReset(
217 core_ptr, mission,
218 fname.mission_log
219 );
220
221 /* Log mission start event */
222 s = (char *)malloc(
223 (80 + STRLEN(name) +
224 STRLEN(mission->start_location_name)
225 ) * sizeof(char)
226 );
227 sprintf(
228 s,
229 "%s took off at %s",
230 name,
231 mission->start_location_name
232 );
233 SARMissionLogEvent(
234 core_ptr, core_ptr->mission,
235 SAR_MISSION_LOG_EVENT_TAKEOFF,
236 -1.0,
237 (player_obj_ptr != NULL) ? &player_obj_ptr->pos : NULL,
238 NULL, 0,
239 s,
240 fname.mission_log
241 );
242 free(s);
243
244 /* Update message text color and hud color based on the
245 * initial time of day set on the scene
246 */
247 SARSetGlobalTextColorBrightness(
248 core_ptr,
249 (float)(
250 (scene->tod > 43200.0f) ?
251 MAX(1.0 - ((scene->tod - 43200.0) / 43200.0), 0.4) :
252 MAX(scene->tod / 43200.0, 0.4)
253 )
254 );
255
256 /* Switch off menus */
257 SARMenuSwitchToMenu(core_ptr, NULL);
258
259 /* Update sound on scene */
260 SARSceneSoundUpdate(
261 core_ptr,
262 opt->engine_sounds,
263 opt->event_sounds,
264 opt->voice_sounds,
265 opt->music
266 );
267 }
268
269 /* Need to reset timmers since the loading may have consumed
270 * long amount of time and if the lapsed_millitime is too long
271 * simulations and other timings can get out of sync
272 */
273 SARResetTimmersCB(core_ptr, SARGetCurMilliTime());
274
275 /* Reset option values before starting simulation */
276 SARSimBeginResetOptions(core_ptr);
277
278 GWSetInputReady(display);
279
280 /* Hide pointer cursor */
281 GWHideCursor(display);
282
283 free(cb_data);
284
285 return(0);
286 }
287
288 /*
289 * Enters free flight simulation from the menu system.
290 *
291 * Returns 0 on success or -1 on failure. On failure this function
292 * will return the menu system.
293 */
SARSimBeginFreeFlight(sar_core_struct * core_ptr,const char * scene_file,const char * player_file,sar_position_struct * start_pos,sar_direction_struct * start_dir,const char * weather_preset_name,Boolean free_flight_system_time)294 int SARSimBeginFreeFlight(
295 sar_core_struct *core_ptr,
296 const char *scene_file,
297 const char *player_file, /* Player aircraft. */
298 sar_position_struct *start_pos,
299 sar_direction_struct *start_dir,
300 const char *weather_preset_name,
301 Boolean free_flight_system_time
302 )
303 {
304 gw_display_struct *display;
305 sar_scene_struct *scene;
306 sar_progress_cb_struct *cb_data;
307 const sar_option_struct *opt;
308
309 if(core_ptr == NULL)
310 return(-1);
311
312 display = core_ptr->display;
313 if(display == NULL)
314 return(-1);
315
316 opt = &core_ptr->option;
317
318 /* Check inputs */
319 if(player_file == NULL)
320 {
321 GWOutputMessage(
322 display,
323 GWOutputMessageTypeWarning,
324 "Missing Information",
325 "No aircraft selected",
326 "You need to select an aircraft for free flight"
327 );
328 return(-1);
329 }
330 if(scene_file == NULL)
331 {
332 GWOutputMessage(
333 display,
334 GWOutputMessageTypeWarning,
335 "Missing Information",
336 "No scenery selected",
337 "You need to select a scenery to fly in"
338 );
339 return(-1);
340 }
341
342
343 /* Begin switching from menus to free flight simulation */
344
345 /* Switch to load simulation progress menu */
346 SARMenuSwitchToMenu(
347 core_ptr, SAR_MENU_NAME_LOADING_SIMULATION
348 );
349 /* Check if music needs to be updated and update it as needed.
350 * This will detect that the current menu is the loading
351 * simulation menu and switch to the loading simulation music.
352 */
353 SARMusicUpdate(core_ptr);
354
355 GWSetInputBusy(display);
356
357 core_ptr->stop_count = 0;
358
359 /* Allocate scene structure as needed. */
360 if(core_ptr->scene == NULL)
361 {
362 core_ptr->scene = (sar_scene_struct *)calloc(
363 1, sizeof(sar_scene_struct)
364 );
365 if(core_ptr->scene == NULL)
366 {
367 SARMenuSwitchToMenu(
368 core_ptr, SAR_MENU_NAME_MAIN
369 );
370 GWSetInputReady(display);
371 return(-1);
372 }
373 }
374 scene = core_ptr->scene;
375
376 /* Unload scene (incase it's already loaded/allocated). */
377 SARSceneDestroy(
378 core_ptr, scene,
379 &core_ptr->object,
380 &core_ptr->total_objects
381 );
382
383 /* Reset game controller values. */
384 GCtlResetValues(core_ptr->gctl);
385
386 /* Set up load progress callback data. */
387 cb_data = SAR_PROGRESS_CB(calloc(1, sizeof(sar_progress_cb_struct)));
388 cb_data->core_ptr = core_ptr;
389 cb_data->coeff_offset = 0.0f;
390 cb_data->coeff_range = 0.9f;
391 cb_data->can_abort = False;
392
393 /* Load scene */
394 if(SARSceneLoadFromFile(
395 core_ptr, scene, scene_file,
396 weather_preset_name,
397 cb_data, SARLoadProgressCB
398 ))
399 {
400 /* Failed to load scene
401 *
402 * Delete any loaded portions of the scene, switch back to
403 * the menus, and return indicating error
404 */
405 SARSceneDestroy(
406 core_ptr, scene,
407 &core_ptr->object, &core_ptr->total_objects
408 );
409 free(scene);
410 core_ptr->scene = scene = NULL;
411
412 free(cb_data);
413
414 SARMenuSwitchToMenu(
415 core_ptr, SAR_MENU_NAME_MAIN
416 );
417 GWSetInputReady(display);
418 return(-1);
419 }
420 else
421 {
422 /* Successfully loaded scene */
423
424 /* Add player object to scene */
425 cb_data->coeff_offset = 0.9f;
426 cb_data->coeff_range = 0.1f;
427 SARLoadProgressCB(cb_data, 0, 1);
428 SARSceneAddPlayerObject(
429 core_ptr, scene, player_file,
430 start_pos, start_dir
431 );
432 SARLoadProgressCB(cb_data, 1, 1);
433
434 /* Set free flight time from system time? */
435 if(free_flight_system_time)
436 {
437 time_t t = time(NULL);
438 struct tm *tm_ptr = localtime(&t);
439 if(tm_ptr != NULL)
440 {
441 scene->tod = (float)(
442 (tm_ptr->tm_hour * 3600) +
443 (tm_ptr->tm_min * 60) +
444 (tm_ptr->tm_sec)
445 );
446 }
447 }
448
449 /* Update message text color and hud color based on the
450 * initial time of day set on the scene
451 */
452 SARSetGlobalTextColorBrightness(
453 core_ptr,
454 (float)(
455 (scene->tod > 43200.0f) ?
456 MAX(1.0 - ((scene->tod - 43200.0) / 43200.0), 0.4) :
457 MAX(scene->tod / 43200.0, 0.4)
458 )
459 );
460
461 /* Switch off menus */
462 SARMenuSwitchToMenu(core_ptr, NULL);
463
464 /* Update sound on scene */
465 SARSceneSoundUpdate(
466 core_ptr,
467 opt->engine_sounds,
468 opt->event_sounds,
469 opt->voice_sounds,
470 opt->music
471 );
472 }
473
474 /* Need to reset timmers since the loading may have consumed
475 * long amount of time and if the lapsed_millitime is too long
476 * simulations and other timings can get out of sync
477 */
478 SARResetTimmersCB(core_ptr, SARGetCurMilliTime());
479
480 /* Reset option values before starting simulation */
481 SARSimBeginResetOptions(core_ptr);
482
483 GWSetInputReady(display);
484
485 /* Hide pointer cursor */
486 GWHideCursor(display);
487
488 free(cb_data);
489
490 return(0);
491 }
492