1 /***************************************************************************
2 main.cpp - description
3 -------------------
4 begin : Tue Sep 19 17:16:48 PDT 2000
5 copyright : (C) 2000 by Michael Bridak
6 email : michael.bridak@verizon.net
7 $Id: main.cpp,v 1.28 2003/07/18 03:50:00 mbridak Exp $
8 ***************************************************************************/
9
10 /***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License. *
15 * . *
16 * *
17 ***************************************************************************/
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21
22 /*Feeling left out? Get included!*/
23 #include <iostream>
24 #include <list>
25 #include <string.h>
26 #include <string>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <math.h>
30 #include <time.h>
31 #include <unistd.h>
32 #include <SDL.h>
33 #include <SDL/SDL.h>
34 #include <SDL/SDL_image.h>
35 #include <SDL/SDL_thread.h>
36 #include "dfont.h"
37 #include "draw.h"
38 #include "gameclock.h"
39 #include "submarine.h"
40 #include "towedarray.h"
41 #include "targetmotionanalysis.h"
42 #include "menu.h"
43 #include "message.h"
44 #include "mission.h"
45 #include "sonar.h"
46 #include "radar.h"
47 #include "files.h"
48 #include "esm.h"
49 #include "control.h"
50 #include "helicopter.h"
51 #include "main.h"
52 #include "sound.h"
53 #include "map.h"
54 #include "winfunctions.h"
55 #include <fstream>
56 #include <cstdlib>
57 #include <iomanip>
58 using namespace std;
59
60 MAP *my_map = NULL;
61
62 //#######GRAPHIC PRIMITIVES#############
SetupScreen(bool full_screen)63 void SetupScreen(bool full_screen){
64 //Initialize the screen and some default colors
65
66 if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO) < 0 ) {
67 cerr << "Couldn't initialize SDL: " << SDL_GetError() << endl;
68 exit(1);
69 }
70 atexit(SDL_Quit);
71 SDL_InitSubSystem(SDL_INIT_TIMER);
72 if(full_screen){
73 //Create main screen surface
74 screen = SDL_SetVideoMode(1024, 768, 16, SDL_FULLSCREEN);
75 }else{
76 screen = SDL_SetVideoMode(1024, 768, 16, SDL_SWSURFACE);
77 }
78
79 if ( screen == NULL ) {
80 cerr << "Couldn't set video mode..." << endl
81 << "OpenSSN requires 1024x768 @ 16 bpp" << endl
82 << SDL_GetError() << endl;
83 exit(1);
84 }
85 SDL_WM_SetCaption("OpenSSN http://openssn.sf.net", "OpenSSN");
86
87 //define some standard colors
88 textcolor = SDL_MapRGB(screen->format, 192, 255, 6);
89 black = SDL_MapRGB(screen->format, 0, 0, 0);
90 white = SDL_MapRGB(screen->format, 255, 255, 255);
91 red = SDL_MapRGB(screen->format, 255, 99, 20);
92 dark_red = SDL_MapRGB(screen->format, 140, 80, 10);
93 green = SDL_MapRGB(screen->format, 0, 255, 0);
94 dark_green = SDL_MapRGB(screen->format, 0, 120, 0);
95 yellow = SDL_MapRGB(screen->format, 216, 255, 0);
96 brown = SDL_MapRGB(screen->format, 120, 140, 0);
97 grey = SDL_MapRGB(screen->format, 180, 180, 180);
98 dark_grey = SDL_MapRGB(screen->format, 100, 100, 100);
99 // mapcolor = SDL_MapRGB(screen->format, 130, 201, 225);
100 mapcolor = SDL_MapRGB(screen->format, 10, 10, 100);
101 // Init_Audio();
102 }
103
MapIcon(int x,int y,int ShipType,int Friend,Uint32 color)104 void MapIcon(int x, int y, int ShipType, int Friend, Uint32 color){
105 // Display NTDS symbols according to the following Legend
106 // Hostile: Submarine = Red Bottom Half Diamond, Surface = Red Full Diamond,
107 // Aircraft = Red Top Half Diamond
108
109 // Friendly: Submarine = green Bottom SemiCircle, Surface = green Circle,
110 // Aircraft = green Top SemiCircle
111
112 // Unknown: Submarine = grey Bottom Half Box, Surface = grey Box,
113 // Aircraft = grey Top Half Box
114
115 // Neutral: Submarine = Yellow Bottom Half box, Surface = Yellow box,
116 // Aircraft = Yellow Top Half box
117
118 // Is it a submarine?
119 if(ShipType == TYPE_SUB) {
120 switch(Friend){
121 case 0: //Foe??
122 DrawDiamond(screen, x-2, y+2, 7, 'B', black); //Bottom Half Diamond
123 DrawDiamond(screen, x, y, 7, 'B', color); //Bottom Half Diamond
124 break;
125 case 1: //Friend??
126 DrawArc(screen, x-2,y+2, 7, 180, 360, black); //Bottom SemiCircle
127 DrawArc(screen, x-2, y+3, 7, 180, 360, black); // thickness
128 DrawArc(screen, x ,y, 7, 180, 360, color); //Bottom SemiCircle
129 DrawArc(screen, x, y + 1, 7, 180, 360, color); // thickness
130 break;
131 case 2://Unknown??
132 DrawBox(screen, x-2 ,y+2, 7, 'B', black); //Bottom Half Box
133 DrawBox(screen, x ,y, 7, 'B', color); //Bottom Half Box
134 break;
135 default: //Neutral
136 DrawBox(screen, x-2 ,y+2, 7, 'B', black); //Bottom Half Box
137 DrawBox(screen, x ,y, 7, 'B', color); //Bottom Half Box
138 }
139 }
140 // Is it a surface ship?
141 else if(ShipType == TYPE_SHIP) {
142 switch(Friend){
143 case 0: //Foe??
144 DrawDiamond(screen, x-2 ,y+2, 7, 'F', black); //Diamond
145 DrawDiamond(screen, x ,y, 7, 'F', color); //Diamond
146 break;
147 case 1: //Friend??
148 DrawCircle(screen, x-2, y+2, 7, black); //Circle
149 DrawCircle(screen, x, y, 7, color); //Circle
150 break;
151 case 2: //Unknown??
152 DrawBox(screen, x-2 ,y+2, 7, 'F', black); //Box
153 DrawBox(screen, x ,y, 7, 'F', color); //Box
154 break;
155 default: //Neutral
156 DrawBox(screen, x-2 ,y+2, 7, 'F', black); //Cross
157 DrawBox(screen, x ,y, 7, 'F', color); //Cross
158 }
159 }
160
161 // Is it an airplane or Helo?
162 else if(ShipType == TYPE_HELICOPTER) {
163 switch(Friend){
164 case 0: //Foe??
165 DrawDiamond(screen, x, y, 7, 'T', color); //Top Half Diamond
166 break;
167 case 1: //Friend??
168 DrawArc(screen, x ,y, 7, 0, 180, color); //Top SemiCircle
169 break;
170 case 2: //Unknown??
171 DrawBox(screen, x ,y, 7, 'T', color); //Top Half Box
172 break;
173 default: //Neutral
174 DrawBox(screen, x ,y, 7, 'T', color); //Top Half Cross
175 }
176 }
177 else if (ShipType == TYPE_TORPEDO)
178 {
179 DrawDiamond(screen, x, y, 7, 'B', color);
180 DrawLine(screen, x, y-5, x, y, color);
181 }
182 else if (ShipType == TYPE_NOISEMAKER)
183 {
184 DrawBox(screen, x, y, 7, 'B', color);
185 }
186 }
187
188
DirectionalPointer(int x,int y,int heading,int speed,Uint32 color)189 void DirectionalPointer(int x, int y, int heading, int speed,Uint32 color){
190 //Draws a directional vane on a ships map icon.
191 //the length will vary depending on the speed.
192
193 double var1; //just a place to hold a value so we don't have to calc it twice.
194 double destinationx; //the dest x&y point for
195 double destinationy; //the drawn line.
196
197 if((speed > 1) || (speed < -1)) speed=speed/2; //allow for 0 speed.
198 var1 = heading * 0.017453; //convert degrees to radians.
199 destinationx = (sin(var1) * speed) + x;
200 destinationy = (-1) * (cos(var1) * speed) + y;
201 DrawLine(screen, x, y, (int)destinationx, (int)destinationy, color);
202 }
203
LoadScreen(int item)204 void LoadScreen(int item){
205 //Loads a PN file into an SDL surface then
206 //blits it to the display surface.
207 //then deletes the temporary surface.
208
209
210 SDL_Surface *IMGFile=NULL; // Get our selfs a surface to work with..
211 SDL_Rect dest; //A rectangle structure to define a blit area
212 switch (item)
213 {
214 case 0:
215 IMGFile = Load_Image("images/tittle.png"); //fill the surface w/ the bmp
216 break;
217 case 1:
218 IMGFile = Load_Image("images/Sonarscreen.png"); //fill the surface w/ the bmp
219 break;
220 case 2:
221 IMGFile = Load_Image("images/Mapscreen.png"); //fill the surface w/ the bmp
222 break;
223 case 3:
224 IMGFile = Load_Image("images/Mapscreen.png"); //fill the surface w/ the bmp
225 break;
226 case 4:
227 IMGFile = Load_Image("images/ControlScreen.png"); //fill the surface w/ the bmp
228 break;
229 case 5:
230 IMGFile = Load_Image("images/RadarScreen.png"); //fill the surface w/ the bmp
231 break;
232 case 6:
233 IMGFile = Load_Image("images/ESMScreen.png"); //fill the surface w/ the bmp
234 break;
235 case 7:
236 IMGFile = Load_Image("images/sub_surfacing.png"); break;
237 case 8:
238 IMGFile = Load_Image("images/sub_rising.png"); break;
239 case 9:
240 IMGFile = Load_Image("images/sub_menu.png"); break;
241 default:
242 cerr << "Unknown screen item" << endl;
243 break;
244 }
245 if ( IMGFile == NULL ) { // Are we screwed??
246 cerr << "Function LoadScreen()" << endl
247 << "Couldn't load screen item# " << item <<endl
248 << "SDL Error: " << SDL_GetError() << endl;
249 SDL_Quit();
250 exit(0);
251 return; // Whine Snivel and Bail..
252 }
253 dest.x = 0; // Blit destination x&y to the upper left
254 dest.y = 0;
255 dest.w = IMGFile->w; // Height and width equal to the
256 dest.h = IMGFile->h; // source images....
257 SDL_BlitSurface(IMGFile, NULL, screen, &dest); // Do the actual Blit
258 SDL_UpdateRects(screen, 1, &dest); //Show the screen...
259 SDL_FreeSurface(IMGFile); //Free up the surface memory..
260 return;
261 }
262
LoadWidgets()263 void LoadWidgets(){
264 SDL_Surface *temp;
265
266 temp = Load_Image("images/mapup.png");
267 if(temp != NULL) navbuttonup = SDL_DisplayFormat(temp);
268 if ( navbuttonup == NULL ) { // Are we screwed??
269 cerr<<"Function LoadWidgets()" << endl
270 << SDL_GetError() << endl;
271 SDL_Quit();
272 exit(0);
273 }
274 SDL_FreeSurface(temp);
275
276 temp = Load_Image("images/mapdown.png");
277 if(temp != NULL) navbuttondown = SDL_DisplayFormat(temp);
278 if ( navbuttondown == NULL ) { // Are we screwed??
279 cerr<<"Function LoadWidgets()" << endl
280 << SDL_GetError() << endl;
281 SDL_Quit();
282 exit(0);
283 }
284 SDL_FreeSurface(temp);
285
286 temp = Load_Image("images/tmaup.png");
287 if(temp != NULL) tmabuttonup = SDL_DisplayFormat(temp);
288 if ( tmabuttonup == NULL ) { // Are we screwed??
289 cerr<<"Function LoadWidgets()" << endl
290 << SDL_GetError() << endl;
291 SDL_Quit();
292 exit(0);
293 }
294 SDL_FreeSurface(temp);
295
296 temp = Load_Image("images/tmadown.png");
297 if(temp != NULL) tmabuttondown = SDL_DisplayFormat(temp);
298 if ( tmabuttondown == NULL ) { // Are we screwed??
299 cerr<<"Function LoadWidgets()" << endl
300 << SDL_GetError() << endl;
301 SDL_Quit();
302 exit(0);
303 }
304 SDL_FreeSurface(temp);
305
306 temp = Load_Image("images/shipcontrolup.png");
307 if(temp != NULL) shipcontrolbuttonup = SDL_DisplayFormat(temp);
308 if ( shipcontrolbuttonup == NULL ) { // Are we screwed??
309
310 cerr<<"Function LoadWidgets()" << endl
311 << SDL_GetError() << endl;
312 SDL_Quit();
313 exit(0);
314 }
315 SDL_FreeSurface(temp);
316
317 temp = Load_Image("images/shipcontroldown.png");
318 if(temp != NULL) shipcontrolbuttondown = SDL_DisplayFormat(temp);
319 if ( shipcontrolbuttondown == NULL ) { // Are we screwed??
320 cerr<<"Function LoadWidgets()" << endl
321 << SDL_GetError() << endl;
322 SDL_Quit();
323 exit(0);
324 }
325 SDL_FreeSurface(temp);
326
327 temp = Load_Image("images/esmup.png");
328 if(temp != NULL) esmbuttonup = SDL_DisplayFormat(temp);
329 if ( esmbuttonup == NULL ) { // Are we screwed??
330 cerr<<"Function LoadWidgets()" << endl
331 << SDL_GetError() << endl;
332 SDL_Quit();
333 exit(0);
334 }
335 SDL_FreeSurface(temp);
336
337 temp = Load_Image("images/esmdown.png");
338 if(temp != NULL) esmbuttondown = SDL_DisplayFormat(temp);
339 if ( esmbuttondown == NULL ) { // Are we screwed??
340 cerr<<"Function LoadWidgets()" << endl
341 << SDL_GetError() << endl;
342 SDL_Quit();
343 exit(0);
344 }
345 SDL_FreeSurface(temp);
346
347 temp = Load_Image("images/radarup.png");
348 if(temp != NULL) radarbuttonup = SDL_DisplayFormat(temp);
349 if ( radarbuttonup == NULL ) { // Are we screwed??
350 cerr<<"Function LoadWidgets()" << endl
351 << SDL_GetError() << endl;
352 SDL_Quit();
353 exit(0);
354 }
355 SDL_FreeSurface(temp);
356
357 temp = Load_Image("images/radardown.png");
358 if(temp != NULL) radarbuttondown = SDL_DisplayFormat(temp);
359 if ( radarbuttondown == NULL ) { // Are we screwed??
360 cerr<<"Function LoadWidgets()" << endl
361 << SDL_GetError() << endl;
362 SDL_Quit();
363 exit(0);
364 }
365 SDL_FreeSurface(temp);
366
367 temp = Load_Image("images/quitbuttonup.png");
368 if(temp != NULL) quitbuttonup = SDL_DisplayFormat(temp);
369 if ( quitbuttonup == NULL ) { // Are we screwed??
370 cerr<<"Function LoadWidgets()" << endl
371 << SDL_GetError() << endl;
372 SDL_Quit();
373 exit(0);
374 }
375 SDL_FreeSurface(temp);
376
377 temp = Load_Image("images/quitbuttondown.png");
378 if(temp != NULL) quitbuttondown = SDL_DisplayFormat(temp);
379 if ( quitbuttondown == NULL ) { // Are we screwed??
380 cerr<<"Function LoadWidgets()" << endl
381 << SDL_GetError() << endl;
382 SDL_Quit();
383 exit(0);
384 }
385 SDL_FreeSurface(temp);
386
387 temp = Load_Image("images/plusbuttonup.png");
388 if(temp != NULL) plusbuttonup = SDL_DisplayFormat(temp);
389 if ( quitbuttonup == NULL ) { // Are we screwed??
390
391 cerr<<"Function LoadWidgets()" << endl
392 << SDL_GetError() << endl;
393 SDL_Quit();
394 exit(0);
395 }
396 SDL_FreeSurface(temp);
397
398 temp = Load_Image("images/plusbuttondown.png");
399 if(temp != NULL) plusbuttondown = SDL_DisplayFormat(temp);
400 if ( quitbuttondown == NULL ) { // Are we screwed??
401 cerr<<"Function LoadWidgets()" << endl
402 << SDL_GetError() << endl;
403 SDL_Quit();
404 exit(0);
405 }
406 SDL_FreeSurface(temp);
407
408 temp = Load_Image("images/minusbuttonup.png");
409 if(temp != NULL) minusbuttonup = SDL_DisplayFormat(temp);
410 if ( minusbuttonup == NULL ) { // Are we screwed??
411 cerr<<"Function LoadWidgets()" << endl
412 << SDL_GetError() << endl;
413 SDL_Quit();
414 exit(0);
415 }
416 SDL_FreeSurface(temp);
417
418 temp = Load_Image("images/minusbuttondown.png");
419 if(temp != NULL) minusbuttondown = SDL_DisplayFormat(temp);
420 if ( minusbuttondown == NULL ) { // Are we screwed??
421 cerr<<"Function LoadWidgets()" << endl
422 << SDL_GetError() << endl;
423 SDL_Quit();
424 exit(0);
425 }
426 SDL_FreeSurface(temp);
427
428 temp = Load_Image("images/centerbuttondown.png");
429 if(temp != NULL) centerbuttondown = SDL_DisplayFormat(temp);
430 if ( centerbuttondown == NULL ) { // Are we screwed??
431 cerr<<"Function LoadWidgets()" << endl
432 << SDL_GetError() << endl;
433 SDL_Quit();
434 exit(0);
435 }
436 SDL_FreeSurface(temp);
437
438 temp = Load_Image("images/centerbuttonup.png");
439 if(temp != NULL) centerbuttonup = SDL_DisplayFormat(temp);
440 if ( centerbuttonup == NULL ) { // Are we screwed??
441 cerr<<"Function LoadWidgets()" << endl
442 << SDL_GetError() << endl;
443 SDL_Quit();
444 exit(0);
445 }
446 SDL_FreeSurface(temp);
447
448 temp = Load_Image("images/upbuttondown.png");
449 if(temp != NULL) upbuttondown = SDL_DisplayFormat(temp);
450 if ( upbuttondown == NULL ) { // Are we screwed??
451 cerr<<"Function LoadWidgets()" << endl
452 << SDL_GetError() << endl;
453 SDL_Quit();
454 exit(0);
455 }
456 SDL_FreeSurface(temp);
457
458 temp = Load_Image("images/upbuttonup.png");
459 if(temp != NULL) upbuttonup = SDL_DisplayFormat(temp);
460 if ( upbuttonup == NULL ) { // Are we screwed??
461 cerr<<"Function LoadWidgets()" << endl
462 << SDL_GetError() << endl;
463 SDL_Quit();
464 exit(0);
465 }
466 SDL_FreeSurface(temp);
467
468 temp = Load_Image("images/downbuttondown.png");
469 if(temp != NULL) downbuttondown = SDL_DisplayFormat(temp);
470 if ( centerbuttondown == NULL ) { // Are we screwed??
471 cerr<<"Function LoadWidgets()" << endl
472 << SDL_GetError() << endl;
473 SDL_Quit();
474 exit(0);
475 }
476 SDL_FreeSurface(temp);
477
478 temp = Load_Image("images/downbuttonup.png");
479 if(temp != NULL) downbuttonup = SDL_DisplayFormat(temp);
480 if ( downbuttonup == NULL ) { // Are we screwed??
481 cerr<<"Function LoadWidgets()" << endl
482 << SDL_GetError() << endl;
483 SDL_Quit();
484 exit(0);
485 }
486 SDL_FreeSurface(temp);
487
488 temp = Load_Image("images/leftbuttondown.png");
489 if(temp != NULL) leftbuttondown = SDL_DisplayFormat(temp);
490 if ( leftbuttondown == NULL ) { // Are we screwed??
491 cerr<<"Function LoadWidgets()" << endl
492 << SDL_GetError() << endl;
493 SDL_Quit();
494 exit(0);
495 }
496 SDL_FreeSurface(temp);
497
498 temp = Load_Image("images/leftbuttonup.png");
499 if(temp != NULL) leftbuttonup = SDL_DisplayFormat(temp);
500 if ( leftbuttonup == NULL ) { // Are we screwed??
501 cerr<<"Function LoadWidgets()" << endl
502 << SDL_GetError() << endl;
503 SDL_Quit();
504 exit(0);
505 }
506 SDL_FreeSurface(temp);
507
508 temp = Load_Image("images/rightbuttondown.png");
509 if(temp != NULL) rightbuttondown = SDL_DisplayFormat(temp);
510 if ( rightbuttondown == NULL ) { // Are we screwed??
511 cerr<<"Function LoadWidgets()" << endl
512 << SDL_GetError() << endl;
513 SDL_Quit();
514 exit(0);
515 }
516 SDL_FreeSurface(temp);
517
518 temp = Load_Image("images/rightbuttonup.png");
519 if(temp != NULL) rightbuttonup = SDL_DisplayFormat(temp);
520 if ( rightbuttonup == NULL ) { // Are we screwed??
521 cerr<<"Function LoadWidgets()" << endl
522 << SDL_GetError() << endl;
523 SDL_Quit();
524 exit(0);
525 }
526 SDL_FreeSurface(temp);
527
528 temp = Load_Image("images/noisemaker.png");
529 if (temp)
530 {
531 noisemaker_image = SDL_DisplayFormat(temp);
532 if (! noisemaker_image)
533 cerr << "Error loading noisemaker image." << endl;
534 SDL_FreeSurface(temp);
535 }
536
537 temp = Load_Image("images/torpedo.png");
538 if (temp)
539 {
540 torpedo_image = SDL_DisplayFormat(temp);
541 if (! noisemaker_image)
542 cerr << "Error loading torpedo image." << endl;
543 SDL_FreeSurface(temp);
544 }
545
546 }
547
548
549
UnLoadWidgets()550 void UnLoadWidgets(){
551
552 //free the surfaces
553
554 SDL_FreeSurface(sonarbuttonup);
555 SDL_FreeSurface(sonarbuttondown);
556 SDL_FreeSurface(navbuttonup);
557 SDL_FreeSurface(navbuttondown);
558 SDL_FreeSurface(tmabuttonup);
559 SDL_FreeSurface(tmabuttondown);
560 SDL_FreeSurface(quitbuttonup);
561 SDL_FreeSurface(quitbuttondown);
562 SDL_FreeSurface(plusbuttonup);
563 SDL_FreeSurface(plusbuttondown);
564 SDL_FreeSurface(minusbuttonup);
565 SDL_FreeSurface(minusbuttondown);
566 SDL_FreeSurface(torpedo_image);
567 SDL_FreeSurface(noisemaker_image);
568 }
569
DisplayNavigationWidgets()570 void DisplayNavigationWidgets(){
571 if (navwidget){ // is the nav button down?
572 destination_rectangle.x = 280; //upper left corner to
573 destination_rectangle.y = 710; //place the button.
574 destination_rectangle.h = navbuttondown->h; //height &
575 destination_rectangle.w = navbuttondown->w;//width of button.
576 SDL_BlitSurface(navbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
577 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
578 if(mapcenter){
579 destination_rectangle.x = 225; //upper left corner to
580 destination_rectangle.y = 269; //place the button.
581 destination_rectangle.h = centerbuttondown->h; //height &
582 destination_rectangle.w = centerbuttondown->w;//width of button.
583 SDL_BlitSurface(centerbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
584 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
585 }else{
586 destination_rectangle.x = 225; //upper left corner to
587 destination_rectangle.y = 269; //place the button.
588 destination_rectangle.h = centerbuttonup->h; //height &
589 destination_rectangle.w = centerbuttonup->w;//width of button.
590 SDL_BlitSurface(centerbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
591 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
592 }
593 destination_rectangle.x = 225; //upper left corner to
594 destination_rectangle.y = 219; //place the button.
595 destination_rectangle.h = upbuttonup->h; //height &
596 destination_rectangle.w = upbuttonup->w;//width of button.
597 SDL_BlitSurface(upbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
598 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
599 destination_rectangle.x = 225; //upper left corner to
600 destination_rectangle.y = 319; //place the button.
601 destination_rectangle.h = downbuttonup->h; //height &
602 destination_rectangle.w = downbuttonup->w;//width of button.
603 SDL_BlitSurface(downbuttonup, NULL, screen, &destination_rectangle); // Do the Blit
604 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen..
605 destination_rectangle.x = 175; //upper left corner to
606 destination_rectangle.y = 269; //place the button.
607 destination_rectangle.h = leftbuttonup->h; //height &
608 destination_rectangle.w = leftbuttonup->w;//width of button.
609 SDL_BlitSurface(leftbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
610 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
611 destination_rectangle.x = 275; //upper left corner to
612 destination_rectangle.y = 269; //place the button.
613 destination_rectangle.h = rightbuttonup->h; //height &
614 destination_rectangle.w = rightbuttonup->w;//width of button.
615 SDL_BlitSurface(rightbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
616 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
617 destination_rectangle.x = 175; //upper left corner to
618 destination_rectangle.y = 359; //place the button.
619 destination_rectangle.h = plusbuttonup->h; //height &
620 destination_rectangle.w = plusbuttonup->w;//width of button.
621 SDL_BlitSurface(plusbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
622 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
623 destination_rectangle.x = 275; //upper left corner to
624 destination_rectangle.y = 359; //place the button.
625 destination_rectangle.h = minusbuttonup->h; //height &
626 destination_rectangle.w = minusbuttonup->w;//width of button.
627 SDL_BlitSurface(minusbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
628 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
629 }else{ // our button must be up...
630 destination_rectangle.x = 280; //upper left corner to
631 destination_rectangle.y = 710; //place the button.
632 destination_rectangle.h = navbuttonup->h; //height &
633 destination_rectangle.w = navbuttonup->w;//width of button.
634 SDL_BlitSurface(navbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
635 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
636 }
637 }
638
DisplayTMAWidgets()639 void DisplayTMAWidgets(){
640 if (tmawidget){ // is the TMA button down?
641 destination_rectangle.x = 380; //upper left corner to
642 destination_rectangle.y = 710; //place the button.
643 destination_rectangle.h = tmabuttondown->h; //height &
644 destination_rectangle.w = tmabuttondown->w;//width of button.
645 SDL_BlitSurface(tmabuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
646 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
647 if(Tma.centerGeoPlot){
648 destination_rectangle.x = 225; //upper left corner to
649 destination_rectangle.y = 269; //place the button.
650 destination_rectangle.h = centerbuttondown->h; //height &
651 destination_rectangle.w = centerbuttondown->w;//width of button.
652 SDL_BlitSurface(centerbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
653 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
654 }else{
655 destination_rectangle.x = 225; //upper left corner to
656 destination_rectangle.y = 269; //place the button.
657 destination_rectangle.h = centerbuttonup->h; //height &
658 destination_rectangle.w = centerbuttonup->w;//width of button.
659 SDL_BlitSurface(centerbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
660 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
661 }
662 destination_rectangle.x = 225; //upper left corner to
663 destination_rectangle.y = 219; //place the button.
664 destination_rectangle.h = upbuttonup->h; //height &
665 destination_rectangle.w = upbuttonup->w;//width of button.
666 SDL_BlitSurface(upbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
667 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
668 destination_rectangle.x = 225; //upper left corner to
669 destination_rectangle.y = 319; //place the button.
670 destination_rectangle.h = downbuttonup->h; //height &
671 destination_rectangle.w = downbuttonup->w;//width of button.
672 SDL_BlitSurface(downbuttonup, NULL, screen, &destination_rectangle); // Do the Blit
673 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen..
674 destination_rectangle.x = 175; //upper left corner to
675 destination_rectangle.y = 269; //place the button.
676 destination_rectangle.h = leftbuttonup->h; //height &
677 destination_rectangle.w = leftbuttonup->w;//width of button.
678 SDL_BlitSurface(leftbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
679 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
680 destination_rectangle.x = 275; //upper left corner to
681 destination_rectangle.y = 269; //place the button.
682 destination_rectangle.h = rightbuttonup->h; //height &
683 destination_rectangle.w = rightbuttonup->w;//width of button.
684 SDL_BlitSurface(rightbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
685 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
686 destination_rectangle.x = 175; //upper left corner to
687 destination_rectangle.y = 359; //place the button.
688 destination_rectangle.h = plusbuttonup->h; //height &
689 destination_rectangle.w = plusbuttonup->w;//width of button.
690 SDL_BlitSurface(plusbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
691 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
692 destination_rectangle.x = 275; //upper left corner to
693 destination_rectangle.y = 359; //place the button.
694 destination_rectangle.h = minusbuttonup->h; //height &
695 destination_rectangle.w = minusbuttonup->w;//width of button.
696 SDL_BlitSurface(minusbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
697 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
698 }else{ // our button must be up...
699 destination_rectangle.x = 380; //upper left corner to
700 destination_rectangle.y = 710; //place the button.
701 destination_rectangle.h = tmabuttonup->h; //height &
702 destination_rectangle.w = tmabuttonup->w;//width of button.
703 SDL_BlitSurface(tmabuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
704 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
705 }
706 }
707
DisplayESMWidgets()708 void DisplayESMWidgets(){
709 destination_rectangle.x = 580; //upper left corner to
710 destination_rectangle.y = 710; //place the button.
711
712 if (esmwidget){ // is the nav button down?
713 destination_rectangle.h =esmbuttondown->h; //height &
714 destination_rectangle.w = esmbuttondown->w;//width of button.
715 SDL_BlitSurface(esmbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
716 }else{ // our button must be up...
717 destination_rectangle.h = esmbuttonup->h; //height &
718 destination_rectangle.w = esmbuttonup->w;//width of button.
719 SDL_BlitSurface(esmbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
720 }
721 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
722 }
723
DisplayRADARWidgets()724 void DisplayRADARWidgets(){
725 destination_rectangle.x = 680; //upper left corner to
726 destination_rectangle.y = 710; //place the button.
727
728 if (radarwidget){ // is the nav button down?
729 destination_rectangle.h =radarbuttondown->h; //height &
730 destination_rectangle.w = radarbuttondown->w;//width of button.
731 SDL_BlitSurface(radarbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
732 }else{ // our button must be up...
733 destination_rectangle.h = radarbuttonup->h; //height &
734 destination_rectangle.w = radarbuttonup->w;//width of button.
735 SDL_BlitSurface(radarbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
736 }
737 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
738 }
739
DisplayShipControlWidgets()740 void DisplayShipControlWidgets(){
741 destination_rectangle.x = 480; //upper left corner to
742 destination_rectangle.y = 710; //place the button.
743
744 if (shipcontrolwidget){ // is the nav button down?
745 destination_rectangle.h = shipcontrolbuttondown->h; //height &
746 destination_rectangle.w = shipcontrolbuttondown->w;//width of button.
747 SDL_BlitSurface(shipcontrolbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
748 }else{ // our button must be up...
749 destination_rectangle.h = shipcontrolbuttonup->h; //height &
750 destination_rectangle.w = shipcontrolbuttonup->w;//width of button.
751 SDL_BlitSurface(shipcontrolbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
752 }
753 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
754 }
DisplayWidgets()755 void DisplayWidgets(){
756 SonarStation.DisplaySonarWidgets();
757 DisplayNavigationWidgets();
758 DisplayTMAWidgets();
759 DisplayShipControlWidgets();
760 DisplayESMWidgets();
761 DisplayRADARWidgets();
762
763 destination_rectangle.x = 780; //upper left corner to
764 destination_rectangle.y = 710; //place the button.
765 if (quitwidget){ // is the quit button down?
766 destination_rectangle.h = quitbuttondown->h; //height &
767 destination_rectangle.w = quitbuttondown->w;//width of button.
768 SDL_BlitSurface(quitbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
769 }else{ // our button must be up...
770 destination_rectangle.h = quitbuttonup->h; //height &
771 destination_rectangle.w = quitbuttonup->w;//width of button.
772 SDL_BlitSurface(quitbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
773 }
774 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
775
776 destination_rectangle.x = 880; //upper left corner to
777 destination_rectangle.y = 710; //place the button.
778 destination_rectangle.h = plusbuttonup->h; //height &
779 destination_rectangle.w = plusbuttonup->w;//width of button.
780 SDL_BlitSurface(plusbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
781 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show button on the screen...
782 destination_rectangle.x = 970; //upper left corner to
783 destination_rectangle.y = 710; //place the button.
784 destination_rectangle.h = minusbuttonup->h; //height &
785 destination_rectangle.w = minusbuttonup->w;//width of button.
786 SDL_BlitSurface(minusbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
787 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show button on the screen...
788
789 }
790
791
792
793 // This function adds a torpedo to the linked-list of torpedoes
794 // The returned value is the new linked-list pointer, in case
795 // the new_torpedo is the first in the list.
Add_Ship(Submarine * all_torp,Submarine * new_torp)796 Submarine *Add_Ship(Submarine *all_torp, Submarine *new_torp)
797 {
798 Submarine *my_torp;
799
800 // we do not have a torpedo to add
801 if (! new_torp)
802 return all_torp;
803
804 // empty list
805 if (! all_torp)
806 return new_torp;
807
808 // add one to an existing list
809 my_torp = all_torp;
810 while (my_torp->next)
811 my_torp = my_torp->next;
812
813 // add to end of list
814 my_torp->next = new_torp;
815
816 return all_torp;
817 }
818
819
820 // This function removes a torpedo from the list of all
821 // torpedoes. It returns the first item in the torpedo linked-list.
Remove_Ship(Submarine * all_torpedoes,Submarine * old_torpedo)822 Submarine *Remove_Ship(Submarine *all_torpedoes, Submarine *old_torpedo)
823 {
824 Submarine *my_torp, *previous;
825
826 if (! all_torpedoes)
827 return NULL;
828 if (! old_torpedo)
829 return all_torpedoes;
830
831 my_torp = all_torpedoes;
832 previous = NULL;
833 while (my_torp)
834 {
835 // found match and it is the first in the list
836 if ( (my_torp == old_torpedo) && (! previous) )
837 {
838 previous = my_torp->next;
839 delete my_torp;
840 return previous;
841 }
842 // found a match and it isn't the first in the list
843 else if (my_torp == old_torpedo)
844 {
845 previous->next = my_torp->next;
846 delete my_torp;
847 return all_torpedoes;
848 }
849 // this one does not match, go to next node
850 else
851 {
852 previous = my_torp;
853 my_torp = my_torp->next;
854 }
855
856 }
857 // item wasn't found, just return the complete list
858 return all_torpedoes;
859 }
860
861
862
Add_Helicopter(Helicopter * all_helicopters,Helicopter * new_helicopter)863 Helicopter *Add_Helicopter(Helicopter *all_helicopters, Helicopter *new_helicopter)
864 {
865 Helicopter *current;
866
867 if (! new_helicopter)
868 return all_helicopters;
869 if (! all_helicopters)
870 return new_helicopter;
871
872 current = all_helicopters;
873 while (current->next)
874 current = current->next;
875 current->next = new_helicopter;
876
877 return all_helicopters;
878 }
879
880
881
Remove_Helicopter(Helicopter * all_helicopters,Helicopter * old_helicopter)882 Helicopter *Remove_Helicopter(Helicopter *all_helicopters, Helicopter *old_helicopter)
883 {
884 Helicopter *current, *previous = NULL;
885
886 if (! all_helicopters)
887 return NULL;
888 if (! old_helicopter)
889 return all_helicopters;
890
891 current = all_helicopters;
892 while (current)
893 {
894 // first in list
895 if ( (current == old_helicopter) && (! previous) )
896 {
897 previous = current->next;
898 delete current;
899 return previous;
900 }
901 // not first in list
902 else if (current == old_helicopter)
903 {
904 previous->next = current->next;
905 delete current;
906 return all_helicopters;
907 }
908 // this is not our node
909 else
910 {
911 previous = current;
912 current = current->next;
913 }
914 }
915 return all_helicopters;
916 }
917
918
919
920
921
922 //######################################
ShipHandeling()923 void ShipHandeling(){
924 Submarine *my_torp, *temp_torp;
925 int status;
926 Submarine *ship;
927 Helicopter *helicopter;
928
929 // see if we can use radar, esm, etc
930 if (player->Depth > PERISCOPE_DEPTH)
931 {
932 EsmStation.LowerMast();
933 RadarStation.LowerMast();
934 player->using_radar = FALSE;
935 }
936 // if array is out, limit speed
937 if (TB16.GetLength() > 0)
938 {
939 int max_speed = Subs->MaxSpeed / 2;
940 if (Subs->Speed > max_speed)
941 Subs->Speed = max_speed;
942 }
943
944 ship = Subs;
945 while (ship)
946 {
947 ship->UpdateLatLon(); //Move all the ships
948 // see what the AI wants to do
949 if (ship != Subs)
950 {
951 /*
952 if (ship->ShipType == TYPE_SUB)
953 torpedoes = ship->Sub_AI(Subs, torpedoes);
954 else if (ship->ShipType == TYPE_SHIP)
955 torpedoes = ship->Ship_AI(Subs, torpedoes);
956 */
957 torpedoes = ship->Sub_AI(Subs, torpedoes, helicopters);
958 }
959 ship->Handeling(); //Steer, Change Depth etc...
960
961 // we were pinging, but it fades quickly
962 if (ship->pinging > 0)
963 ship->pinging--;
964 ship = ship->next;
965 }
966 helicopter = helicopters;
967 while (helicopter)
968 {
969 helicopter->UpdateLatLon();
970 torpedoes = helicopter->Helicopter_AI(Subs, torpedoes);
971 #ifdef DEBUG_HELICOPTER
972 printf("Course: %d\nSpeed: %d\nHeight: %d\n",
973 (int) helicopter->Heading, (int) helicopter->Speed,
974 (int) helicopter->Depth);
975 printf("DX: %d DY: %d\nX: %d Y: %d\n",
976 helicopter->destination_x, helicopter->destination_y,
977 (int) helicopter->Lat_TotalYards,
978 (int) helicopter->Lon_TotalYards);
979 #endif
980 helicopter->Handle();
981 helicopter = helicopter->next;
982 }
983
984 for (int x = 0; x < MAX_SUBS; x++){
985 Contacts[x].UpdateContact();
986 }
987
988 // move some torps
989 my_torp = torpedoes;
990 while (my_torp)
991 {
992 // check to see if this torpedo is chasing the player
993 if ( (my_torp->target == player) &&
994 (my_torp->fuel_remaining == (TORPEDO_FUEL - 30)) )
995 {
996 Message.post_message("Torpedo coming our way!");
997 Message.display_message();
998 }
999 my_torp->UpdateLatLon();
1000 my_torp->Torpedo_AI(Subs); // see where we should be going
1001 my_torp->Handeling(); // change heading and depth
1002 status = my_torp->Check_Status(); // see if we ran into something
1003 // or we are out of fuel
1004 if (status == OUT_OF_FUEL)
1005 {
1006 if (my_torp->ShipType == TYPE_TORPEDO)
1007 Message.post_message("A torpedo ran out of fuel.");
1008 else
1009 Message.post_message("Noisemaker stopped running.");
1010 temp_torp = my_torp->next;
1011 if (current_target == my_torp)
1012 current_target = NULL;
1013 Subs->Cancel_Target(my_torp);
1014 torpedoes = Remove_Ship(torpedoes, my_torp);
1015 my_torp = temp_torp;
1016 Message.display_message();
1017 }
1018 else if (status == HIT_TARGET)
1019 {
1020 int target_status = DAMAGE_OK;
1021 // damage target
1022 // we should always have a target, but just in case...
1023 if (my_torp->target)
1024 {
1025 if (my_torp->target == player)
1026 Message.post_message("We have been hit!");
1027 else
1028 Message.post_message("A torpedo hit its target!");
1029 // radio warning to others
1030 if ( (my_torp->target->ShipType == TYPE_SHIP) &&
1031 (my_torp->target->mood == MOOD_CONVOY) )
1032 {
1033 my_torp->target->Radio_Signal(Subs, RADIO_UNDER_ATTACK);
1034 }
1035 target_status = my_torp->target->Take_Damage();
1036 if (target_status == DAMAGE_SINK)
1037 {
1038 if (my_torp->target == player)
1039 player = NULL;
1040 if (my_torp->target->mission_status == MISSION_ALIVE)
1041 my_mission_status = MISSION_FAILED;
1042 Remove_Inactive_Ship(my_torp->target);
1043 }
1044 }
1045 if (current_target == my_torp)
1046 current_target = NULL;
1047 Subs->Cancel_Target(my_torp);
1048 temp_torp = my_torp->next;
1049 torpedoes = Remove_Ship(torpedoes, my_torp);
1050 my_torp = temp_torp;
1051 // Message.post_message("A torpedo hit its target!");
1052 if (target_status == DAMAGE_SINK)
1053 Message.post_message("Target is sinking!");
1054 Message.display_message();
1055 }
1056 else
1057 my_torp = my_torp->next;
1058 } // end of all torpedoes
1059
1060 // see if we can still detect the current target
1061 if (current_target)
1062 {
1063 status = player->Can_Detect(current_target);
1064 if (status < CONTACT_WEAK)
1065 current_target = NULL;
1066 }
1067 }
1068
1069
1070
1071 // This function may get a little messy, we need to do a few things
1072 // to remove a ship completely from the scenario.
1073 // 1. Any torpedoes shooting at this target have to have their
1074 // target variable set to NULL
1075 // 2. Any ships/subs who were tracking this ship need to stop
Remove_Inactive_Ship(Submarine * victim)1076 void Remove_Inactive_Ship(Submarine *victim)
1077 {
1078 Submarine *torpedo;
1079 Submarine *ship;
1080
1081 if (! victim) // couldn't find victim, this should never happen, quit
1082 return;
1083
1084 // 1. Cancel torpedoes targetting this ship
1085 torpedo = torpedoes;
1086 while (torpedo)
1087 {
1088 if (torpedo->target == victim)
1089 torpedo->target = NULL;
1090 torpedo = torpedo->next;
1091 }
1092
1093 // 2. Ships who were tracking this ship need to stop
1094 ship = Subs;
1095 while (ship)
1096 {
1097 ship->Cancel_Target(victim);
1098 ship = ship->next;
1099 }
1100
1101 Subs->last_target = NULL;
1102 Subs = Remove_Ship(Subs, victim);
1103 if (victim == current_target)
1104 current_target = NULL;
1105 }
1106
1107
1108
1109
1110
1111
RelativeBearing(Submarine * observer,Submarine * target)1112 double RelativeBearing(Submarine *observer, Submarine *target){
1113 // Returns the relative bearing of target to observer. This bearing is
1114 //measured clockwise from on ships heading to target bearing.
1115 double relative_bearing;
1116 int observer_heading, bearing_to_target;
1117 bearing_to_target = (int) observer->BearingToTarget(target );
1118 observer_heading = (int)observer->Heading;
1119 if(observer_heading > bearing_to_target) bearing_to_target += 360;
1120 relative_bearing = bearing_to_target - observer_heading;
1121 return relative_bearing;
1122 }
1123
ReciprocalBearing(int bearing)1124 int ReciprocalBearing(int bearing){
1125 // returns the 180 degree opposite of the bearing given to it..
1126 int recipbearing;
1127 if (bearing >= 180){
1128 recipbearing = bearing - 180;
1129 }else{
1130 recipbearing = bearing + 180;
1131 }
1132 return recipbearing;
1133 }
1134
AngleOnBow(Submarine * observer,Submarine * target)1135 double AngleOnBow(Submarine *observer, Submarine *target){
1136 // Returns the Angle on the Bow (AOB) of target relative to observer.
1137 // Note: -180 < Angle on Bow < 180
1138 // Positive AOB = Port AOB, Negative AOB = Starboard AOB
1139 // Examples:
1140 // target AOB port 30 -> +30
1141 // target AOB starboard 30 -> -30
1142 // target pointing at observer -> 0
1143 // target pointing away from observer -> -180
1144 double aob=0;
1145 aob = target->Heading - observer->Heading
1146 - RelativeBearing(observer,target) - 180;
1147 if (aob > 180) aob = 360 - aob;
1148 if (aob < -180) aob = 360 + aob;
1149 return aob;
1150 }
1151
minimize360(int compass_bearing)1152 int minimize360 ( int compass_bearing ){
1153 // If course is bigger than 360 degrees, then subtract 360 degrees from it
1154 // and keep doing so until it is less than 360 degrees.
1155 while ( compass_bearing > 360 )
1156 {
1157 compass_bearing -= 360;
1158 }
1159 return compass_bearing;
1160 }
1161
maximize360(int compass_bearing)1162 int maximize360 ( int compass_bearing ){
1163 // If course is negative then, then add 360 degrees to it
1164 // and keep doing so until it is positive.
1165 while ( compass_bearing < 0 )
1166 {
1167 compass_bearing += 360;
1168 }
1169 return compass_bearing;
1170 }
1171
CalculateRange(Submarine * observer,Submarine * target)1172 double CalculateRange(Submarine *observer, Submarine *target){
1173 //Calculates the distance in yards from the observer, to the target.
1174
1175 double latdif = 0, londif = 0; //sqrt needs doubles
1176 LatLonDifference( observer, target, &latdif, &londif );
1177 return sqrt((latdif * latdif) + (londif * londif));
1178 }
1179
LatLonDifference(Submarine * x,Submarine * y,double * platdif,double * plondif)1180 void LatLonDifference(Submarine *x, Submarine *y, double *platdif, double *plondif){ // CHANGE TO REFERENCES
1181 //Returns in yards the difference between object x and object y
1182
1183 if (x->Lat_TotalYards > y->Lat_TotalYards){
1184 *platdif = x->Lat_TotalYards - y->Lat_TotalYards;
1185 }
1186 else{
1187 *platdif = y->Lat_TotalYards - x->Lat_TotalYards;
1188 }
1189
1190 if (x->Lon_TotalYards > y->Lon_TotalYards){
1191 *plondif = x->Lon_TotalYards - y->Lon_TotalYards;
1192 }
1193 else{
1194 *plondif = y->Lon_TotalYards - x->Lon_TotalYards;
1195 }
1196 }
1197
CreateShips(int mission_number,MAP * map)1198 void CreateShips(int mission_number, MAP *map)
1199 {
1200 char *ship_file, *mission_name;
1201 char filename[128];
1202 char line[256], *status;
1203 // int i;
1204 FILE *my_file, *mission_file;
1205 Submarine *new_ship;
1206 Helicopter *new_helicopter;
1207 int ship_type, ship_class;
1208
1209 #ifndef WIN32
1210 snprintf(filename, 128, "data/ships%d.dat", mission_number);
1211 #else
1212 sprintf(filename, "data/ships%d.dat", mission_number);
1213 #endif
1214
1215 ship_file = Find_Data_File(filename);
1216 my_file = fopen(ship_file, "r");
1217 if ( (ship_file) && (ship_file != filename) )
1218 free(ship_file);
1219
1220 // idiot check
1221 if(!my_file){
1222 printf("Create ships: file missing\n");
1223 exit(1);
1224 }
1225
1226 #ifndef WIN32
1227 snprintf(filename, 128, "data/mission%d.dat", mission_number);
1228 #else
1229 sprintf(filename, "data/mission%d.dat", mission_number);
1230 #endif
1231 mission_name = Find_Data_File(filename);
1232 mission_file = fopen(mission_name, "r");
1233 if ( (mission_name) && (mission_name != filename) )
1234 free(mission_name);
1235
1236
1237 // Read in the data from the ship file
1238 // Format of ship file: 1 row of data per ship
1239 // Active flag, Ship Type, Friend flag, Speed, DesiredSpeed, Depth,
1240 // Desired depth, Heading, Desired
1241 // Heading, Rudder, Lat_TotalYards, Lon_TotalYards, PSCS
1242
1243 // Notes: Ship Type: Sub=0, Surface=1, Aircraft=2
1244 // Friend: Foe=0, Friend=1, Unknown=2, Neutral=3
1245 // i = 0;
1246 status = fgets(line, 256, my_file);
1247 while (status)
1248 {
1249 sscanf(line, "%d %d", &ship_type, &ship_class);
1250 if (ship_class == CLASS_HELICOPTER)
1251 {
1252 #ifdef DEBUG
1253 printf("Creating new helicopter.\n");
1254 #endif
1255 new_helicopter = new Helicopter();
1256 if (new_helicopter)
1257 {
1258 new_helicopter->map = map;
1259 sscanf(line, "%d %d %d %d %d %d %f %f %d",
1260 &(new_helicopter->ShipType),
1261 &(new_helicopter->ShipClass),
1262 &(new_helicopter->Friend),
1263 &(new_helicopter->DesiredSpeed),
1264 &(new_helicopter->DesiredDepth),
1265 &(new_helicopter->DesiredHeading),
1266 &(new_helicopter->Lat_TotalYards),
1267 &(new_helicopter->Lon_TotalYards),
1268 &(new_helicopter->has_sonar) );
1269 // check mood
1270 #ifndef WIN32
1271 if ( strcasestr(line, "convoy") )
1272 new_helicopter->mood = MOOD_CONVOY;
1273 else if ( strcasestr(line, "passive") )
1274 new_helicopter->mood = MOOD_PASSIVE;
1275 else if ( strcasestr(line, "attack") )
1276 new_helicopter->mood = MOOD_ATTACK;
1277 #else
1278 if ( my_strcasestr(line, "convoy") )
1279 new_helicopter->mood = MOOD_CONVOY;
1280 else if ( my_strcasestr(line, "passive") )
1281 new_helicopter->mood = MOOD_PASSIVE;
1282 else if ( my_strcasestr(line, "attack") )
1283 new_helicopter->mood = MOOD_ATTACK;
1284 #endif
1285 new_helicopter->Speed = new_helicopter->DesiredSpeed;
1286 new_helicopter->Heading = new_helicopter->DesiredHeading;
1287 new_helicopter->Depth = new_helicopter->DesiredDepth;
1288 // load mission
1289 new_helicopter->Load_Mission(mission_file);
1290 // load class
1291 sprintf(filename, "ships/class%d.shp", new_helicopter->ShipClass);
1292 ship_file = Find_Data_File(filename);
1293 new_helicopter->Load_Class(ship_file);
1294 // add helicopter to list
1295 helicopters = Add_Helicopter(helicopters, new_helicopter);
1296 if ( (ship_file) && (ship_file != filename) )
1297 free(ship_file);
1298 } // end of created a helicopter
1299
1300 } // end of helicopter
1301
1302 else // all other classes
1303 {
1304 #ifdef DEBUG
1305 printf("Creating new ship\n");
1306 #endif
1307 new_ship = new Submarine();
1308 if (new_ship)
1309 {
1310 #ifdef DEBUG
1311 printf("Added new ship to list of ships.\n");
1312 #endif
1313 new_ship->Init();
1314 new_ship->map = map;
1315 #ifdef DEBUG
1316 printf("Loaded: %s", line);
1317 #endif
1318 sscanf(line, "%d %d %d %d %d %d %f %f",
1319 &(new_ship->ShipType),
1320 &(new_ship->ShipClass), &(new_ship->Friend),
1321 &(new_ship->DesiredSpeed), &(new_ship->DesiredDepth),
1322 &(new_ship->DesiredHeading), &(new_ship->Lat_TotalYards),
1323 &(new_ship->Lon_TotalYards)); // , &(new_ship->PSCS) );
1324 // check mood
1325 #ifndef WIN32
1326 if ( strcasestr(line, "convoy") )
1327 new_ship->mood = MOOD_CONVOY;
1328 else if ( strcasestr(line, "passive") )
1329 new_ship->mood = MOOD_PASSIVE;
1330 else if ( strcasestr(line, "attack") )
1331 new_ship->mood = MOOD_ATTACK;
1332 #else
1333 if ( my_strcasestr(line, "convoy") )
1334 new_ship->mood = MOOD_CONVOY;
1335 else if ( my_strcasestr(line, "passive") )
1336 new_ship->mood = MOOD_PASSIVE;
1337 else if ( my_strcasestr(line, "attack") )
1338 new_ship->mood = MOOD_ATTACK;
1339 #endif
1340
1341 #ifdef DEBUG
1342 printf("%d %d %d %d %d %d %f %f %d\n",
1343 (new_ship->ShipType),
1344 (new_ship->ShipClass), (new_ship->Friend),
1345 (new_ship->DesiredSpeed), (new_ship->DesiredDepth),
1346 (new_ship->DesiredHeading), (new_ship->Lat_TotalYards),
1347 (new_ship->Lon_TotalYards), new_ship->mood);
1348 // , (new_ship->PSCS) );
1349
1350 #endif
1351 new_ship->Speed = new_ship->DesiredSpeed;
1352 new_ship->Depth = new_ship->DesiredDepth;
1353 new_ship->Heading = new_ship->DesiredHeading;
1354 #ifdef DEBUG
1355 printf("Set S: %f H: %f D: %f\n", new_ship->Speed,
1356 new_ship->Heading, new_ship->Depth);
1357 #endif
1358 new_ship->Load_Mission(mission_file);
1359 #ifdef DEBUG
1360 printf("Ship has mission flag: %d\n", new_ship->mission_status);
1361 #endif
1362 sprintf(filename, "ships/class%d.shp", new_ship->ShipClass);
1363 ship_file = Find_Data_File(filename);
1364 new_ship->Load_Class(ship_file);
1365 Subs = Add_Ship(Subs, new_ship);
1366 if ( (ship_file) && (ship_file != filename) )
1367 free(ship_file);
1368 // i+=1;
1369 } // end of successfully created new ship
1370
1371 } // end of other classes
1372
1373 status = fgets(line, 256, my_file);
1374 }
1375 // inClientFile.close();
1376 if (my_file)
1377 fclose(my_file);
1378 if (mission_file)
1379 fclose(mission_file);
1380
1381 // ships = i - 1;
1382 // ships = i;
1383 // rdm 5/15/01 testing to be sure correct number of ships being read
1384 // cout << " Number of ships = " << i-1 << endl;
1385 if (Subs)
1386 {
1387 SonarStation.Subs = Subs;
1388 RadarStation.Subs = Subs;
1389 EsmStation.Subs = Subs;
1390 ControlStation.Subs = Subs;
1391 player = Subs;
1392 }
1393 }
1394
UpdateSensors()1395 void UpdateSensors(){
1396 //Added code to place our boats position into a FIFO so we
1397 //can calculate where the sonar array is at any time.
1398 //the cable on the TB16 is 2600ft. wich is 866yds. The FIFO is
1399 //100 elements holding 2 double precision floats. So 866/100
1400 //Is 8.66, Which is the resolution of our placement of the array.
1401 #ifdef DEBUG
1402 printf("Updating sensors and stuff\n");
1403 #endif
1404 static float distance_traveled;
1405 distance_traveled += Subs->Speed * 0.555;
1406 if(distance_traveled >= 8.66){ //if we've gone 8.66yds record our loc in the FIFO
1407 TB16.RecordPos(Subs->Lat_TotalYards, Subs->Lon_TotalYards);
1408 distance_traveled = distance_traveled - 8.66;
1409 }
1410 TB16.OperateWinch();//extend/retract the array as needed.
1411 SoundEnvironment(); //lets give a listen...
1412 SonarStation.Sonar(SonarStation.GetNorthCenterState());
1413 SonarStation.TowedSonar(SonarStation.GetNorthCenterState());
1414 }
1415
UpdateDisplay()1416 void UpdateDisplay(){
1417 if (drawmap){
1418 Display_Target();
1419 DrawMap(); // fix me to do something useful!
1420 Draw_Depth_Meter(player, SCREEN_NAV);
1421 }
1422 if (drawsonar){
1423 SonarStation.UpdateDisplay(current_target);
1424 }
1425 if (drawtma){
1426 DisplayTMA();
1427 }
1428 if (drawweapons)
1429 DisplayWeapons();
1430 if (drawradar){
1431 RadarStation.DisplayContacts();
1432 }
1433 if (drawesm){
1434 EsmStation.DisplayContacts();
1435 }
1436 if (drawcontrol){
1437 ControlStation.Display();
1438 Draw_Depth_Meter(player, SCREEN_HELM);
1439 }
1440
1441 }
1442
1443
1444
1445 // Show information on the currently selected target
Display_Target()1446 void Display_Target()
1447 {
1448 char buffer[256];
1449 SDL_Rect rectangle;
1450 DFont fnt("images/font.png", "data/font.dat");
1451 float range;
1452 double bearing;
1453
1454 // if (! current_target)
1455 // return;
1456
1457 // make empty box to the side of the screen
1458 rectangle.x = 120;
1459 rectangle.y = 400;
1460 rectangle.w = 200;
1461 rectangle.h = 160;
1462 SDL_FillRect(screen, &rectangle, black);
1463
1464 if (current_target)
1465 {
1466 // fill in data
1467 sprintf(buffer, " Target");
1468 fnt.PutString(screen, 150, 400, buffer);
1469 sprintf(buffer, "Heading: %d", (int) current_target->Heading);
1470 fnt.PutString(screen, 140, 424, buffer);
1471
1472 sprintf(buffer, "Spead: %d knots", (int) current_target->Speed);
1473 fnt.PutString(screen, 140, 436, buffer);
1474
1475 range = Subs->DistanceToTarget(current_target);
1476 // range *= 0.000568;
1477 range *= YARDS_TO_MILES;
1478 sprintf(buffer, "Range: %2.1f miles", range);
1479 fnt.PutString(screen, 140, 448, buffer);
1480
1481 bearing = Subs->BearingToTarget(current_target);
1482 sprintf(buffer, "Bearing: %2.0lf", bearing);
1483 fnt.PutString(screen, 140, 460, buffer);
1484
1485 sprintf(buffer, "Depth: %d feet", (int) current_target->Depth);
1486 fnt.PutString(screen, 140, 472, buffer);
1487
1488 sprintf(buffer, "Type: %s ", current_target->ClassName );
1489 if (current_target->ClassType[0])
1490 strcat(buffer, current_target->ClassType);
1491 fnt.PutString(screen, 140, 484, buffer);
1492 } // end of valid target
1493 SDL_UpdateRects(screen, 1, &rectangle);
1494 }
1495
1496
1497
Draw_Depth_Meter(Submarine * my_sub,int screen_number)1498 void Draw_Depth_Meter(Submarine *my_sub, int screen_number)
1499 {
1500 SDL_Rect rectangle;
1501 int y, index;
1502
1503 if (screen_number == SCREEN_NAV)
1504 {
1505 rectangle.x = 890;
1506 rectangle.y = 145;
1507 rectangle.h = 500;
1508 }
1509 else // helm screen
1510 {
1511 rectangle.x = 450;
1512 rectangle.y = 125;
1513 rectangle.h = 525;
1514 }
1515 rectangle.w = 10;
1516
1517 if (! my_sub)
1518 return;
1519 SDL_FillRect(screen, &rectangle, mapcolor);
1520 if (my_sub->map)
1521 {
1522 for (index = 0; index < my_sub->map->Thermals_Between(0, MAX_DEPTH); index++)
1523 {
1524 y = my_sub->map->thermals[index];
1525 y = rectangle.y + (y / 10);
1526 FillRectangle(screen, rectangle.x, y, rectangle.x + 10, y+1, white);
1527 }
1528 }
1529 y = (my_sub->Depth / 10) + rectangle.y;
1530 FillRectangle(screen, rectangle.x, y, rectangle.x + 10, y+1, red);
1531 SDL_UpdateRects(screen, 1, &rectangle);
1532 }
1533
1534
DrawMap()1535 void DrawMap(){
1536 //Future home of an actual map display routine, right now just a blank field with dots
1537
1538 SDL_Rect rectangle;
1539 rectangle.x=374;
1540 rectangle.y=145; //define a rectangle on the screen and make it blue
1541 rectangle.h=500;
1542 rectangle.w=501;
1543 SDL_FillRect(screen, &rectangle, mapcolor);
1544
1545 for (int x=374; x<874; x+= 10){ //Make meaningless dots grid on "Map"
1546 for (int y=145; y<637; y+= 10){
1547 DrawPixel(screen, x+5, y+5, white);
1548 }
1549 }
1550 #ifdef DEBUG
1551 printf("About to place ships.\n");
1552 #endif
1553 PlaceShips(mapscale, 0, 0, current_target);
1554 SDL_UpdateRects(screen, 1, &rectangle);
1555
1556 }
1557
PlaceShips(int scale,int change_scrollx,int change_scrolly,Submarine * current_target)1558 void PlaceShips(int scale, int change_scrollx, int change_scrolly, Submarine *current_target){
1559 //Places all Ships onto the map. Soon to change, so only registered contacts appear.
1560 //scale is in YDS per pixel
1561 int fresh;
1562 int x, y; //where to place the ships
1563 int xoffset = 374; //offsets to move the ships to
1564 int yoffset = 145; //the defined place on map screen
1565 static int scrolloffsetx=0; //offset to center map
1566 static int scrolloffsety=0;
1567 Uint32 color;
1568 Submarine *a_torp;
1569 Submarine *target_ship;
1570 Helicopter *a_helicopter;
1571 int layers;
1572
1573 scale = scale * MAP_FACTOR;
1574 if(mapcenter){ //center map onto our own ntds symbol
1575 scrolloffsetx = 250 - ((int)Subs->Lat_TotalYards / scale);
1576 scrolloffsety = 250 - ((int)Subs->Lon_TotalYards / scale);
1577 }else{
1578 scrolloffsetx += change_scrollx;
1579 scrolloffsety += change_scrolly;
1580 }
1581 target_ship = Subs;
1582 #ifdef DEBUG
1583 printf("About to place ships on map.\n");
1584 #endif
1585 while (target_ship)
1586 {
1587 fresh = Subs->Can_Detect(target_ship);
1588 #ifdef DEBUG
1589 printf("Freshness factor %d\n", fresh);
1590 #endif
1591 if ( (fresh) || (target_ship == Subs) )
1592 {
1593 x = 500 - ((int)target_ship->Lat_TotalYards / scale);
1594 x = x - scrolloffsetx;
1595 y = 500 - ((int)target_ship->Lon_TotalYards / scale);
1596 y = y - scrolloffsety;
1597 if (x>10 && x<490 && y>10 && y<490){ //are we going to fall off the damn map???
1598 x = x + xoffset;
1599 y = y + yoffset;
1600 // not only do we need friend/foe, but
1601 // also fresh/old contact
1602 // fresh = Subs->Can_Detect(target_ship);
1603 switch(target_ship->Friend){
1604 case 0: //Foe??
1605 if (fresh >= CONTACT_SOLID)
1606 color = red;
1607 else
1608 color = dark_red;
1609 break;
1610 case 1: //Friend??
1611 if (fresh >= CONTACT_SOLID)
1612 color = green;
1613 else
1614 color = dark_green;
1615 break;
1616 case 2: // Neither???
1617 if (fresh >= CONTACT_SOLID)
1618 color = yellow;
1619 else
1620 color = brown;
1621 break;
1622 default: // Unknown
1623 if (fresh >= CONTACT_SOLID)
1624 color = grey;
1625 else
1626 color = dark_grey;
1627 break;
1628 }
1629 if (target_ship == Subs){ // Is it me???
1630 color = green;
1631 }
1632 #ifdef DEBUG
1633 printf("Deciding if to draw clearly.\n");
1634 #endif
1635 if ( (fresh >= CONTACT_WEAK) || (Subs == target_ship) )
1636 {
1637 MapIcon(x, y, (int)target_ship->ShipType, (int)target_ship->Friend, color); //Draw the NTDS symbol.
1638 // check to see if we should highlight
1639 if (current_target == target_ship)
1640 MapIcon(x, y+1, (int)target_ship->ShipType, (int)target_ship->Friend, color);
1641 DirectionalPointer(x-2, y+2, (int)target_ship->Heading, (int)target_ship->Speed, black);
1642 DirectionalPointer(x, y, (int)target_ship->Heading, (int)target_ship->Speed, color);
1643 // Add pointer the show heading.
1644 } // end of we can hear you ok
1645 } // end of we are on the map
1646 } // end of able to detect
1647 target_ship = target_ship->next;
1648 }
1649
1650 // now place torpedoes
1651 #ifdef DEBUG
1652 printf("About to draw torpedoes on map\n");
1653 #endif
1654 a_torp = torpedoes;
1655 while (a_torp)
1656 {
1657 x = 500 - ((int)a_torp->Lat_TotalYards / scale);
1658 x = x - scrolloffsetx;
1659 y = 500 - ((int)a_torp->Lon_TotalYards / scale);
1660 y = y - scrolloffsety;
1661 if (x>10 && x<490 && y>10 && y<490) //are we going to fall off map??
1662 {
1663 x = x + xoffset;
1664 y = y + yoffset;
1665 switch(a_torp->Friend){
1666 case 0: //Foe??
1667 color = red;
1668 break;
1669 case 1: //Friend??
1670 color = green;
1671 break;
1672 case 2: // Neither???
1673 color = yellow;
1674 break;
1675 default: // Unknown
1676 color = grey;
1677 break;
1678 }
1679 MapIcon(x, y, (int)a_torp->ShipType, (int)a_torp->Friend, color);
1680 } // within map limits
1681
1682 a_torp = a_torp->next;
1683 } // end of displaying torpedoes
1684
1685 #ifdef DEBUG
1686 printf("About to draw helicopters on map.\n");
1687 #endif
1688 // we only draw helicopters if we are near the surface
1689 // and moving slow. This is crude, but it'll do for now
1690 layers = my_map->Thermals_Between(0, player->Depth);
1691 if ( (layers < 1) && (player->Speed < (player->MaxSpeed / 2) ) )
1692 {
1693 a_helicopter = helicopters;
1694 while (a_helicopter)
1695 {
1696 x = 500 - ((int)a_helicopter->Lat_TotalYards / scale);
1697 x = x - scrolloffsetx;
1698 y = 500 - ((int)a_helicopter->Lon_TotalYards / scale);
1699 y = y - scrolloffsety;
1700 if (x>10 && x<490 && y>10 && y<490) // are we on the map
1701 {
1702 x = x + xoffset;
1703 y = y + yoffset;
1704 switch (a_helicopter->Friend)
1705 {
1706 case FOE: color = red; break;
1707 case FRIEND: color = green; break;
1708 case NEUTRAL: color = grey; break;
1709 case UNKNOWN:
1710 default: color = yellow; break;
1711 } // end of friend/foe switch
1712 MapIcon(x, y, a_helicopter->ShipType,
1713 a_helicopter->Friend, color);
1714 } // within map limits
1715 a_helicopter = a_helicopter->next;
1716 } // end of drawing helicopters
1717 } // end of if near surface
1718 }
1719
1720
1721
1722 // calls the other detection functions to see if there is
1723 // any way we can pick up the target
Any_Detection(double Range,Submarine * observer,Submarine * target)1724 float Any_Detection(double Range, Submarine *observer, Submarine *target)
1725 {
1726 float status;
1727
1728 #ifdef DEBUG
1729 printf("Attempting all forms of detection.\n");
1730 #endif
1731 status = Radar_Detection(Range, observer, target);
1732 if (status)
1733 {
1734 // printf("I can see on radar target %d\n", target);
1735 return 2.0;
1736 }
1737 status = Esm_Detection(Range, observer, target);
1738 if (status)
1739 {
1740 // printf("I can pick up on esm target %d\n", target);
1741 return 1.0;
1742 }
1743 // this one takes the most math, so we do it last
1744 // status = Sonar_Detection(Range, observer, target);
1745 status = Sonar_Detection_New(Range, observer, target);
1746 // if (status)
1747 // printf("I can hear target %d\n", target);
1748 return status;
1749 }
1750
1751
1752 // Can I see you on radar?
Radar_Detection(double Range,Submarine * observer,Submarine * target)1753 float Radar_Detection(double Range, Submarine *observer, Submarine *target)
1754 {
1755 int depth, range;
1756 bool result;
1757
1758 depth = (int) observer->Depth;
1759 range = (int) observer->DistanceToTarget(target);
1760 result = RadarStation.isTargetVisible(target, range, depth,
1761 SHIP_HEIGHT, DEFAULT_SEA_STATE);
1762 if (result)
1763 return 1.0;
1764 else
1765 return 0.0;
1766 }
1767
1768
1769 // Can I detect your radar?
Esm_Detection(double Range,Submarine * observer,Submarine * target)1770 float Esm_Detection(double Range, Submarine *observer, Submarine *target)
1771 {
1772 int depth, range;
1773 bool result;
1774
1775 depth = (int) observer->Depth;
1776 range = (int) observer->DistanceToTarget(target);
1777 result = EsmStation.isTargetVisible(target, range, depth,
1778 SHIP_HEIGHT, TRUE, DEFAULT_SEA_STATE);
1779 if (result)
1780 return 1.0;
1781 else
1782 return 0.0;
1783
1784 }
1785
1786
1787
1788 /// Can the observer hear the target?
Sonar_Detection_New(double Range,Submarine * observer,Submarine * target)1789 float Sonar_Detection_New(double Range, Submarine *observer, Submarine *target)
1790 {
1791
1792 float NauticalMiles = (float)Range / 2000.0;
1793 float HisPassiveSonarCrosssection = target->PSCS;
1794 float EffectiveTargetSpeed;
1795 float AmbientNoise;
1796 float OwnShipNoise;
1797 float TotalNoise;
1798 float TargetNoise;
1799 float Gb;
1800 float Lbp;
1801 float NoiseFromSpeed;
1802 float BasisNoiseLevel;
1803 float value;
1804 float SeaState = 3.0; // Anyone want to model the weather.
1805 int thermal_layers = 0;
1806
1807 if (target->Speed <= 5.0){
1808 EffectiveTargetSpeed = 0.0;
1809 }else{
1810 EffectiveTargetSpeed = target->Speed - 5.0;
1811 }
1812
1813 if (target->Speed < 20.0){
1814 NoiseFromSpeed = 1.30;
1815 BasisNoiseLevel = 0.0;
1816 }else{
1817 NoiseFromSpeed = 0.65;
1818 BasisNoiseLevel = 9.75;
1819 }
1820 if (my_map)
1821 thermal_layers = my_map->Thermals_Between(observer->Depth, target->Depth);
1822 #ifdef DEBUGMAP
1823 printf("There are %d thermal layers between us.\n", thermal_layers);
1824 #endif
1825 AmbientNoise = 89.0 + (5.0 * SeaState);
1826 OwnShipNoise = observer->RadiatedNoise();
1827 TotalNoise = 10.0 * log10(pow(10.0,OwnShipNoise/10.0) + pow(10.0,AmbientNoise/10.0));
1828 Gb = (TotalNoise - AmbientNoise) / 2.9;
1829 Lbp = AmbientNoise + Gb;
1830 TargetNoise = HisPassiveSonarCrosssection +
1831 ((NoiseFromSpeed * EffectiveTargetSpeed) + BasisNoiseLevel);
1832 #ifdef DEBUGMAP
1833 printf("Old target noise: %f\n", TargetNoise);
1834 #endif
1835 if (thermal_layers)
1836 TargetNoise -= TargetNoise * (thermal_layers * THERMAL_FILTER);
1837 #ifdef DEBUGMAP
1838 printf("New target noise: %f\n", TargetNoise);
1839 #endif
1840 value = TargetNoise - (20.0 * log10(NauticalMiles) + 1.1 * NauticalMiles) - Lbp;
1841 if (!observer)
1842 SonarStation.flowandambientnoise = (Lbp - 34);
1843 if (value > -45.0){
1844 return (value - -45.0) + 1.0;
1845 }else{
1846 return 0.0;
1847 }
1848 }
1849
1850
1851
1852
1853
SoundEnvironment()1854 void SoundEnvironment(){
1855 ///********************************************************************
1856 //This will gather sound information from all platforms and place
1857 //messages into each platforms sonar queue.
1858 //*********************************************************************
1859
1860 int bearing;
1861 double Range;
1862 Submarine *target;
1863 int line = FALSE;
1864
1865 //loop through each ship and let them listen
1866 //for the other ships...
1867 #ifdef DEBUG
1868 printf("Advancing sonar.\n");
1869 #endif
1870 Subs->AdvanceSonarHistory(); //advance sonar queue by 1/5th of a second
1871 TB16.AdvanceSonarHistory(); //advance sonar queue by 1/5th of a second
1872 // for (target=Subs->next; target; target = target->next){
1873 target = Subs->next;
1874 while (target)
1875 {
1876 #ifdef DEBUG
1877 printf("Checking if we can hear other ships.\n");
1878 #endif
1879 if (! player->InBaffles(target, 1, &TB16)){ //I'm not deaf?
1880 Range = CalculateRange(target, Subs);
1881 float signal;
1882 signal = Any_Detection(Range, Subs, target);
1883 if (signal){ // Are we audible?
1884 #ifdef DEBUG
1885 printf("Heard you, adding to list.\n");
1886 #endif
1887 bearing = (int)Subs->BearingToTarget(target); //Change me to float for better tma
1888 // this weird check prevents us from
1889 // erasing sonar data with radar/esm data
1890 if ( (signal == 1.0) || (signal == 2.0) )
1891 {
1892 float temp_signal;
1893 temp_signal = Sonar_Detection_New(Range, Subs, target);
1894 Subs->RegisterEvent(bearing,temp_signal,target->ShipType);
1895 }
1896 else
1897 Subs->RegisterEvent(bearing, signal, target->ShipType);
1898 // printf("Adding target %d to list.\n", target);
1899 Subs->Add_Target(target, signal);
1900 }
1901 else {
1902 // printf("Lost target %d from list.\n", target);
1903 Subs->Remove_Target(target);
1904 }
1905 }
1906 else if (! player->InBaffles(target, 2, &TB16) && TB16.GetLength() >240){ // do the same for towed array
1907 Range = TB16.RangeToTarget(target->Lat_TotalYards, target->Lon_TotalYards);
1908 float signal;
1909 // signal = Sonar_Detection(Range, 0, target);
1910 signal = Sonar_Detection_New(Range, Subs, target);
1911 if (signal){ // Are we audible?
1912 bearing = (int)TB16.BearingToTarget(target->Lat_TotalYards, target->Lon_TotalYards); //Change me to float for better tma
1913 TB16.RegisterEvent(bearing,signal, target->ShipType);
1914 // printf("Adding target %d to list.\n", target);
1915 Subs->Add_Target(target, signal);
1916 }
1917 else {
1918 // printf("Lost target %d from list.\n", target);
1919 Subs->Remove_Target(target);
1920 }
1921 }
1922 else // can't hear target with either sonar device
1923 Subs->Remove_Target(target);
1924
1925 target = target->next;
1926 if ( (!target) && (! line) )
1927 {
1928 target = torpedoes;
1929 line = TRUE;
1930 }
1931 }
1932 }
1933
1934 /*********************************************
1935 This function will return if a target is in
1936 the observers Baffles and therefore not
1937 detectable. Values for 'int sensor' are 1 for
1938 spherical array, 2 for towed array, 3 for port
1939 hull array and 4 for starboard hull array.
1940
1941 Might want to move the calculations of the
1942 baffle angles to the Coord class so they don't
1943 have to be calculated all the time.
1944 *********************************************/
1945 /*
1946 Moving InBaffles to the Submarine class to keep things cleaner.
1947 -- Jesse
1948
1949 int InBaffles(Submarine *observer, Submarine *target, int sensor){
1950 int array_heading;
1951 int relative_bearing;
1952 int sensordeaf=1;
1953 int bearing_to_target;
1954
1955 switch(sensor){
1956 case 1: //Spherical
1957 sensordeaf = 0;
1958 array_heading = (int)observer->Heading;
1959 bearing_to_target = (int)observer->BearingToTarget( target);
1960 if(array_heading > bearing_to_target) bearing_to_target += 360;
1961 relative_bearing = bearing_to_target - array_heading;
1962 if(relative_bearing > 150 && relative_bearing < 210) sensordeaf = 1;
1963 if(target == observer) sensordeaf = 1;
1964 break;
1965 case 2: //Towed
1966 sensordeaf = 0;
1967 array_heading = (int)TB16.ReturnHeading();
1968 bearing_to_target = (int)TB16.BearingToTarget(target->Lat_TotalYards, target->Lon_TotalYards);
1969 if(array_heading > bearing_to_target) bearing_to_target += 360;
1970 relative_bearing = bearing_to_target - array_heading;
1971 if(relative_bearing < 30 || relative_bearing > 330) sensordeaf = 1;
1972 break;
1973 case 3: //port hull
1974 case 4: //sb hull
1975 default:
1976 break;
1977 }
1978 return sensordeaf;
1979 }
1980 */
1981
1982
DisplayTMA(int xoffset,int yoffset)1983 void DisplayTMA(int xoffset,int yoffset){
1984 SDL_Rect source, destination;
1985 source.x = 0;
1986 source.y = 0;
1987 source.w = 500;
1988 source.h = 500;
1989 destination.x = 374;
1990 destination.y = 145;
1991 destination.w = 500;
1992 destination.h = 500;
1993 Tma.Lock();
1994 Tma.our_heading = (double)Subs->Heading;
1995 Tma.our_speed = (float)Subs->Speed;
1996 Tma.target_heading = (double)Subs->Heading;
1997 Tma.target_speed = (float)Subs->Speed;
1998 Tma.DisplayGeoPlot(xoffset,yoffset);
1999 //Tma.DisplayLOS();
2000 SDL_BlitSurface(Tma.GeoPlotScreen, &source, screen, &destination);
2001 SDL_UpdateRects(screen, 1, &destination);
2002 Tma.UnLock();
2003 }
2004
DisplayWeapons()2005 void DisplayWeapons()
2006 {
2007 SDL_Rect weapons, tubes;
2008 DFont fnt("images/font.png", "data/font.dat");
2009 char text[256];
2010 int index, y1, y2;
2011
2012 if (! update_weapons_screen)
2013 return;
2014
2015 weapons.x = 150;
2016 weapons.y = 145;
2017 weapons.w = 200;
2018 weapons.h = 300;
2019 tubes.x = 374;
2020 tubes.y = 145;
2021 tubes.h = 500;
2022 tubes.w = 501;
2023
2024 SDL_FillRect(screen, &weapons, black);
2025 sprintf(text, "WEAPONS");
2026 fnt.PutString(screen, 190, 150, text);
2027 sprintf(text, " Torpedos: %d", Subs->TorpedosOnBoard);
2028 fnt.PutString(screen, 160, 174, text);
2029 sprintf(text, "Noise Makers: %d", Subs->NoiseMakers);
2030 fnt.PutString(screen, 160, 196, text);
2031 sprintf(text, "'T' to load torpedo");
2032 fnt.PutString(screen, 160, 300, text);
2033 sprintf(text, "'N' to load noise maker");
2034 fnt.PutString(screen, 160, 312, text);
2035 sprintf(text, "'U' to unload device");
2036 fnt.PutString(screen, 160, 324, text);
2037 sprintf(text, "'F' to fire");
2038 fnt.PutString(screen, 160, 336, text);
2039 SDL_UpdateRects(screen, 1, &weapons);
2040
2041 SDL_FillRect(screen, &tubes, black);
2042 y1 = 150; y2 = 190;
2043 for (index = 0; index < MAX_TUBES; index++)
2044 {
2045 // draw tube
2046 DrawRectangle(screen, 390, y1, 500, y2, green);
2047 // draw buttons
2048 fnt.PutString(screen, 520, y1 + 5, " Load");
2049 fnt.PutString(screen, 520, y1 + 18, "Torpedo");
2050 DrawRectangle(screen, 520, y1, 590, y2, green);
2051 fnt.PutString(screen, 600, y1 + 5, " Load");
2052 fnt.PutString(screen, 600, y1 + 18, "Noise Maker");
2053 DrawRectangle(screen, 600, y1, 690, y2, green);
2054 fnt.PutString(screen, 700, y1 + 10, "Unload");
2055 DrawRectangle(screen, 700, y1, 760, y2, green);
2056 fnt.PutString(screen, 770, y1 + 10, "Fire!");
2057 DrawRectangle(screen, 770, y1, 815, y2, green);
2058 y1 += 50; y2 += 50;
2059 }
2060 SDL_UpdateRects(screen, 1, &tubes);
2061
2062 // put stuff in the tubes
2063 y1 = 151;
2064 for (index = 0; index < MAX_TUBES; index++)
2065 {
2066 tubes.x = 391;
2067 tubes.y = y1;
2068 tubes.w = 105;
2069 tubes.h = 35;
2070 if (Subs->torpedo_tube[index] == TUBE_TORPEDO)
2071 SDL_BlitSurface(torpedo_image, NULL, screen, &tubes);
2072 else if (Subs->torpedo_tube[index] == TUBE_NOISEMAKER)
2073 SDL_BlitSurface(noisemaker_image, NULL, screen, &tubes);
2074 else
2075 {
2076 SDL_FillRect(screen, &tubes, black);
2077 sprintf(text, "Tube %d", index + 1);
2078 fnt.PutString(screen, 420, y1 + 10, text);
2079 }
2080 SDL_UpdateRects(screen, 1, &tubes);
2081 y1 += 50;
2082 }
2083 update_weapons_screen = FALSE;
2084 }
2085
2086
2087
RandInt(int TO)2088 inline int RandInt(int TO){ //Returns a random interger...TO is upper limit
2089 return (rand()%TO);
2090 }
2091
Clamp(int sample)2092 inline int Clamp(int sample){ //holds a value to be between 0 and 255
2093 if (sample < 0){
2094 sample = 0;
2095 }
2096 if (sample > 255){
2097 sample = 255;
2098 }
2099 return sample;
2100 }
2101
Clamp(double sample)2102 inline double Clamp(double sample){ //Overloaded for floats
2103 if (sample < 0){
2104 sample = 0.0;
2105 }
2106 if (sample > 255){
2107 sample = 255.0;
2108 }
2109 return sample;
2110 }
2111
ResetWidgetFlags()2112 void ResetWidgetFlags(){
2113 //turns off all the widget redraw flags
2114 SonarStation.sonarwidget=false;
2115 navwidget=0;
2116 quitwidget=0;
2117 tmawidget=0;
2118 esmwidget=0;
2119 radarwidget=0;
2120 shipcontrolwidget=0;
2121 }
2122
ShowStation(int station)2123 void ShowStation(int station){
2124
2125 // init everything to avoid overlap
2126 drawmap = drawweapons = drawsonar = drawradar = drawesm = drawcontrol = 0;
2127 navwidget = shipcontrolwidget = radarwidget = esmwidget = 0;
2128 switch (station){// which station are we at?
2129 case 1: //sonar screen
2130 LoadScreen(1); //load in the screen for the SONAR station
2131 ResetWidgetFlags(); //self explanitory
2132 SonarStation.sonarwidget = true; //depress the widget
2133 DisplayWidgets(); // display the widgets
2134 drawsonar = 1; //tell the sonar it's ok to draw itself
2135 break;
2136 case 2: //nav screen
2137 LoadScreen(2); //load in the screen for the NAV station
2138 ResetWidgetFlags(); //self explanitory
2139 navwidget = 1; //depress the widget
2140 DisplayWidgets(); // display the widgets
2141 drawmap = 1; //tell the Map it's ok to draw itself
2142 break;
2143 case 3: //tma screen
2144 LoadScreen(3); //load in the screen for the TMA station
2145 ResetWidgetFlags(); //self explanitory
2146 // tmawidget = 1; //depress the widget
2147 DisplayWidgets(); // display the widgets
2148 drawweapons = 1; //Turn on TMA screen updates
2149 break;
2150 case 4: //shipcontrol screen
2151 LoadScreen(4); //load in the screen for the shipcontrol station
2152 ResetWidgetFlags(); //self explanitory
2153 shipcontrolwidget = 1; //depress the widget
2154 DisplayWidgets(); // display the widgets
2155 drawcontrol = 1;
2156 ControlStation.InitGraphics(screen, controlscreen);
2157 break;
2158 case 5: //RADAR screen
2159 LoadScreen(5); //load in the screen for the RADAR station
2160 ResetWidgetFlags(); //self explanitory
2161 radarwidget = 1; //depress the widget
2162 DisplayWidgets(); // display the widgets
2163 drawradar = 1; //Turn on Radar screen updates
2164 RadarStation.InitGraphics(screen, radarscreen);
2165 break;
2166 case 6: //ESM screen
2167 LoadScreen(6); //load in the screen for the ESM station
2168 ResetWidgetFlags(); //self explanitory
2169 esmwidget = 1; //depress the widget
2170 DisplayWidgets(); // display the widgets
2171 drawesm = 1; //Turn on ESM screen updates
2172 EsmStation.InitGraphics(screen, esmscreen);
2173 break;
2174 }
2175 }
2176
2177
2178
2179
2180
2181 /**************************************************
2182 This is our callback function to handle
2183 time critical Functions
2184 **************************************************/
timerfunc(Uint32 interval,void * param)2185 Uint32 timerfunc(Uint32 interval, void *param){
2186
2187 should_update_everything = TRUE;
2188 return interval;
2189 }
2190
Update_Everything()2191 int Update_Everything()
2192 {
2193 // param = NULL;
2194 #ifdef DEBUG
2195 printf("In timer function\n");
2196 #endif
2197 Clock.UpdateTime();
2198 ShipHandeling();
2199 if (player)
2200 {
2201 UpdateSensors();
2202 // see if the mission is over
2203 Check_Find(Subs);
2204 Check_Alive(Subs);
2205 my_mission_status = Mission_Status(Subs, my_mission_status);
2206 } // player is dead, we should end the mission
2207 else
2208 my_mission_status = MISSION_FAILED;
2209 return TRUE;
2210 }
2211
2212
2213
2214 /***************************************************
2215 Another callback to handle the 60 second
2216 resolution TMA stuff.
2217 ****************************************************/
TmaTimer(Uint32 interval,void * param)2218 Uint32 TmaTimer(Uint32 interval, void *param){
2219 static Uint32 tick = 0;
2220 Tma.Lock(); //Lock Tma access mutex
2221 param = NULL; //Quites error messages.
2222 tick ++; //record the time of the tma record.
2223 Tma.RecordBoatPosition(Subs->Lat_TotalYards, Subs->Lon_TotalYards, Subs->BearingToTarget(& (Subs[1])) , tick);
2224 Tma.UnLock(); //Unlock mutex
2225 return interval;
2226 }
2227
HandleInput(SDL_Event & event,int & mousex,int & mousey)2228 int HandleInput(SDL_Event &event, int &mousex, int &mousey){
2229 static string textline;
2230 int y1, y2, x_checks_out;
2231 int index;
2232
2233 switch (event.type){
2234 case SDL_MOUSEBUTTONDOWN:
2235 mousex = event.button.x;
2236 mousey = event.button.y;
2237 if (mousey<740 && mousey>711){
2238 if (mousex <212 && mousex>180){ //SONAR widget
2239 return SONAR;
2240 break;
2241 }
2242 if (mousex <312 && mousex>280){ //Map Widget
2243 return NAVMAP;
2244 break;
2245 }
2246 if (mousex <412 && mousex>380){ //TMA Widget
2247 return WEAPONS;
2248 break;
2249 }
2250 if (mousex <512 && mousex>480){ //Ship Control Widget
2251 return SHIPCONTROL;
2252 break;
2253 }
2254 if (mousex <612 && mousex>580){ //ESM Widget
2255 return ESM;
2256 break;
2257 }
2258 if (mousex <712 && mousex>680){ //RADAR Widget
2259 return RADAR;
2260 break;
2261 }
2262 if (mousex <812 && mousex>780){ //Quit Widget
2263 return QUIT;
2264 break;
2265 }
2266 if (mousex < 908 && mousex > 884){ //Time Compression +
2267 return COMPRESSTIME;
2268 break;
2269 }
2270
2271 if (mousex < 1000 && mousex > 972){ //Time Compression -
2272 return UNCOMPRESSTIME;
2273 break;
2274 }
2275 }
2276 if(drawmap || drawtma){
2277 if(mousex > 224 && mousex < 257){
2278 if(mousey >270 && mousey < 300){
2279 return CENTERDISPLAY;
2280 break;
2281 }
2282 }
2283 if(mousex > 224 && mousex < 257){
2284 if(mousey >220 && mousey < 245){
2285 return SCROLLMAPUP;
2286 break;
2287 }
2288 }
2289 if(mousex > 224 && mousex < 257){
2290 if(mousey >320 && mousey < 345){
2291 return SCROLLMAPDOWN;
2292 break;
2293 }
2294 }
2295 if(mousex > 175 && mousex < 210){
2296 if(mousey >270 && mousey < 300){
2297 return SCROLLMAPLEFT;
2298 break;
2299 }
2300 }
2301 if(mousex > 275 && mousex < 310){
2302 if(mousey >270 && mousey < 300){
2303 return SCROLLMAPRIGHT;
2304 break;
2305 }
2306 }
2307 if(mousex >175 && mousex < 210){
2308 if(mousey > 360 && mousey < 390){
2309 return INCREASEMAPSCALE;
2310 break;
2311 }
2312 }
2313 if(mousex >275 && mousex < 310){
2314 if(mousey > 360 && mousey < 390){
2315 return DECREASEMAPSCALE;
2316 break;
2317 }
2318 }
2319 }
2320 // Radar events
2321 if(drawradar){
2322 if(mousex > 105 && mousex < 512){
2323 if(mousey >156 && mousey < 566){
2324 RadarStation.ShowData(screen, mousex, mousey);
2325 break;
2326 }
2327 }
2328
2329 if(mousex > 748 && mousex < 795){
2330 if(mousey >320 && mousey < 367){
2331 return TOGGLER10;
2332 break;
2333 }
2334 }
2335
2336 if(mousex > 795 && mousex < 842){
2337 if(mousey >320 && mousey < 367){
2338 return TOGGLER20;
2339 break;
2340 }
2341 }
2342
2343 if(mousex > 842 && mousex < 889){
2344 if(mousey >320 && mousey < 367){
2345 return TOGGLER30;
2346 break;
2347 }
2348 }
2349
2350 if(mousex > 748 && mousex < 795){
2351 if(mousey >367 && mousey < 414){
2352 return TOGGLER40;
2353 break;
2354 }
2355 }
2356
2357 if(mousex > 795 && mousex < 842){
2358 if(mousey >367 && mousey < 414){
2359 return TOGGLER50;
2360 break;
2361 }
2362 }
2363
2364 if(mousex > 842 && mousex < 889){
2365 if(mousey >367 && mousey < 414){
2366 return TOGGLER60;
2367 break;
2368 }
2369 }
2370
2371 if(mousex > 744 && mousex < 791){
2372 if(mousey >185 && mousey < 232){
2373 return RADARDOWN;
2374 break;
2375 }
2376 }
2377
2378 if(mousex > 850 && mousex < 897){
2379 if(mousey >185 && mousey < 232){
2380 return RADARUP;
2381 break;
2382 }
2383 }
2384
2385 if(mousex > 749 && mousex < 796){
2386 if(mousey >501 && mousey < 548){
2387 return RING0;
2388 break;
2389 }
2390 }
2391
2392 if(mousex > 796 && mousex < 843){
2393 if(mousey >501 && mousey < 548){
2394 return RING5;
2395 break;
2396 }
2397 }
2398
2399 if(mousex > 843 && mousex < 889){
2400 if(mousey >501 && mousey < 548){
2401 return RING10;
2402 break;
2403 }
2404 }
2405
2406 if(mousex > 548 && mousex < 796){
2407 if(mousey >548 && mousey < 594){
2408 return RING15;
2409 break;
2410 }
2411 }
2412
2413 if(mousex > 796 && mousex < 843){
2414 if(mousey >548 && mousey < 594){
2415 return RING20;
2416 break;
2417 }
2418 }
2419
2420 if(mousex > 843 && mousex < 889){
2421 if(mousey >548 && mousey < 594){
2422 return RING25;
2423 break;
2424 }
2425 }
2426 }
2427
2428 // Weapon console events
2429 if (drawweapons)
2430 {
2431 x_checks_out = TRUE;
2432 y1 = 150; y2 = 190;
2433 // check all x1-x2 possiblities
2434 if ( (mousex > 520) && (mousex < 590) )
2435 tube_action = LOAD_TORPEDO;
2436 else if ( (mousex > 600) && (mousex < 680) )
2437 tube_action = LOAD_NOISEMAKER;
2438 else if ( (mousex > 700) && (mousex < 760) )
2439 tube_action = UNLOAD_TUBE;
2440 else if ( (mousex > 770) && (mousex < 815) )
2441 tube_action = FIRE_TUBE;
2442 else
2443 {
2444 tube_action = 0;
2445 x_checks_out = FALSE;
2446 }
2447 // look at all y1-y2 button possibilities
2448 if (x_checks_out)
2449 {
2450 index = 0;
2451 tube_to_use = -1;
2452 while ( (index < MAX_TUBES) &&
2453 (tube_to_use == -1) )
2454 {
2455 if ((mousey > y1) && (mousey < y2) )
2456 tube_to_use = index;
2457 else
2458 {
2459 index++;
2460 y1 += 50; y2 += 50;
2461 }
2462 } // end of checking buttons vertically
2463 if (tube_to_use == -1)
2464 tube_action = 0;
2465 }
2466 else
2467 tube_action = 0;
2468 if ( (tube_action) && (tube_to_use > -1) )
2469 return USE_TUBE;
2470
2471
2472 } // end of weapons screen
2473 // ESM events
2474 if(drawesm){
2475 if(mousex > 744 && mousex < 791){
2476 if(mousey >185 && mousey < 232){
2477 return ESMDOWN;
2478 break;
2479 }
2480 }
2481
2482 if(mousex > 850 && mousex < 897){
2483 if(mousey >185 && mousey < 232){
2484 return ESMUP;
2485 break;
2486 }
2487 }
2488 }
2489
2490 // Control events
2491 if(drawcontrol){
2492 if(mousex > 158 && mousex < 347){
2493 if(mousey >250 && mousey < 430){
2494 ControlStation.AdjustHeading(mousex, mousey);
2495 break;
2496 }
2497 }
2498 if(mousex > 112 && mousex < 126){
2499 if(mousey >254 && mousey < 293){
2500 ControlStation.AdjustDepth(mousex);
2501 break;
2502 }
2503 }
2504
2505 if(mousex > 385 && mousex < 401){
2506 if(mousey >257 && mousey < 296){
2507 ControlStation.AdjustDepth(mousex);
2508 break;
2509 }
2510 }
2511 if(mousex > 364 && mousex < 404){
2512 if(mousey >403 && mousey < 418){
2513 return TURNSTARBOARD;
2514 break;
2515 }
2516 }
2517
2518 if(mousex > 108 && mousex < 147){
2519 if(mousey >405 && mousey < 421){
2520 return TURNPORT;
2521 break;
2522 }
2523 }
2524 if(mousex > 232 && mousex < 252){
2525 if(mousey >581 && mousey < 607){
2526 return ASTOP;
2527 break;
2528 }
2529 }
2530 if(mousex > 263 && mousex < 287){
2531 if(mousey >581 && mousey < 607){
2532 return A13;
2533 break;
2534 }
2535 }
2536 if(mousex > 296 && mousex < 320){
2537 if(mousey >581 && mousey < 607){
2538 return A23;
2539 break;
2540 }
2541 }
2542 if(mousex > 329 && mousex < 352){
2543 if(mousey >581 && mousey < 607){
2544 return ASTD;
2545 break;
2546 }
2547 }
2548 if(mousex > 364 && mousex < 384){
2549 if(mousey >581 && mousey < 607){
2550 return AFULL;
2551 break;
2552 }
2553 }
2554 if(mousex > 397 && mousex < 416){
2555 if(mousey >581 && mousey < 607){
2556 return AFLK;
2557 break;
2558 }
2559 }
2560 if(mousex > 200 && mousex < 218){
2561 if(mousey >581 && mousey < 607){
2562 return B13;
2563 break;
2564 }
2565 }
2566 if(mousex > 166 && mousex < 185){
2567 if(mousey >581 && mousey < 607){
2568 return B23;
2569 break;
2570 }
2571 }
2572 if(mousex > 134 && mousex < 152){
2573 if(mousey >581 && mousey < 607){
2574 return BSTD;
2575 break;
2576 }
2577 }
2578 if(mousex > 100 && mousex < 118){
2579 if(mousey >581 && mousey < 607){
2580 return BEMER;
2581 break;
2582 }
2583 }
2584 if(mousex > 717 && mousex < 757){
2585 if(mousey >585 && mousey < 601){
2586 return EXTENDARRAY;
2587 break;
2588 }
2589 }
2590 if(mousex > 717 && mousex < 757){
2591 if(mousey >612 && mousey < 628){
2592 return RETRACTARRAY;
2593 break;
2594 }
2595 }
2596 }
2597
2598 if(drawsonar){
2599 if(mousex > 615 && mousex < 657){
2600 if(mousey > 162 && mousey < 210){
2601 return TOGGLETRUERELATIVE;
2602 break;
2603 }
2604 }
2605 if(mousex > 474 && mousex < 519){
2606 if(mousey > 358 && mousey < 401){
2607 return DESIGNATECONTACT;
2608 break;
2609 }
2610 }
2611 if(mousex > 615 && mousex < 657){
2612 if(mousey > 215 && mousey < 261){
2613 return TOGGLESPHERICALTOWED;
2614 break;
2615 }
2616 }
2617 if(mousex > 663 && mousex < 706){
2618 if(mousey > 162 && mousey < 210){
2619 return UPPERCRTBUTTON;
2620 break;
2621 }
2622 }
2623 if(mousex > 663 && mousex < 706){
2624 if(mousey > 215 && mousey < 261){
2625 return LOWERCRTBUTTON;
2626 break;
2627 }
2628 }
2629 if (mousex > 472 && mousex < 520)
2630 {
2631 if (mousey > 590 && mousey < 638)
2632 return SEND_PING;
2633 }
2634 if(mousex > 520 && mousex < 567)
2635 {
2636 if (mousey > 590 && mousey < 638)
2637 {
2638 return CUTARRAY;
2639 break;
2640 }
2641 }
2642 if(mousex >569 && mousex < 614){
2643 if(mousey > 593 && mousey < 638){
2644 return STOPWINCH;
2645 break;
2646 }
2647 }
2648 if(mousex > 617 && mousex < 660){
2649 if(mousey > 593 && mousey < 638){
2650 return EXTENDARRAY;
2651 break;
2652 }
2653 }
2654 if(mousex > 663 && mousex < 706){
2655 if(mousey > 593 && mousey < 638){
2656 return RETRACTARRAY;
2657 break;
2658 }
2659 }
2660 if(mousex > 476 && mousex < 517){
2661 if(mousey > 406 && mousey < 447){
2662 return ASSIGNTRACKER;
2663 break;
2664 }
2665 }
2666 if(mousex > 523 && mousex < 564){
2667 if(mousey > 406 && mousey < 447){
2668 return TRACKER1;
2669 break;
2670 }
2671 }
2672 if(mousex > 570 && mousex < 611){
2673 if(mousey > 406 && mousey < 447){
2674 return TRACKER2;
2675 break;
2676 }
2677 }
2678 if(mousex > 617 && mousex < 658){
2679 if(mousey > 406 && mousey < 447){
2680 return TRACKER3;
2681 break;
2682 }
2683 }
2684 if(mousex > 663 && mousex < 706){
2685 if(mousey > 406 && mousey < 447){
2686 return TRACKER4;
2687 break;
2688 }
2689 }
2690 }
2691 break;
2692 case SDL_QUIT:
2693 return QUIT;
2694 break;
2695 case SDL_KEYDOWN: //Process key presses
2696 switch(event.key.keysym.sym){
2697 case SDLK_PAGEUP: // PgUp Make Einstein proud.
2698 return COMPRESSTIME;
2699 break;
2700 case SDLK_PAGEDOWN: // PgDown
2701 return UNCOMPRESSTIME;
2702 break;
2703 case SDLK_KP_PLUS:
2704 case SDLK_PLUS: // Speed Up
2705 return INCREASESPEED;
2706 break;
2707 case SDLK_KP_MINUS:
2708 case SDLK_MINUS: // Slow Down
2709 return DECREASESPEED;
2710 break;
2711 // case SDLK_n: // Navigation
2712 case SDLK_F2:
2713 return NAVMAP;
2714 break;
2715 // case SDLK_s: // Sonar
2716 case SDLK_F1:
2717 return SONAR;
2718 break;
2719 // case SDLK_t: // TMA
2720 case SDLK_F3:
2721 return WEAPONS;
2722 break;
2723 case SDLK_ESCAPE: // Quit...
2724 return QUIT;
2725 break;
2726 case SDLK_TAB: // switch target
2727 return SWITCHTARGET;
2728 break;
2729 case SDLK_F10: // Dump the screen
2730 return DUMPSCREEN;
2731 break;
2732 case SDLK_F4:
2733 return SHIPCONTROL;
2734 break;
2735 case SDLK_F5:
2736 return ESM;
2737 break;
2738 case SDLK_F6:
2739 return RADAR;
2740 break;
2741 case SDLK_KP4: // Turn Left
2742 return TURNPORT;
2743 break;
2744 case SDLK_KP6: // Turn Right
2745 return TURNSTARBOARD;
2746 break;
2747 case SDLK_KP2: // Dive
2748 return INCREASEDEPTH;
2749 break;
2750 case SDLK_KP8: //Surface
2751 return DECREASEDEPTH;
2752 break;
2753 case SDLK_INSERT:
2754 return INCREASEMAPSCALE;
2755 break;
2756 case SDLK_DELETE:
2757 return DECREASEMAPSCALE;
2758 break;
2759 case SDLK_UP :
2760 return SCROLLMAPUP;
2761 break;
2762 case SDLK_DOWN:
2763 return SCROLLMAPDOWN;
2764 break;
2765 case SDLK_LEFT:
2766 return SCROLLMAPLEFT;
2767 break;
2768 case SDLK_RIGHT:
2769 return SCROLLMAPRIGHT;
2770 break;
2771 case SDLK_c:
2772 return CENTERDISPLAY;
2773 break;
2774 case SDLK_e:
2775 return EXTENDARRAY;
2776 break;
2777 case SDLK_r:
2778 return RETRACTARRAY;
2779 break;
2780 case SDLK_w:
2781 return STOPWINCH;
2782 break;
2783 // case 19: // Pause The Game
2784 case SDLK_p: // Pause The Game
2785 return PAUSEGAME;
2786 break;
2787 case SDLK_t:
2788 tube_action = LOAD_TORPEDO;
2789 tube_to_use = -1;
2790 return WHICHTUBE;
2791 case SDLK_n:
2792 tube_action = LOAD_NOISEMAKER;
2793 tube_to_use = -1;
2794 return WHICHTUBE;
2795 case SDLK_u:
2796 tube_action = UNLOAD_TUBE;
2797 tube_to_use = -1;
2798 return WHICHTUBE;
2799 case SDLK_f:
2800 tube_action = FIRE_TUBE;
2801 tube_to_use = -1;
2802 return WHICHTUBE;
2803 case SDLK_1:
2804 tube_to_use = 0;
2805 return USE_TUBE;
2806 case SDLK_2:
2807 tube_to_use = 1;
2808 return USE_TUBE;
2809 case SDLK_3:
2810 tube_to_use = 2;
2811 return USE_TUBE;
2812 case SDLK_4:
2813 tube_to_use = 3;
2814 return USE_TUBE;
2815 case SDLK_5:
2816 tube_to_use = 4;
2817 return USE_TUBE;
2818 case SDLK_6:
2819 tube_to_use = 5;
2820 return USE_TUBE;
2821 case SDLK_g:
2822 return SEND_PING;
2823 case SDLK_q:
2824 return UP_THERMAL;
2825 case SDLK_a:
2826 return HOLD_DEPTH;
2827 case SDLK_z:
2828 return DOWN_THERMAL;
2829 case SDLK_s:
2830 return GO_SURFACE;
2831 case SDLK_x:
2832 return GO_PERISCOPE_DEPTH;
2833 default:
2834 return 0;
2835 break;
2836 }
2837 default:
2838 return 0;
2839 break;
2840 }
2841 return 0;
2842 }
2843
main(int argc,char ** argv)2844 int main(int argc, char **argv){
2845 static char text[120];
2846 int status;
2847 int hours=0;
2848 int minutes=0;
2849 int seconds=0;
2850 int option_choice;//a place to put command line switches
2851 int screendumpcount = 0;
2852 int mousex = 0, mousey = 0; //where is the mouse?
2853 bool quit = false; //Quit flag Duh!
2854 int station; //flag to decide which work station to display
2855 bool full_screen = false;
2856 char *textline = "";
2857 char file1[] = "images/font.png";
2858 char file2[] = "data/font.dat";
2859 char file3[] = "images/largefont.png";
2860 char file4[] = "data/largefont.dat";
2861 int mission_number = 0;
2862 int enable_sound = FALSE;
2863 SDL_Event event; //a typedef to hold events
2864 drawsonar = 0; // draw the sonar flag
2865 drawmap = 1; // draw the map flag
2866 drawradar = 0;
2867 drawesm = 0;
2868 drawcontrol = 0;
2869 northcenter = true; //make the sonar display N. centered
2870 Uint32 timer1; // timer2; // our event timers....
2871 SDL_TimerID timer_id, timer_id2;
2872 torpedoes = NULL;
2873 helicopters = NULL;
2874 tmamutex = SDL_CreateMutex();
2875 srand(time(NULL)); //Seed the random generator
2876
2877 //Process commandline options.
2878 /*
2879 sprintf(text,"m:vwfkhs");
2880 while ((option_choice = getopt(argc, argv, text)) != -1){
2881 */
2882 status = 1;
2883 while (status < argc)
2884 {
2885 if (argv[status][0] == '-')
2886 option_choice = argv[status][1];
2887 else
2888 option_choice = '\0';
2889 switch (option_choice)
2890 {
2891 case 'm':
2892 // mission_number = atoi(optarg);
2893 mission_number = atoi(argv[status + 1]);
2894 status++;
2895 break;
2896 case 'w': //they passed the '-w' flag.
2897 full_screen = false;
2898 break;
2899 case 'f': // full screen
2900 full_screen = true;
2901 break;
2902 /*
2903 case 'k': //This option is just for me cause when using kdevelop
2904 //I don't start in the right directory.
2905 chdir("./subsim");
2906 break;
2907 */
2908 case 'v':
2909 cout << "OpenSSN version " << VERSION << endl;
2910 return 0;
2911 case 'h':
2912 cout << "Usage:" << endl
2913 << "-m <mission> select specific mission." << endl
2914 << "-f For full screen mode." << endl
2915 << "-s Enable sound effects." << endl
2916 << "-w For Windowed Mode." << endl
2917 << "-v For version." << endl
2918 << "-h For this message." << endl;
2919 return 0;
2920 break;
2921 case 's':
2922 enable_sound = TRUE;
2923 break;
2924 default:
2925 cout << "Unknown command-line argument" << endl
2926 << "Please use -h for a list of commands." << endl;
2927 return 1;
2928 } // end of switch
2929 status++;
2930 } // end of while
2931 SetupScreen(full_screen);
2932 Init_Audio(enable_sound);
2933 // CreateShips(mission_number);
2934 Tma.InitGraphics();
2935 SonarStation.InitGraphics();
2936 // msg Message;
2937 Message.InitGraphics();
2938 Clock.InitTime(12,15,0);
2939 SonarStation.LoadWidgets();
2940 SDL_EnableKeyRepeat(150,100);
2941 LoadWidgets();
2942 LoadScreen(0); //Display intro screen
2943 DFont fnt(file1, file2);
2944 static DFont fnt2(file3,file4);
2945 my_map = new MAP();
2946 #ifdef DEBUGMAP
2947 my_map->Test_Map();
2948 #endif
2949 SDL_UpdateRect(screen, 0, 0, 0, 0);
2950 timer1 = SDL_GetTicks();// initialize the timer
2951 SDL_Delay(1000); // show splash screen for one second
2952 quit = false; //reset loop exit flag
2953 //LoadWidgets(); //load up the buttons
2954 LoadScreen(9);
2955 // main menu stuff goes here
2956 status = Main_Menu(&mission_number, screen);
2957 if (status == ACTION_QUIT)
2958 quit = true;
2959
2960 CreateShips(mission_number, my_map);
2961 SDL_Rect rectangle;
2962 rectangle.x = 0;
2963 rectangle.y = 0;
2964 rectangle.w = 1024; // This block of code clears the screen
2965 rectangle.h = 768;
2966 SDL_FillRect(screen, &rectangle, black);
2967 timecompression = 1;
2968 station = 2; //default station
2969 ShowStation(station);
2970 // textline="OpenSSN VERSION 0.5";
2971 sprintf(text, "OpenSSN version %2.1f", VERSION);
2972 Message.post_message(text);
2973 textline="http://openssn.sourceforge.net";
2974 Message.post_message(textline);
2975 Message.display_message();
2976 sprintf(text, "[%i] ", timecompression);
2977 fnt.PutString(screen, 933, 718, text);
2978 my_mission_status = MISSION_STARTED;
2979 timer_id = SDL_AddTimer(1000, timerfunc, NULL);
2980 timer_id2 = SDL_AddTimer(60000, TmaTimer, NULL);
2981 timer1 = SDL_GetTicks();
2982 // timer2 = SDL_GetTicks();
2983 const int frameperiod = 100; //how fast we want the displays to update (in milliseconds)... this allows for a fixed frame rate
2984 while (!quit)
2985 { //This is the main loop.....
2986 if (timer1 + (frameperiod) < SDL_GetTicks()){
2987 timer1 = SDL_GetTicks();
2988 RadarStation.Sweep(frameperiod*timecompression);
2989 UpdateDisplay();
2990
2991 SDL_Rect rectangle;
2992 rectangle.x=16;
2993 rectangle.y=14; //define a rectangle on the screen and make it black
2994 rectangle.h=72;
2995 rectangle.w=126;
2996 SDL_FillRect(screen, &rectangle, black);
2997 sprintf(text, "Now - Wanted");
2998 fnt.PutString(screen, 30, 20, text);
2999 sprintf(text, "S: [%3i] - [%3i]", (int)Subs->Speed, Subs->DesiredSpeed);
3000 fnt.PutString(screen, 30, 31, text);
3001 sprintf(text, "H: [%3i] - [%3i]", (int)Subs->Heading, Subs->DesiredHeading);
3002 fnt.PutString(screen, 30, 42, text);
3003 sprintf(text, "D: [%4i] - [%4i]", (int)Subs->Depth, Subs->DesiredDepth);
3004 fnt.PutString(screen, 30, 53, text);
3005 // sprintf(text, "ARRAY [%4i]", TB16.GetLength());
3006 // fnt.PutString(screen, 40, 53, text);
3007 Clock.GetTime(hours,minutes,seconds);
3008 sprintf(text, "%.2i:%.2i:%.2i", hours, minutes, seconds);
3009 fnt.PutString(screen, 40, 64, text);
3010 SDL_UpdateRects(screen, 1, &rectangle);
3011 }
3012
3013 while (SDL_PollEvent(&event)){
3014 //If there are events waiting take care of them
3015 switch (HandleInput(event, mousex, mousey)){
3016 case SONAR:
3017 ShowStation(1);
3018 UpdateDisplay();
3019 Message.post_message("Sonar station");
3020 Message.display_message();
3021 sprintf(text, "[%i] ", timecompression);
3022 fnt.PutString(screen, 933, 718, text);
3023 break;
3024 case NAVMAP:
3025 ShowStation(2);
3026 UpdateDisplay();
3027 Message.post_message("Naviation display");
3028 Message.display_message();
3029 sprintf(text, "[%i] ", timecompression);
3030 fnt.PutString(screen, 933, 718, text);
3031 break;
3032 case WEAPONS:
3033 update_weapons_screen = TRUE;
3034 ShowStation(3);
3035 UpdateDisplay();
3036 Message.post_message("Weapons console");
3037 Message.display_message();
3038 sprintf(text, "[%i] ", timecompression);
3039 fnt.PutString(screen, 933, 718, text);
3040 break;
3041 case WHICHTUBE:
3042 update_weapons_screen = TRUE;
3043 UpdateDisplay();
3044 Message.post_message("Which tube (1-6)?");
3045 Message.display_message();
3046 break;
3047 case SHIPCONTROL:
3048 ShowStation(4);
3049 UpdateDisplay();
3050 Message.post_message("Helm control");
3051 Message.display_message();
3052 sprintf(text, "[%i] ", timecompression);
3053 fnt.PutString(screen, 933, 718, text);
3054 break;
3055 case ESM:
3056 ShowStation(6);
3057 UpdateDisplay();
3058 Message.post_message("ESM station");
3059 Message.display_message();
3060 sprintf(text, "[%i] ", timecompression);
3061 fnt.PutString(screen, 933, 718, text);
3062 break;
3063 case RADAR:
3064 ShowStation(5);
3065 UpdateDisplay();
3066 Message.post_message("Radar console");
3067 Message.display_message();
3068 sprintf(text, "[%i] ", timecompression);
3069 fnt.PutString(screen, 933, 718, text);
3070 break;
3071 case SWITCHTARGET:
3072 current_target = Subs->Next_Target();
3073 if (drawmap)
3074 {
3075 DrawMap();
3076 // PlaceShips(mapscale, 0, -10, current_target);
3077 }
3078 SDL_Delay(100);
3079 break;
3080 case QUIT:
3081 printf("Got quit signal.\n");
3082 ResetWidgetFlags();
3083 quitwidget=1;
3084 DisplayWidgets();
3085 SDL_Delay(200);
3086 quitwidget=0;
3087 DisplayWidgets();
3088 SDL_Delay(500);
3089 quit = true;
3090 break;
3091 case COMPRESSTIME: // Make Einstein proud.
3092 destination_rectangle.x = 880; //upper left corner to
3093 destination_rectangle.y = 710; //place the button.
3094 destination_rectangle.h = plusbuttondown->h; //height &
3095 destination_rectangle.w = plusbuttondown->w;//width of button.
3096 SDL_BlitSurface(plusbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3097 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show button on the screen...
3098 timecompression++;
3099 if(timecompression > 8){
3100 timecompression = 8;
3101 }else{
3102 if (!pause_game){
3103 SDL_RemoveTimer(timer_id);
3104 SDL_RemoveTimer(timer_id2);
3105 timer_id = SDL_AddTimer(1000/timecompression, timerfunc, NULL);
3106 timer_id2 = SDL_AddTimer(60000/timecompression, TmaTimer, NULL);
3107 }
3108 sprintf(text, "[%i] ", timecompression);
3109 fnt.PutString(screen, 933, 718, text);
3110 }
3111 SDL_Delay(150);
3112 DisplayWidgets();
3113 break;
3114 case UNCOMPRESSTIME: // Take A Downer
3115 destination_rectangle.x = 970; //upper left corner to
3116 destination_rectangle.y = 710; //place the button.
3117 destination_rectangle.h = minusbuttondown->h; //height &
3118 destination_rectangle.w = minusbuttondown->w;//width of button.
3119 SDL_BlitSurface(minusbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3120 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show button on the screen...
3121 timecompression--;
3122 if(timecompression < 1){
3123 timecompression = 1;
3124 }else{
3125 if (!pause_game){
3126 SDL_RemoveTimer(timer_id);
3127 SDL_RemoveTimer(timer_id2);
3128 timer_id = SDL_AddTimer(1000/timecompression, timerfunc, NULL);
3129 timer_id2 = SDL_AddTimer(60000/timecompression, TmaTimer, NULL);
3130 }
3131 sprintf(text, "[%i] ", timecompression);
3132 fnt.PutString(screen, 933, 718, text);
3133 }
3134 SDL_Delay(150);
3135 DisplayWidgets();
3136 break;
3137 case INCREASESPEED:
3138 Subs->DesiredSpeed++;
3139 break;
3140 case DECREASESPEED:
3141 Subs->DesiredSpeed--;
3142 break;
3143 case DUMPSCREEN:
3144 screendumpcount++;
3145 sprintf(text, "screendump%i.bmp", screendumpcount );
3146 SDL_SaveBMP(screen,text); //screen dumps
3147 cerr << "Screen Dump" << endl;
3148 break;
3149 case TURNPORT:
3150 Subs->DesiredHeading--;
3151 if(Subs->DesiredHeading < 0){
3152 Subs->DesiredHeading += 360;
3153 }
3154 break;
3155 case TURNSTARBOARD:
3156 Subs->DesiredHeading++;
3157 if(Subs->DesiredHeading > 359){
3158 Subs->DesiredHeading -= 360;
3159 }
3160 break;
3161 case INCREASEDEPTH:
3162 Subs->DesiredDepth++;
3163 if (Subs->DesiredDepth > Subs->MaxDepth)
3164 Subs->DesiredDepth = Subs->MaxDepth;
3165 break;
3166 case DECREASEDEPTH:
3167 Subs->DesiredDepth--;
3168 if(Subs->DesiredDepth < 0){
3169 Subs->DesiredDepth = 0;
3170 }
3171 break;
3172 case INCREASEMAPSCALE:
3173 if (drawmap){
3174 mapscale++;
3175 if(mapscale>MAX_MAP_SCALE) mapscale=MAX_MAP_SCALE;
3176 destination_rectangle.x = 175; //upper left corner to
3177 destination_rectangle.y = 359; //place the button.
3178 destination_rectangle.h = plusbuttondown->h; //height &
3179 destination_rectangle.w = plusbuttondown->w;//width of button.
3180 SDL_BlitSurface(plusbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3181 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
3182 DrawMap();
3183 //UpdateDisplay();
3184 SDL_Delay(100);
3185 DisplayNavigationWidgets();
3186 }
3187 if(drawtma){
3188 destination_rectangle.x = 175; //upper left corner to
3189 destination_rectangle.y = 359; //place the button.
3190 destination_rectangle.h = plusbuttondown->h; //height &
3191 destination_rectangle.w = plusbuttondown->w;//width of button.
3192 SDL_BlitSurface(plusbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3193 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
3194 Tma.IncreasePlotScale();
3195 DisplayTMA();
3196 SDL_Delay(100);
3197 DisplayTMAWidgets();
3198 }
3199 break;
3200 case DECREASEMAPSCALE:
3201 if(drawmap){
3202 mapscale--;
3203 if(mapscale<1) mapscale = 1;
3204 destination_rectangle.x = 275; //upper left corner to
3205 destination_rectangle.y = 359; //place the button.
3206 destination_rectangle.h = minusbuttondown->h; //height &
3207 destination_rectangle.w = minusbuttondown->w;//width of button.
3208 SDL_BlitSurface(minusbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3209 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
3210 DrawMap();
3211 //UpdateDisplay();
3212 SDL_Delay(100);
3213 DisplayNavigationWidgets();
3214 }
3215 if(drawtma){
3216 Tma.DecreasePlotScale();
3217 destination_rectangle.x = 275; //upper left corner to
3218 destination_rectangle.y = 359; //place the button.
3219 destination_rectangle.h = minusbuttondown->h; //height &
3220 destination_rectangle.w = minusbuttondown->w;//width of button.
3221 SDL_BlitSurface(minusbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3222 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
3223 DisplayTMA();
3224 SDL_Delay(100);
3225 DisplayTMAWidgets();
3226 }
3227 break;
3228 case SCROLLMAPUP:
3229 if(drawmap){
3230 destination_rectangle.x = 225; //upper left corner to
3231 destination_rectangle.y = 219; //place the button.
3232 destination_rectangle.h = upbuttondown->h; //height &
3233 destination_rectangle.w = upbuttondown->w;//width of button.
3234 SDL_BlitSurface(upbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3235 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
3236 PlaceShips(mapscale, 0, -10, current_target);
3237 DrawMap();
3238 SDL_Delay(100);
3239 DisplayNavigationWidgets();
3240 }
3241 if(drawtma){
3242 destination_rectangle.x = 225; //upper left corner to
3243 destination_rectangle.y = 219; //place the button.
3244 destination_rectangle.h = upbuttondown->h; //height &
3245 destination_rectangle.w = upbuttondown->w;//width of button.
3246 SDL_BlitSurface(upbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3247 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
3248 PlaceShips(mapscale, 0, -10, current_target);
3249 DisplayTMA(0,-10);
3250 SDL_Delay(100);
3251 DisplayTMAWidgets();
3252 }
3253 break;
3254 case SCROLLMAPDOWN:
3255 if(drawmap){
3256 destination_rectangle.x = 225; //upper left corner to
3257 destination_rectangle.y = 319; //place the button.
3258 destination_rectangle.h = downbuttondown->h; //height &
3259 destination_rectangle.w = downbuttondown->w;//width of button.
3260 SDL_BlitSurface(downbuttondown, NULL, screen, &destination_rectangle); // Do the Blit
3261 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen..
3262 PlaceShips(mapscale, 0, 10, current_target);
3263 DrawMap();
3264 SDL_Delay(100);
3265 DisplayNavigationWidgets();
3266 }
3267 if(drawtma){
3268 destination_rectangle.x = 225; //upper left corner to
3269 destination_rectangle.y = 319; //place the button.
3270 destination_rectangle.h = downbuttondown->h; //height &
3271 destination_rectangle.w = downbuttondown->w;//width of button.
3272 SDL_BlitSurface(downbuttondown, NULL, screen, &destination_rectangle); // Do the Blit
3273 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen..
3274 PlaceShips(mapscale, 0, 10, current_target);
3275 DisplayTMA(0,10);
3276 SDL_Delay(100);
3277 DisplayTMAWidgets();
3278 }
3279 break;
3280 case SCROLLMAPLEFT:
3281 if(drawmap){
3282 destination_rectangle.x = 175; //upper left corner to
3283 destination_rectangle.y = 269; //place the button.
3284 destination_rectangle.h = leftbuttondown->h; //height &
3285 destination_rectangle.w = leftbuttondown->w;//width of button.
3286 SDL_BlitSurface(leftbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3287 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
3288 PlaceShips(mapscale, -10, 0, current_target);
3289 DrawMap();
3290 SDL_Delay(100);
3291 DisplayNavigationWidgets();
3292 }
3293 if(drawtma){
3294 destination_rectangle.x = 175; //upper left corner to
3295 destination_rectangle.y = 269; //place the button.
3296 destination_rectangle.h = leftbuttondown->h; //height &
3297 destination_rectangle.w = leftbuttondown->w;//width of button.
3298 SDL_BlitSurface(leftbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3299 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
3300 PlaceShips(mapscale, -10, 0, current_target);
3301 DisplayTMA(-10,0);
3302 SDL_Delay(100);
3303 DisplayTMAWidgets();
3304 }
3305 break;
3306 case SCROLLMAPRIGHT:
3307 if(drawmap){
3308 destination_rectangle.x = 275; //upper left corner to
3309 destination_rectangle.y = 269; //place the button.
3310 destination_rectangle.h = rightbuttondown->h; //height &
3311 destination_rectangle.w = rightbuttondown->w;//width of button.
3312 SDL_BlitSurface(rightbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3313 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
3314 PlaceShips(mapscale, 10, 0, current_target);
3315 DrawMap();
3316 SDL_Delay(100);
3317 DisplayNavigationWidgets();
3318 }
3319 if(drawtma){
3320 destination_rectangle.x = 275; //upper left corner to
3321 destination_rectangle.y = 269; //place the button.
3322 destination_rectangle.h = rightbuttondown->h; //height &
3323 destination_rectangle.w = rightbuttondown->w;//width of button.
3324 SDL_BlitSurface(rightbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3325 SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
3326 DisplayTMA(10,0);
3327 SDL_Delay(100);
3328 DisplayTMAWidgets();
3329 }
3330 break;
3331 case UP_THERMAL:
3332 if ( (player) && (my_map) )
3333 {
3334 status = my_map->Next_Up(player->Depth);
3335 if (status != player->Depth)
3336 {
3337 player->DesiredDepth = status - 25;
3338 Message.post_message("Going up one thermal.");
3339 Message.display_message();
3340 }
3341 }
3342 break;
3343 case DOWN_THERMAL:
3344 if ( (player) && (my_map) )
3345 {
3346 status = my_map->Next_Down(player->Depth);
3347 if (status != player->Depth)
3348 {
3349 player->DesiredDepth = status + 25;
3350 Message.post_message("Going down one thermal.");
3351 Message.display_message();
3352 }
3353 }
3354 break;
3355 case HOLD_DEPTH:
3356 if (player)
3357 player->DesiredDepth = player->Depth;
3358 Message.post_message("Holding depth, Captain.");
3359 Message.display_message();
3360 break;
3361 case GO_SURFACE:
3362 if (player)
3363 player->DesiredDepth = 0;
3364 Message.post_message("Surfacing, Captain!");
3365 Message.display_message();
3366 break;
3367 case GO_PERISCOPE_DEPTH:
3368 if (player)
3369 player->DesiredDepth = PERISCOPE_DEPTH;
3370 Message.post_message("Heading to periscope depth.");
3371 Message.display_message();
3372 break;
3373
3374 case TOGGLESPHERICALTOWED:
3375 SonarStation.ToggleArrayChoice();
3376 SonarStation.DisplaySonarWidgets();
3377 break;
3378 case TOGGLETRUERELATIVE:
3379 SonarStation.ToggleTrueRel();
3380 SonarStation.DisplaySonarWidgets();
3381 break;
3382 case UPPERCRTBUTTON:
3383 SonarStation.UpperCRT_Button();
3384 break;
3385 case LOWERCRTBUTTON:
3386 SonarStation.LowerCRT_Button();
3387 break;
3388 case CENTERDISPLAY:
3389 if(drawmap){
3390 if(mapcenter) {
3391 mapcenter = 0;
3392 DisplayNavigationWidgets();
3393 }else{
3394 mapcenter = 1;
3395 DisplayNavigationWidgets();
3396 }
3397 UpdateDisplay();
3398 }
3399 if(drawsonar){
3400 SonarStation.ToggleNorthCenter();
3401 SonarStation.ClearSonarData();
3402 UpdateDisplay();
3403 Message.display_message();
3404 }
3405 if(drawtma){
3406 Tma.ToggleGeoPlotCenter();
3407 DisplayTMAWidgets();
3408 UpdateDisplay();
3409 Message.display_message();
3410 }
3411 break;
3412 case EXTENDARRAY:
3413 status = TB16.Extend();
3414 if (status)
3415 {
3416 SonarStation.DisplaySonarWidgets();
3417 Message.post_message("Extending sonar array.");
3418 }
3419 else
3420 Message.post_message("Unable to extend array.");
3421 Message.display_message();
3422 break;
3423 case RETRACTARRAY:
3424 status = TB16.ReelIn();
3425 if (status)
3426 {
3427 SonarStation.DisplaySonarWidgets();
3428 Message.post_message("Retrieving sonar array.");
3429 }
3430 else
3431 Message.post_message("Unable to retrieve array.");
3432 Message.display_message();
3433 break;
3434 case CUTARRAY:
3435 status = TB16.CutArray();
3436 SonarStation.DisplaySonarWidgets();
3437 if (status)
3438 Message.post_message("Cut towed array.");
3439 else
3440 Message.post_message("Cannot cut array.");
3441 Message.display_message();
3442 break;
3443 case STOPWINCH:
3444 SonarStation.StopWinch();
3445 Message.post_message("Stopping sonar array.");
3446 Message.display_message();
3447 break;
3448 case ASSIGNTRACKER:
3449 SonarStation.ToggleAssignTracker();
3450 SonarStation.DisplaySonarWidgets();
3451 break;
3452 case TRACKER1:
3453 if(SonarStation.assigntracker){
3454 SonarStation.ToggleAssignTracker();
3455 Tma.AssignTracker(0,0);
3456 SonarStation.DisplaySonarWidgets();
3457 }
3458 break;
3459 case TRACKER2:
3460 if(SonarStation.assigntracker){
3461 SonarStation.ToggleAssignTracker();
3462 Tma.AssignTracker(1,0);
3463 SonarStation.DisplaySonarWidgets();
3464 }
3465 break;
3466 case TRACKER3:
3467 if(SonarStation.assigntracker){
3468 SonarStation.ToggleAssignTracker();
3469 Tma.AssignTracker(2,0);
3470 SonarStation.DisplaySonarWidgets();
3471 }
3472 break;
3473 case TRACKER4:
3474 if(SonarStation.assigntracker){
3475 SonarStation.ToggleAssignTracker();
3476 Tma.AssignTracker(3,0);
3477 SonarStation.DisplaySonarWidgets();
3478 }
3479 break;
3480 case DESIGNATECONTACT:
3481 // textline="CON, SONAR, NEW CONTACT BEARING 123. DESIGNATEING CONTACT S1.";
3482 // Message.post_message(textline);
3483 break;
3484 case TOGGLER10:
3485 RadarStation.ToggleRangeScale10();
3486 RadarStation.DisplayWidgets();
3487 break;
3488 case TOGGLER20:
3489 RadarStation.ToggleRangeScale20();
3490 RadarStation.DisplayWidgets();
3491 break;
3492 case TOGGLER30:
3493 RadarStation.ToggleRangeScale30();
3494 RadarStation.DisplayWidgets();
3495 break;
3496 case TOGGLER40:
3497 RadarStation.ToggleRangeScale40();
3498 RadarStation.DisplayWidgets();
3499 break;
3500 case TOGGLER50:
3501 RadarStation.ToggleRangeScale50();
3502 RadarStation.DisplayWidgets();
3503 break;
3504 case TOGGLER60:
3505 RadarStation.ToggleRangeScale60();
3506 RadarStation.DisplayWidgets();
3507 break;
3508 case RING0:
3509 RadarStation.ToggleRangeRing0();
3510 RadarStation.DisplayWidgets();
3511 break;
3512 case RING5:
3513 RadarStation.ToggleRangeRing5();
3514 RadarStation.DisplayWidgets();
3515 break;
3516 case RING10:
3517 RadarStation.ToggleRangeRing10();
3518 RadarStation.DisplayWidgets();
3519 break;
3520 case RING15:
3521 RadarStation.ToggleRangeRing15();
3522 RadarStation.DisplayWidgets();
3523 break;
3524 case RING20:
3525 RadarStation.ToggleRangeRing20();
3526 RadarStation.DisplayWidgets();
3527 break;
3528 case RING25:
3529 RadarStation.ToggleRangeRing25();
3530 RadarStation.DisplayWidgets();
3531 break;
3532 case RADARDOWN:
3533 RadarStation.LowerMast();
3534 RadarStation.DisplayWidgets();
3535 RadarStation.ClearScreen();
3536 if (player)
3537 player->using_radar = FALSE;
3538 break;
3539 case RADARUP:
3540 if (Subs->Depth <= PERISCOPE_DEPTH)
3541 {
3542 RadarStation.RaiseMast();
3543 RadarStation.DisplayWidgets();
3544 if (player)
3545 player->using_radar = TRUE;
3546 }
3547 break;
3548 case ESMDOWN:
3549 EsmStation.LowerMast();
3550 EsmStation.DisplayWidgets();
3551 EsmStation.ClearScreen();
3552 break;
3553 case ESMUP:
3554 if (Subs->Depth <= PERISCOPE_DEPTH)
3555 {
3556 EsmStation.RaiseMast();
3557 EsmStation.DisplayWidgets();
3558 }
3559 break;
3560 case ASTOP:
3561 ControlStation.ToggleASTOP();
3562 ControlStation.DisplayWidgets();
3563 break;
3564 case A13:
3565 ControlStation.ToggleA13();
3566 ControlStation.DisplayWidgets();
3567 break;
3568 case A23:
3569 ControlStation.ToggleA23();
3570 ControlStation.DisplayWidgets();
3571 break;
3572 case ASTD:
3573 ControlStation.ToggleASTD();
3574 ControlStation.DisplayWidgets();
3575 break;
3576 case AFULL:
3577 ControlStation.ToggleAFULL();
3578 ControlStation.DisplayWidgets();
3579 break;
3580 case AFLK:
3581 ControlStation.ToggleAFLK();
3582 ControlStation.DisplayWidgets();
3583 break;
3584 case B13:
3585 ControlStation.ToggleB13();
3586 ControlStation.DisplayWidgets();
3587 break;
3588 case B23:
3589 ControlStation.ToggleB23();
3590 ControlStation.DisplayWidgets();
3591 break;
3592 case BSTD:
3593 ControlStation.ToggleBSTD();
3594 ControlStation.DisplayWidgets();
3595 break;
3596 case BEMER:
3597 ControlStation.ToggleBEMER();
3598 ControlStation.DisplayWidgets();
3599 break;
3600 case SEND_PING:
3601 player->Send_Ping(Subs);
3602 Message.post_message("Sending active ping, sir.");
3603 Message.display_message();
3604 break;
3605 case USE_TUBE:
3606 // check to see if we already have too
3607 // many items out there
3608 status = player->Count_Torpedoes(torpedoes);
3609 status += player->Count_Noisemakers(torpedoes);
3610 if (status >= MAX_PLAYER_WEAPONS)
3611 {
3612 Message.post_message("Tracking computer full, Captain.");
3613 Message.display_message();
3614 break;
3615 }
3616 // load, fire or unload a tube
3617 status = Subs->Use_Tube(tube_action, tube_to_use);
3618 if (status == TUBE_ERROR_FIRE_NOISEMAKER)
3619 {
3620 Submarine *new_torpedo, *my_torp;
3621 char *ship_file, filename[] = "ships/class6.shp";
3622 ship_file = Find_Data_File(filename);
3623 new_torpedo = Subs->Fire_Tube(NULL, ship_file);
3624 if ( (ship_file) && (ship_file != filename) )
3625 free(ship_file);
3626 if (new_torpedo)
3627 {
3628 new_torpedo->Friend = player->Friend;
3629 new_torpedo->owner = player;
3630 torpedoes = Add_Ship(torpedoes, new_torpedo);
3631 Message.post_message("Noise maker launched!");
3632 Message.display_message();
3633 my_torp = torpedoes;
3634 while (my_torp)
3635 {
3636 if (my_torp->target == player)
3637 my_torp->Is_Distracted_By_Noisemaker(new_torpedo);
3638 my_torp = my_torp->next;
3639 }
3640 }
3641 }
3642 else if ( (status == TUBE_ERROR_FIRE_SUCCESS) && (current_target) )
3643 {
3644 char *ship_file, filename[] = "ships/class5.shp";
3645 ship_file = Find_Data_File(filename);
3646 if (current_target)
3647 {
3648 Submarine *new_torpedo;
3649 new_torpedo = Subs->Fire_Tube(current_target, ship_file );
3650 if ( (ship_file) && (ship_file != filename) )
3651 free(ship_file);
3652 if (new_torpedo)
3653 {
3654 char *sound_file, *file_name = "sounds/torpedo-launch.ogg";
3655 sound_file = Find_Data_File(file_name);
3656 Play_Sound(sound_file);
3657 if ( (sound_file) && (sound_file != file_name) )
3658 free(sound_file);
3659 new_torpedo->Friend = FRIEND;
3660 new_torpedo->owner = Subs;
3661 torpedoes = Add_Ship(torpedoes, new_torpedo);
3662 Message.post_message("Torpedo launched!");
3663 Message.display_message();
3664 }
3665 }
3666 }
3667 else if (status == TUBE_ERROR_FIRE_SUCCESS)
3668 {
3669 Message.post_message("Torpedo has no target.");
3670 Message.display_message();
3671 Subs->TorpedosOnBoard++;
3672 }
3673
3674
3675 tube_action = 0;
3676 tube_to_use = -1;
3677 update_weapons_screen = TRUE;
3678 UpdateDisplay();
3679 break;
3680 case PAUSEGAME:
3681 if (pause_game){ //UnPause
3682 pause_game = !pause_game;
3683 timer_id = SDL_AddTimer(1000/timecompression, timerfunc, NULL);
3684 timer_id2 = SDL_AddTimer(60000/timecompression, TmaTimer, NULL);
3685 }else{ //Pause
3686 pause_game = !pause_game;
3687 SDL_RemoveTimer(timer_id);
3688 SDL_RemoveTimer(timer_id2);
3689 }
3690 break;
3691 default:
3692 break;
3693 }
3694 }
3695 /*
3696 if (timer2 < (SDL_GetTicks() - (1000/timecompression) ) )
3697 {
3698 #ifdef DEBUG
3699 printf("Launching timer function.\n");
3700 #endif
3701 // timerfunc(0, NULL);
3702 timer2 = SDL_GetTicks();
3703 }
3704 */
3705 if (should_update_everything)
3706 {
3707 should_update_everything = FALSE;
3708 Update_Everything();
3709 }
3710 if (my_mission_status == MISSION_SUCCESS)
3711 {
3712 printf("Mission completed successfully!\n");
3713 LoadScreen(7);
3714 SDL_Delay(5000);
3715 quit = true;
3716 }
3717 else if (my_mission_status == MISSION_FAILED)
3718 {
3719 printf("Mission failed.\n");
3720 LoadScreen(8);
3721 SDL_Delay(5000);
3722 quit = true;
3723 }
3724
3725 SDL_Delay(GAME_DELAY);
3726 } // end of main loop
3727 #ifdef DEBUG
3728 printf("Unloading widgets.\n");
3729 #endif
3730 UnLoadWidgets();
3731 // get rid of torpedoes
3732 #ifdef DEBUG
3733 printf("Destroying torpedoes\n");
3734 #endif
3735 while (torpedoes)
3736 torpedoes = Remove_Ship(torpedoes, torpedoes);
3737 #ifdef DEBUG
3738 printf("Destroying subs\n");
3739 #endif
3740 while (Subs)
3741 Subs = Remove_Ship(Subs, Subs);
3742 #ifdef DEBUG
3743 printf("Removing helicopters.\n");
3744 #endif
3745 while (helicopters)
3746 helicopters = Remove_Helicopter(helicopters, helicopters);
3747 #ifdef DEBUG
3748 printf("Killing SDL\n");
3749 #endif
3750 Clean_Up_Audio();
3751 if (my_map)
3752 delete my_map;
3753 SDL_Quit();
3754 return 0; // just to make the compiler happy
3755 }
3756
3757