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