Proper Subversion configuration.
[newkind] / space.c
CommitLineData
84bbd123 1/*
2 * Elite - The New Kind.
3 *
4 * Reverse engineered from the BBC disk version of Elite.
5 * Additional material by C.J.Pinder.
6 *
7 * The original Elite code is (C) I.Bell & D.Braben 1984.
8 * This version re-engineered in C by C.J.Pinder 1999-2001.
9 *
10 * email: <christian@newkind.co.uk>
11 *
12 *
13 */
14
15/*
16 * space.c
17 *
18 * This module handles all the flight system and management of the space universe.
19 */
20
21#include <stdio.h>
22#include <string.h>
23#include <math.h>
24#include <stdlib.h>
25
26#include "vector.h"
27
28#include "alg_data.h"
29
30#include "config.h"
31#include "elite.h"
4c1c1a84 32#include "keyboard.h"
84bbd123 33#include "gfx.h"
34#include "docked.h"
35#include "intro.h"
36#include "shipdata.h"
37#include "shipface.h"
38#include "space.h"
39#include "threed.h"
40#include "sound.h"
41#include "main.h"
42#include "swat.h"
43#include "random.h"
44#include "trade.h"
45#include "stars.h"
46#include "pilot.h"
47
48extern int flight_climb;
49extern int flight_roll;
50extern int flight_speed;
51
52struct galaxy_seed destination_planet;
53int hyper_ready;
54int hyper_countdown;
55char hyper_name[16];
56int hyper_distance;
57int hyper_galactic;
58
59
60
61
62
63
64void rotate_x_first (double *a, double *b, int direction)
65{
66 double fx,ux;
67
68 fx = *a;
69 ux = *b;
70
71 if (direction < 0)
72 {
73 *a = fx - (fx / 512) + (ux / 19);
74 *b = ux - (ux / 512) - (fx / 19);
75 }
76 else
77 {
78 *a = fx - (fx / 512) - (ux / 19);
79 *b = ux - (ux / 512) + (fx / 19);
80 }
81}
82
83
84void rotate_vec (struct vector *vec, double alpha, double beta)
85{
86 double x,y,z;
87
88 x = vec->x;
89 y = vec->y;
90 z = vec->z;
91
92 y = y - alpha * x;
93 x = x + alpha * y;
94 y = y - beta * z;
95 z = z + beta * y;
96
97 vec->x = x;
98 vec->y = y;
99 vec->z = z;
100}
101
102
103/*
104 * Update an objects location in the universe.
105 */
106
107void move_univ_object (struct univ_object *obj)
108{
109 double x,y,z;
110 double k2;
111 double alpha;
112 double beta;
113 int rotx,rotz;
114 double speed;
115
116 alpha = flight_roll / 256.0;
117 beta = flight_climb / 256.0;
118
119 x = obj->location.x;
120 y = obj->location.y;
121 z = obj->location.z;
122
123 if (!(obj->flags & FLG_DEAD))
124 {
125 if (obj->velocity != 0)
126 {
127 speed = obj->velocity;
128 speed *= 1.5;
129 x += obj->rotmat[2].x * speed;
130 y += obj->rotmat[2].y * speed;
131 z += obj->rotmat[2].z * speed;
132 }
133
134 if (obj->acceleration != 0)
135 {
136 obj->velocity += obj->acceleration;
137 obj->acceleration = 0;
138 if (obj->velocity > ship_list[obj->type]->velocity)
139 obj->velocity = ship_list[obj->type]->velocity;
140
141 if (obj->velocity <= 0)
142 obj->velocity = 1;
143 }
144 }
145
146 k2 = y - alpha * x;
147 z = z + beta * k2;
148 y = k2 - z * beta;
149 x = x + alpha * y;
150
151 z = z - flight_speed;
152
153 obj->location.x = x;
154 obj->location.y = y;
155 obj->location.z = z;
156
157 obj->distance = sqrt (x*x + y*y + z*z);
158
159 if (obj->type == SHIP_PLANET)
160 beta = 0.0;
161
162 rotate_vec (&obj->rotmat[2], alpha, beta);
163 rotate_vec (&obj->rotmat[1], alpha, beta);
164 rotate_vec (&obj->rotmat[0], alpha, beta);
165
166 if (obj->flags & FLG_DEAD)
167 return;
168
169
170 rotx = obj->rotx;
171 rotz = obj->rotz;
172
173 /* If necessary rotate the object around the X axis... */
174
175 if (rotx != 0)
176 {
177 rotate_x_first (&obj->rotmat[2].x, &obj->rotmat[1].x, rotx);
178 rotate_x_first (&obj->rotmat[2].y, &obj->rotmat[1].y, rotx);
179 rotate_x_first (&obj->rotmat[2].z, &obj->rotmat[1].z, rotx);
180
181 if ((rotx != 127) && (rotx != -127))
182 obj->rotx -= (rotx < 0) ? -1 : 1;
183 }
184
185
186 /* If necessary rotate the object around the Z axis... */
187
188 if (rotz != 0)
189 {
190 rotate_x_first (&obj->rotmat[0].x, &obj->rotmat[1].x, rotz);
191 rotate_x_first (&obj->rotmat[0].y, &obj->rotmat[1].y, rotz);
192 rotate_x_first (&obj->rotmat[0].z, &obj->rotmat[1].z, rotz);
193
194 if ((rotz != 127) && (rotz != -127))
195 obj->rotz -= (rotz < 0) ? -1 : 1;
196 }
197
198
199 /* Orthonormalize the rotation matrix... */
200
201 tidy_matrix (obj->rotmat);
202}
203
204
205/*
206 * Dock the player into the space station.
207 */
208
209void dock_player (void)
210{
211 disengage_auto_pilot();
212 docked = 1;
213 flight_speed = 0;
214 flight_roll = 0;
215 flight_climb = 0;
216 front_shield = 255;
217 aft_shield = 255;
218 energy = 255;
219 myship.altitude = 255;
220 myship.cabtemp = 30;
221 reset_weapons();
222}
223
224
225/*
226 * Check if we are correctly aligned to dock.
227 */
228
229int is_docking (int sn)
230{
231 struct vector vec;
232 double fz;
233 double ux;
234
4c1c1a84 235 if (universe[sn].flags & FLG_ANGRY)
236 return (0);
237
84bbd123 238 if (auto_pilot) // Don't want it to kill anyone!
239 return 1;
240
241 fz = universe[sn].rotmat[2].z;
242
243 if (fz > -0.90)
244 return 0;
245
246 vec = unit_vector (&universe[sn].location);
247
248 if (vec.z < 0.927)
249 return 0;
250
251 ux = universe[sn].rotmat[1].x;
252 if (ux < 0)
253 ux = -ux;
254
255 if (ux < 0.84)
256 return 0;
257
258 return 1;
259}
260
261
262/*
263 * Game Over...
264 */
265
266void do_game_over (void)
267{
268 snd_play_sample (SND_GAMEOVER);
269 game_over = 1;
270}
271
272
273void update_altitude (void)
274{
275 double x,y,z;
276 double dist;
277
278 myship.altitude = 255;
279
280 if (witchspace)
281 return;
282
283 x = fabs(universe[0].location.x);
284 y = fabs(universe[0].location.y);
285 z = fabs(universe[0].location.z);
286
287 if ((x > 65535) || (y > 65535) || (z > 65535))
288 return;
289
290 x /= 256;
291 y /= 256;
292 z /= 256;
293
294 dist = (x * x) + (y * y) + (z * z);
295
296 if (dist > 65535)
297 return;
298
299 dist -= 9472;
300 if (dist < 1)
301 {
302 myship.altitude = 0;
303 do_game_over ();
304 return;
305 }
306
307 dist = sqrt (dist);
308 if (dist < 1)
309 {
310 myship.altitude = 0;
311 do_game_over ();
312 return;
313 }
314
315 myship.altitude = dist;
316}
317
318
319void update_cabin_temp (void)
320{
321 int x,y,z;
322 int dist;
323
324 myship.cabtemp = 30;
325
326 if (witchspace)
327 return;
328
329 if (ship_count[SHIP_CORIOLIS] || ship_count[SHIP_DODEC])
330 return;
331
332 x = abs((int)universe[1].location.x);
333 y = abs((int)universe[1].location.y);
334 z = abs((int)universe[1].location.z);
335
336 if ((x > 65535) || (y > 65535) || (z > 65535))
337 return;
338
339 x /= 256;
340 y /= 256;
341 z /= 256;
342
343 dist = ((x * x) + (y * y) + (z * z)) / 256;
344
345 if (dist > 255)
346 return;
347
348 dist ^= 255;
349
350 myship.cabtemp = dist + 30;
351
352 if (myship.cabtemp > 255)
353 {
354 myship.cabtemp = 255;
355 do_game_over ();
356 return;
357 }
358
359 if ((myship.cabtemp < 224) || (cmdr.fuel_scoop == 0))
360 return;
361
362 cmdr.fuel += flight_speed / 2;
363 if (cmdr.fuel > myship.max_fuel)
364 cmdr.fuel = myship.max_fuel;
365
366 info_message ("Fuel Scoop On");
367}
368
369
370
371/*
372 * Regenerate the shields and the energy banks.
373 */
374
375void regenerate_shields (void)
376{
377 if (energy > 127)
378 {
379 if (front_shield < 255)
380 {
381 front_shield++;
382 energy--;
383 }
384
385 if (aft_shield < 255)
386 {
387 aft_shield++;
388 energy--;
389 }
390 }
391
392 energy++;
393 energy += cmdr.energy_unit;
394 if (energy > 255)
395 energy = 255;
396}
397
398
399void decrease_energy (int amount)
400{
401 energy += amount;
402
403 if (energy <= 0)
404 do_game_over();
405}
406
407
408/*
409 * Deplete the shields. Drain the energy banks if the shields fail.
410 */
411
412void damage_ship (int damage, int front)
413{
414 int shield;
415
416 if (damage <= 0) /* sanity check */
417 return;
418
419 shield = front ? front_shield : aft_shield;
420
421 shield -= damage;
422 if (shield < 0)
423 {
424 decrease_energy (shield);
425 shield = 0;
426 }
427
428 if (front)
429 front_shield = shield;
430 else
431 aft_shield = shield;
432}
433
434
435
436
437void make_station_appear (void)
438{
439 double px,py,pz;
440 double sx,sy,sz;
441 Vector vec;
442 Matrix rotmat;
443
444 px = universe[0].location.x;
445 py = universe[0].location.y;
446 pz = universe[0].location.z;
447
448 vec.x = (rand() & 32767) - 16384;
449 vec.y = (rand() & 32767) - 16384;
450 vec.z = rand() & 32767;
451
452 vec = unit_vector (&vec);
453
454 sx = px - vec.x * 65792;
455 sy = py - vec.y * 65792;
456 sz = pz - vec.z * 65792;
457
458// set_init_matrix (rotmat);
459
460 rotmat[0].x = 1.0;
461 rotmat[0].y = 0.0;
462 rotmat[0].z = 0.0;
463
464 rotmat[1].x = vec.x;
465 rotmat[1].y = vec.z;
466 rotmat[1].z = -vec.y;
467
468 rotmat[2].x = vec.x;
469 rotmat[2].y = vec.y;
470 rotmat[2].z = vec.z;
471
472 tidy_matrix (rotmat);
473
474 add_new_station (sx, sy, sz, rotmat);
475}
476
477
478
479void check_docking (int i)
480{
481 if (is_docking(i))
482 {
483 snd_play_sample (SND_DOCK);
484 dock_player();
485 current_screen = SCR_BREAK_PATTERN;
486 return;
487 }
488
489 if (flight_speed >= 5)
490 {
491 do_game_over();
492 return;
493 }
494
495 flight_speed = 1;
496 damage_ship (5, universe[i].location.z > 0);
497 snd_play_sample (SND_CRASH);
498}
499
500
501void switch_to_view (struct univ_object *flip)
502{
503 double tmp;
504
505 if ((current_screen == SCR_REAR_VIEW) ||
506 (current_screen == SCR_GAME_OVER))
507 {
508 flip->location.x = -flip->location.x;
509 flip->location.z = -flip->location.z;
510
511 flip->rotmat[0].x = -flip->rotmat[0].x;
512 flip->rotmat[0].z = -flip->rotmat[0].z;
513
514 flip->rotmat[1].x = -flip->rotmat[1].x;
515 flip->rotmat[1].z = -flip->rotmat[1].z;
516
517 flip->rotmat[2].x = -flip->rotmat[2].x;
518 flip->rotmat[2].z = -flip->rotmat[2].z;
519 return;
520 }
521
522
523 if (current_screen == SCR_LEFT_VIEW)
524 {
525 tmp = flip->location.x;
526 flip->location.x = flip->location.z;
527 flip->location.z = -tmp;
528
529 if (flip->type < 0)
530 return;
531
532 tmp = flip->rotmat[0].x;
533 flip->rotmat[0].x = flip->rotmat[0].z;
534 flip->rotmat[0].z = -tmp;
535
536 tmp = flip->rotmat[1].x;
537 flip->rotmat[1].x = flip->rotmat[1].z;
538 flip->rotmat[1].z = -tmp;
539
540 tmp = flip->rotmat[2].x;
541 flip->rotmat[2].x = flip->rotmat[2].z;
542 flip->rotmat[2].z = -tmp;
543 return;
544 }
545
546 if (current_screen == SCR_RIGHT_VIEW)
547 {
548 tmp = flip->location.x;
549 flip->location.x = -flip->location.z;
550 flip->location.z = tmp;
551
552 if (flip->type < 0)
553 return;
554
555 tmp = flip->rotmat[0].x;
556 flip->rotmat[0].x = -flip->rotmat[0].z;
557 flip->rotmat[0].z = tmp;
558
559 tmp = flip->rotmat[1].x;
560 flip->rotmat[1].x = -flip->rotmat[1].z;
561 flip->rotmat[1].z = tmp;
562
563 tmp = flip->rotmat[2].x;
564 flip->rotmat[2].x = -flip->rotmat[2].z;
565 flip->rotmat[2].z = tmp;
566
567 }
568}
569
570
571/*
572 * Update all the objects in the universe and render them.
573 */
574
575void update_universe (void)
576{
577 int i;
578 int type;
579 int bounty;
580 char str[80];
581 struct univ_object flip;
582
583
584 gfx_start_render();
585
586 for (i = 0; i < MAX_UNIV_OBJECTS; i++)
587 {
588 type = universe[i].type;
589
590 if (type != 0)
591 {
592 if (universe[i].flags & FLG_REMOVE)
593 {
4c1c1a84 594 if (!(universe[i].flags & FLG_TARGET))
84bbd123 595 cmdr.legal_status |= 64;
596
597 bounty = ship_list[type]->bounty;
598
599 if ((bounty != 0) && (!witchspace))
600 {
601 cmdr.credits += bounty;
1a8abebd 602 sprintf (str, "Bounty: %d.%d CR", bounty / 10, bounty % 10);
84bbd123 603 info_message (str);
604 }
605
606 remove_ship (i);
607 continue;
608 }
609
610 if ((detonate_bomb) && ((universe[i].flags & FLG_DEAD) == 0) &&
611 (type != SHIP_PLANET) && (type != SHIP_SUN) &&
612 (type != SHIP_CONSTRICTOR) && (type != SHIP_COUGAR) &&
613 (type != SHIP_CORIOLIS) && (type != SHIP_DODEC))
614 {
615 snd_play_sample (SND_EXPLODE);
616 universe[i].flags |= FLG_DEAD;
617 }
618
619 if ((current_screen != SCR_INTRO_ONE) &&
620 (current_screen != SCR_INTRO_TWO) &&
621 (current_screen != SCR_GAME_OVER) &&
622 (current_screen != SCR_ESCAPE_POD))
623 {
624 tactics (i);
625 }
626
627 move_univ_object (&universe[i]);
628
629 flip = universe[i];
630 switch_to_view (&flip);
631
632 if (type == SHIP_PLANET)
633 {
634 if ((ship_count[SHIP_CORIOLIS] == 0) &&
635 (ship_count[SHIP_DODEC] == 0) &&
636 (universe[i].distance < 65792)) // was 49152
637 {
638 make_station_appear();
639 }
640
641 draw_ship (&flip);
642 continue;
643 }
644
645 if (type == SHIP_SUN)
646 {
647 draw_ship (&flip);
648 continue;
649 }
650
651
652 if (universe[i].distance < 170)
653 {
654 if ((type == SHIP_CORIOLIS) || (type == SHIP_DODEC))
655 check_docking (i);
656 else
657 scoop_item(i);
658
659 continue;
660 }
661
662 if (universe[i].distance > 57344)
663 {
664 remove_ship (i);
665 continue;
666 }
667
668 draw_ship (&flip);
669
670 universe[i].flags = flip.flags;
671 universe[i].exp_seed = flip.exp_seed;
672 universe[i].exp_delta = flip.exp_delta;
673
674 universe[i].flags &= ~FLG_FIRING;
675
676 if (universe[i].flags & FLG_DEAD)
677 continue;
678
679 check_target (i, &flip);
680 }
681 }
682
683 gfx_finish_render();
684 detonate_bomb = 0;
685}
686
687
688
689
690/*
691 * Update the scanner and draw all the lollipops.
692 */
693
694void update_scanner (void)
695{
696 int i;
697 int x,y,z;
698 int x1,y1,y2;
699 int colour;
700
701 for (i = 0; i < MAX_UNIV_OBJECTS; i++)
702 {
703 if ((universe[i].type <= 0) ||
704 (universe[i].flags & FLG_DEAD) ||
705 (universe[i].flags & FLG_CLOAKED))
706 continue;
707
1a8abebd 708 x = universe[i].location.x * scanner_zoom / 256;
709 y = universe[i].location.y * scanner_zoom / 256;
710 z = universe[i].location.z * scanner_zoom / 256;
84bbd123 711
712 x1 = x;
713 y1 = -z / 4;
714 y2 = y1 - y / 2;
715
716 if ((y2 < -28) || (y2 > 28) ||
717 (x1 < -50) || (x1 > 50))
718 continue;
719
720 x1 += scanner_cx;
721 y1 += scanner_cy;
722 y2 += scanner_cy;
723
724 colour = (universe[i].flags & FLG_HOSTILE) ? GFX_COL_YELLOW_5 : GFX_COL_WHITE;
725
726 switch (universe[i].type)
727 {
728 case SHIP_MISSILE:
729 colour = 137;
730 break;
731
732 case SHIP_DODEC:
733 case SHIP_CORIOLIS:
734 colour = GFX_COL_GREEN_1;
735 break;
736
737 case SHIP_VIPER:
738 colour = 252;
739 break;
740 }
741
742 gfx_draw_colour_line (x1+2, y2, x1-3, y2, colour);
743 gfx_draw_colour_line (x1+2, y2+1, x1-3, y2+1, colour);
744 gfx_draw_colour_line (x1+2, y2+2, x1-3, y2+2, colour);
745 gfx_draw_colour_line (x1+2, y2+3, x1-3, y2+3, colour);
746
747
748 gfx_draw_colour_line (x1, y1, x1, y2, colour);
749 gfx_draw_colour_line (x1+1, y1, x1+1, y2, colour);
750 gfx_draw_colour_line (x1+2, y1, x1+2, y2, colour);
751 }
752}
753
754
755/*
756 * Update the compass which tracks the space station / planet.
757 */
758
759void update_compass (void)
760{
761 struct vector dest;
762 int compass_x;
763 int compass_y;
764 int un = 0;
765
766 if (witchspace)
767 return;
768
769 if (ship_count[SHIP_CORIOLIS] || ship_count[SHIP_DODEC])
770 un = 1;
771
772 dest = unit_vector (&universe[un].location);
773
774 compass_x = compass_centre_x + (dest.x * 16);
775 compass_y = compass_centre_y + (dest.y * -16);
776
777 if (dest.z < 0)
778 {
779 gfx_draw_sprite (IMG_RED_DOT, compass_x, compass_y);
780 }
781 else
782 {
783 gfx_draw_sprite (IMG_GREEN_DOT, compass_x, compass_y);
784 }
785
786}
787
788
789/*
790 * Display the speed bar.
791 */
792
793void display_speed (void)
794{
795 int sx,sy;
796 int i;
797 int len;
798 int colour;
799
800 sx = 417;
801 sy = 384 + 9;
802
803 len = ((flight_speed * 64) / myship.max_speed) - 1;
804
805 colour = (flight_speed > (myship.max_speed * 2 / 3)) ? GFX_COL_DARK_RED : GFX_COL_GOLD;
806
807 for (i = 0; i < 6; i++)
808 {
809 gfx_draw_colour_line (sx, sy + i, sx + len, sy + i, colour);
810 }
811}
812
813
814/*
815 * Draw an indicator bar.
816 * Used for shields and energy banks.
817 */
818
819void display_dial_bar (int len, int x, int y)
820{
821 int i = 0;
822
823 gfx_draw_colour_line (x, y + 384, x + len, y + 384, GFX_COL_GOLD);
824 i++;
825 gfx_draw_colour_line (x, y + i + 384, x + len, y + i + 384, GFX_COL_GOLD);
826
827 for (i = 2; i < 7; i++)
828 gfx_draw_colour_line (x, y + i + 384, x + len, y + i + 384, GFX_COL_YELLOW_1);
829
830 gfx_draw_colour_line (x, y + i + 384, x + len, y + i + 384, GFX_COL_DARK_RED);
831}
832
833
834/*
835 * Display the current shield strengths.
836 */
837
838void display_shields (void)
839{
840 if (front_shield > 3)
841 display_dial_bar (front_shield / 4, 31, 7);
842
843 if (aft_shield > 3)
844 display_dial_bar (aft_shield / 4, 31, 23);
845}
846
847
848void display_altitude (void)
849{
850 if (myship.altitude > 3)
851 display_dial_bar (myship.altitude / 4, 31, 92);
852}
853
854void display_cabin_temp (void)
855{
856 if (myship.cabtemp > 3)
857 display_dial_bar (myship.cabtemp / 4, 31, 60);
858}
859
860
861void display_laser_temp (void)
862{
863 if (laser_temp > 0)
864 display_dial_bar (laser_temp / 4, 31, 76);
865}
866
867
868/*
869 * Display the energy banks.
870 */
871
872void display_energy (void)
873{
874 int e1,e2,e3,e4;
875
876 e1 = energy > 64 ? 64 : energy;
877 e2 = energy > 128 ? 64 : energy - 64;
878 e3 = energy > 192 ? 64 : energy - 128;
879 e4 = energy - 192;
880
881 if (e4 > 0)
882 display_dial_bar (e4, 416, 61);
883
884 if (e3 > 0)
885 display_dial_bar (e3, 416, 79);
886
887 if (e2 > 0)
888 display_dial_bar (e2, 416, 97);
889
890 if (e1 > 0)
891 display_dial_bar (e1, 416, 115);
892}
893
894
895
896void display_flight_roll (void)
897{
898 int sx,sy;
899 int i;
900 int pos;
901
902 sx = 416;
903 sy = 384 + 9 + 14;
904
905 pos = sx - ((flight_roll * 28) / myship.max_roll);
906 pos += 32;
907
908 for (i = 0; i < 4; i++)
909 {
910 gfx_draw_colour_line (pos + i, sy, pos + i, sy + 7, GFX_COL_GOLD);
911 }
912}
913
914void display_flight_climb (void)
915{
916 int sx,sy;
917 int i;
918 int pos;
919
920 sx = 416;
921 sy = 384 + 9 + 14 + 16;
922
923 pos = sx + ((flight_climb * 28) / myship.max_climb);
924 pos += 32;
925
926 for (i = 0; i < 4; i++)
927 {
928 gfx_draw_colour_line (pos + i, sy, pos + i, sy + 7, GFX_COL_GOLD);
929 }
930}
931
932
933void display_fuel (void)
934{
935 if (cmdr.fuel > 0)
936 display_dial_bar ((cmdr.fuel * 64) / myship.max_fuel, 31, 44);
937}
938
939
940void display_missiles (void)
941{
942 int nomiss;
943 int x,y;
944
945 if (cmdr.missiles == 0)
946 return;
947
948 nomiss = cmdr.missiles > 4 ? 4 : cmdr.missiles;
949
950 x = (4 - nomiss) * 16 + 35;
951 y = 113 + 385;
952
953 if (missile_target != MISSILE_UNARMED)
954 {
955 gfx_draw_sprite ((missile_target < 0) ? IMG_MISSILE_YELLOW :
956 IMG_MISSILE_RED, x, y);
957 x += 16;
958 nomiss--;
959 }
960
961 for (; nomiss > 0; nomiss--)
962 {
963 gfx_draw_sprite (IMG_MISSILE_GREEN, x, y);
964 x += 16;
965 }
966}
967
968
1a8abebd 969
970void display_condition(void)
971{
972 static const int cc[] = { GFX_COL_BLACK, GFX_COL_GREEN_1, GFX_COL_YELLOW_1,
973 GFX_COL_RED, GFX_COL_RED };
974 int c = cc[condition];
975 if (condition == COND_ALERT && (mcount & 4))
976 c = GFX_COL_BLACK;
977 gfx_draw_filled_circle(condition_x, condition_y, condition_r, c);
978}
979
84bbd123 980void update_console (void)
981{
84bbd123 982 gfx_draw_scanner();
983
984 display_speed();
985 display_flight_climb();
986 display_flight_roll();
987 display_shields();
988 display_altitude();
989 display_energy();
990 display_cabin_temp();
991 display_laser_temp();
992 display_fuel();
993 display_missiles();
1a8abebd 994 update_condition();
84bbd123 995
1a8abebd 996 if (docked) {
997 gfx_set_clip_region (0, 0, 512, 512);
998 return;
999 }
84bbd123 1000
1001 update_scanner();
1002 update_compass();
1a8abebd 1003 display_condition();
1004
1005 {
1006 char buf[5];
1007 sprintf(buf, "x%d", scanner_zoom);
1008 gfx_display_text(zoom_x, zoom_y, buf);
1009 }
84bbd123 1010
1011 if (ship_count[SHIP_CORIOLIS] || ship_count[SHIP_DODEC])
1012 gfx_draw_sprite (IMG_BIG_S, 387, 490);
1013
1014 if (ecm_active)
1015 gfx_draw_sprite (IMG_BIG_E, 115, 490);
1a8abebd 1016
1017 gfx_set_clip_region (0, 0, 512, 512);
84bbd123 1018}
1019
1020void increase_flight_roll (void)
1021{
1022 if (flight_roll < myship.max_roll)
1023 flight_roll++;
1024}
1025
1026
1027void decrease_flight_roll (void)
1028{
1029 if (flight_roll > -myship.max_roll)
1030 flight_roll--;
1031}
1032
1033
1034void increase_flight_climb (void)
1035{
1036 if (flight_climb < myship.max_climb)
1037 flight_climb++;
1038}
1039
1040void decrease_flight_climb (void)
1041{
1042 if (flight_climb > -myship.max_climb)
1043 flight_climb--;
1044}
1045
1046
1047void start_hyperspace (void)
1048{
1049 if (hyper_ready)
1050 return;
1051
1052 hyper_distance = calc_distance_to_planet (docked_planet, hyperspace_planet);
1053
1a8abebd 1054 if ((docked_planet.a == hyperspace_planet.a &&
1055 docked_planet.b == hyperspace_planet.b &&
1056 docked_planet.c == hyperspace_planet.c &&
1057 docked_planet.d == hyperspace_planet.d &&
1058 docked_planet.e == hyperspace_planet.e &&
1059 docked_planet.f == hyperspace_planet.f) ||
1060 (hyper_distance > cmdr.fuel))
84bbd123 1061 return;
1062
1063 destination_planet = hyperspace_planet;
1064 name_planet (hyper_name, destination_planet);
1065 capitalise_name (hyper_name);
1066
1067 hyper_ready = 1;
1068 hyper_countdown = 15;
1069 hyper_galactic = 0;
1070
1071 disengage_auto_pilot();
1072}
1073
1074void start_galactic_hyperspace (void)
1075{
1076 if (hyper_ready)
1077 return;
1078
1079 if (cmdr.galactic_hyperdrive == 0)
1080 return;
1081
1082 hyper_ready = 1;
1083 hyper_countdown = 2;
1084 hyper_galactic = 1;
1085 disengage_auto_pilot();
1086}
1087
1088
1089
1090void display_hyper_status (void)
1091{
1092 char str[80];
1093
1094 sprintf (str, "%d", hyper_countdown);
1095
1096 if ((current_screen == SCR_FRONT_VIEW) || (current_screen == SCR_REAR_VIEW) ||
1097 (current_screen == SCR_LEFT_VIEW) || (current_screen == SCR_RIGHT_VIEW))
1098 {
1099 gfx_display_text (5, 5, str);
1100 if (hyper_galactic)
1101 {
1102 gfx_display_centre_text (358, "Galactic Hyperspace", 120, GFX_COL_WHITE);
1103 }
1104 else
1105 {
1106 sprintf (str, "Hyperspace - %s", hyper_name);
1107 gfx_display_centre_text (358, str, 120, GFX_COL_WHITE);
1108 }
1109 }
1110 else
1111 {
1112 gfx_clear_area (5, 5, 25, 34);
1113 gfx_display_text (5, 5, str);
1114 }
1115}
1116
1117
1118int rotate_byte_left (int x)
1119{
1120 return ((x << 1) | (x >> 7)) & 255;
1121}
1122
1123void enter_next_galaxy (void)
1124{
1125 cmdr.galaxy_number++;
1126 cmdr.galaxy_number &= 7;
1127
1128 cmdr.galaxy.a = rotate_byte_left (cmdr.galaxy.a);
1129 cmdr.galaxy.b = rotate_byte_left (cmdr.galaxy.b);
1130 cmdr.galaxy.c = rotate_byte_left (cmdr.galaxy.c);
1131 cmdr.galaxy.d = rotate_byte_left (cmdr.galaxy.d);
1132 cmdr.galaxy.e = rotate_byte_left (cmdr.galaxy.e);
1133 cmdr.galaxy.f = rotate_byte_left (cmdr.galaxy.f);
1134
1135 docked_planet = find_planet (0x60, 0x60);
1136 hyperspace_planet = docked_planet;
1137}
1138
1139
1140
1141
1142
1143void enter_witchspace (void)
1144{
1145 int i;
1146 int nthg;
1147
1148 witchspace = 1;
1149 docked_planet.b ^= 31;
1150 in_battle = 1;
1151
1152 flight_speed = 12;
1153 flight_roll = 0;
1154 flight_climb = 0;
1155 create_new_stars();
1156 clear_universe();
1157
1158 nthg = (randint() & 3) + 1;
1159
1160 for (i = 0; i < nthg; i++)
1161 create_thargoid();
1162
1163 current_screen = SCR_BREAK_PATTERN;
1164 snd_play_sample (SND_HYPERSPACE);
1165}
1166
1167
1168void complete_hyperspace (void)
1169{
1170 Matrix rotmat;
1171 int px,py,pz;
1172
1173 hyper_ready = 0;
1174 witchspace = 0;
1175
1176 if (hyper_galactic)
1177 {
1178 cmdr.galactic_hyperdrive = 0;
1179 enter_next_galaxy();
1180 cmdr.legal_status = 0;
1181 }
1182 else
1183 {
1184 cmdr.fuel -= hyper_distance;
1185 cmdr.legal_status /= 2;
1186
1187 if ((rand255() > 253) || (flight_climb == myship.max_climb))
1188 {
1189 enter_witchspace();
1190 return;
1191 }
1192
1193 docked_planet = destination_planet;
1194 }
1195
1196 cmdr.market_rnd = rand255();
1197 generate_planet_data (&current_planet_data, docked_planet);
1198 generate_stock_market ();
1199
1200 flight_speed = 12;
1201 flight_roll = 0;
1202 flight_climb = 0;
1203 create_new_stars();
1204 clear_universe();
1205
1206 generate_landscape(docked_planet.a * 251 + docked_planet.b);
1207 set_init_matrix (rotmat);
1208
1209 pz = (((docked_planet.b) & 7) + 7) / 2;
1210 px = pz / 2;
1211 py = px;
1212
1213 px <<= 16;
1214 py <<= 16;
1215 pz <<= 16;
1216
1217 if ((docked_planet.b & 1) == 0)
1218 {
1219 px = -px;
1220 py = -py;
1221 }
1222
1223 add_new_ship (SHIP_PLANET, px, py, pz, rotmat, 0, 0);
1224
1225
1226 pz = -(((docked_planet.d & 7) | 1) << 16);
1227 px = ((docked_planet.f & 3) << 16) | ((docked_planet.f & 3) << 8);
1228
1229 add_new_ship (SHIP_SUN, px, py, pz, rotmat, 0, 0);
1230
1231 current_screen = SCR_BREAK_PATTERN;
1232 snd_play_sample (SND_HYPERSPACE);
1233}
1234
1235
1236void countdown_hyperspace (void)
1237{
1238 if (hyper_countdown == 0)
1239 {
1240 complete_hyperspace();
1241 return;
1242 }
1243
1244 hyper_countdown--;
1245}
1246
1247
1248
1249void jump_warp (void)
1250{
1251 int i;
1252 int type;
1253 int jump;
4c1c1a84 1254
1255 if (!kbd_ctrl_pressed) {
1256 for (i = 0; i < MAX_UNIV_OBJECTS; i++)
1257 {
1258 type = universe[i].type;
84bbd123 1259
4c1c1a84 1260 if ((type > 0) && (type != SHIP_ASTEROID) && (type != SHIP_CARGO) &&
1261 (type != SHIP_ALLOY) && (type != SHIP_ROCK) &&
1262 (type != SHIP_BOULDER) && (type != SHIP_ESCAPE_CAPSULE))
1263 {
1264 info_message ("Mass Locked");
1265 return;
1266 }
1267 }
1268 if ((universe[0].distance < 75001) || (universe[1].distance < 75001))
1269 {
1270 info_message ("Mass Locked");
1271 return;
1272 }
84bbd123 1273
84bbd123 1274 }
1275
1276
1277 if (universe[0].distance < universe[1].distance)
1278 jump = universe[0].distance - 75000;
1279 else
1280 jump = universe[1].distance - 75000;
1281
4c1c1a84 1282 if (jump > 1024 || kbd_ctrl_pressed)
84bbd123 1283 jump = 1024;
1284
1285 for (i = 0; i < MAX_UNIV_OBJECTS; i++)
1286 {
1287 if (universe[i].type != 0)
1288 universe[i].location.z -= jump;
1289 }
1290
1291 warp_stars = 1;
4c1c1a84 1292 if (!kbd_ctrl_pressed) {
1293 mcount &= 63;
1294 in_battle = 0;
1295 }
84bbd123 1296}
1297
1298
1299void launch_player (void)
1300{
1301 Matrix rotmat;
1302
1303 docked = 0;
1304 flight_speed = 12;
1305 flight_roll = -15;
1306 flight_climb = 0;
1307 cmdr.legal_status |= carrying_contraband();
1308 create_new_stars();
1309 clear_universe();
1310 generate_landscape(docked_planet.a * 251 + docked_planet.b);
1311 set_init_matrix (rotmat);
1312 add_new_ship (SHIP_PLANET, 0, 0, 65536, rotmat, 0, 0);
40471f00 1313#ifdef HACKING
1a8abebd 1314 identify = 0;
40471f00 1315#endif
1a8abebd 1316 scanner_zoom = 1;
84bbd123 1317
1318 rotmat[2].x = -rotmat[2].x;
1319 rotmat[2].y = -rotmat[2].y;
1320 rotmat[2].z = -rotmat[2].z;
1321 add_new_station (0, 0, -256, rotmat);
1322
1323 current_screen = SCR_BREAK_PATTERN;
1324 snd_play_sample (SND_LAUNCH);
1325}
1326
1327
1328
1329/*
1330 * Engage the docking computer.
1331 * For the moment we just do an instant dock if we are in the safe zone.
1332 */
1333
1334void engage_docking_computer (void)
1335{
1336 if (ship_count[SHIP_CORIOLIS] || ship_count[SHIP_DODEC])
1337 {
1a8abebd 1338 snd_play_sample (SND_DOCK);
84bbd123 1339 dock_player();
1340 current_screen = SCR_BREAK_PATTERN;
1341 }
1342}
1343
1a8abebd 1344
1345void update_condition(void)
1346{
1347 if (docked)
1348 condition = COND_DOCKED;
1349 else if (energy < 50 || myship.altitude < 32 || myship.cabtemp > 224)
1350 condition = COND_ALERT;
1351 else if (energy < 128 || myship.altitude < 64 || myship.cabtemp > 192)
1352 condition = COND_RED;
1353 else {
1354 int i;
1355 condition = COND_GREEN;
1356 if (myship.altitude < 128 || myship.cabtemp >= 128)
1357 condition = COND_YELLOW;
1358 for (i = 0; i < MAX_UNIV_OBJECTS; i++) {
1359 struct univ_object *un = &universe[i];
1360 if (un->type <= 0)
1361 continue;
1362 if (un->flags & FLG_HOSTILE) {
1363 condition = COND_RED;
1364 break;
1365 }
1366 if (condition == COND_GREEN &&
1367 un->type != SHIP_ASTEROID && un->type != SHIP_CARGO &&
1368 un->type != SHIP_ALLOY && un->type != SHIP_ROCK &&
1369 un->type != SHIP_BOULDER && un->type != SHIP_ESCAPE_CAPSULE &&
1370 un->type != SHIP_CORIOLIS && un->type != SHIP_DODEC)
1371 condition = COND_YELLOW;
1372 }
1373 }
1374}