Initial revision
[newkind] / swat.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 * swat.c
17 *
18 * Special Weapons And Tactics.
19 */
20
21#include <math.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include "config.h"
26#include "gfx.h"
27#include "elite.h"
28#include "vector.h"
29#include "swat.h"
30#include "shipdata.h"
31#include "space.h"
32#include "main.h"
33#include "sound.h"
34#include "random.h"
35#include "trade.h"
36#include "pilot.h"
37
38int laser_counter;
39int laser;
40int laser2;
41int laser_x;
42int laser_y;
43
44int ecm_active;
45int missile_target;
46int ecm_ours;
47int in_battle;
48
49struct univ_object universe[MAX_UNIV_OBJECTS];
50int ship_count[NO_OF_SHIPS + 1]; /* many */
51
52
53int initial_flags[NO_OF_SHIPS + 1] =
54{
55 0, // NULL,
56 0, // missile
57 0, // coriolis
58 FLG_SLOW | FLG_FLY_TO_PLANET, // escape
59 FLG_INACTIVE, // alloy
60 FLG_INACTIVE, // cargo
61 FLG_INACTIVE, // boulder
62 FLG_INACTIVE, // asteroid
63 FLG_INACTIVE, // rock
64 FLG_FLY_TO_PLANET | FLG_SLOW, // shuttle
65 FLG_FLY_TO_PLANET | FLG_SLOW, // transporter
66 0, // cobra3
67 0, // python
68 0, // boa
69 FLG_SLOW, // anaconda
70 FLG_SLOW, // hermit
71 FLG_BOLD | FLG_POLICE, // viper
72 FLG_BOLD | FLG_ANGRY, // sidewinder
73 FLG_BOLD | FLG_ANGRY, // mamba
74 FLG_BOLD | FLG_ANGRY, // krait
75 FLG_BOLD | FLG_ANGRY, // adder
76 FLG_BOLD | FLG_ANGRY, // gecko
77 FLG_BOLD | FLG_ANGRY, // cobra1
78 FLG_SLOW | FLG_ANGRY, // worm
79 FLG_BOLD | FLG_ANGRY, // cobra3
80 FLG_BOLD | FLG_ANGRY, // asp2
81 FLG_BOLD | FLG_ANGRY, // python
82 FLG_POLICE, // fer_de_lance
83 FLG_BOLD | FLG_ANGRY, // moray
84 FLG_BOLD | FLG_ANGRY, // thargoid
85 FLG_ANGRY, // thargon
86 FLG_ANGRY, // constrictor
87 FLG_POLICE | FLG_CLOAKED, // cougar
88 0 // dodec
89};
90
91
92
93
94void clear_universe (void)
95{
96 int i;
97
98 for (i = 0; i < MAX_UNIV_OBJECTS; i++)
99 universe[i].type = 0;
100
101 for (i = 0; i <= NO_OF_SHIPS; i++)
102 ship_count[i] = 0;
103
104 in_battle = 0;
105}
106
107
108int add_new_ship (int ship_type, int x, int y, int z, struct vector *rotmat, int rotx, int rotz)
109{
110 int i;
111
112 for (i = 0; i < MAX_UNIV_OBJECTS; i++)
113 {
114 if (universe[i].type == 0)
115 {
116 universe[i].type = ship_type;
117 universe[i].location.x = x;
118 universe[i].location.y = y;
119 universe[i].location.z = z;
120
121 universe[i].distance = sqrt(x*x + y*y + z*z);
122
123 universe[i].rotmat[0] = rotmat[0];
124 universe[i].rotmat[1] = rotmat[1];
125 universe[i].rotmat[2] = rotmat[2];
126
127 universe[i].rotx = rotx;
128 universe[i].rotz = rotz;
129
130 universe[i].velocity = 0;
131 universe[i].acceleration = 0;
132 universe[i].bravery = 0;
133 universe[i].target = 0;
134
135 universe[i].flags = initial_flags[ship_type];
136
137 if ((ship_type != SHIP_PLANET) && (ship_type != SHIP_SUN))
138 {
139 universe[i].energy = ship_list[ship_type]->energy;
140 universe[i].missiles = ship_list[ship_type]->missiles;
141 ship_count[ship_type]++;
142 }
143
144 return i;
145 }
146 }
147
148 return -1;
149}
150
151
152
153
154void check_missiles (int un)
155{
156 int i;
157
158 if (missile_target == un)
159 {
160 missile_target = MISSILE_UNARMED;
161 info_message ("Target Lost");
162 }
163
164 for (i = 0; i < MAX_UNIV_OBJECTS; i++)
165 {
166 if ((universe[i].type == SHIP_MISSILE) && (universe[i].target == un))
167 universe[i].flags |= FLG_DEAD;
168 }
169}
170
171
172void remove_ship (int un)
173{
174 int type;
175 Matrix rotmat;
176 int px,py,pz;
177
178 type = universe[un].type;
179
180 if (type == 0)
181 return;
182
183 if (type > 0)
184 ship_count[type]--;
185
186 universe[un].type = 0;
187
188 check_missiles (un);
189
190 if ((type == SHIP_CORIOLIS) || (type == SHIP_DODEC))
191 {
192 set_init_matrix (rotmat);
193 px = universe[un].location.x;
194 py = universe[un].location.y;
195 pz = universe[un].location.z;
196
197 py &= 0xFFFF;
198 py |= 0x60000;
199
200 add_new_ship (SHIP_SUN, px, py, pz, rotmat, 0, 0);
201 }
202}
203
204
205void add_new_station (double sx, double sy, double sz, Matrix rotmat)
206{
207 int station;
208
209 station = (current_planet_data.techlevel >= 10) ? SHIP_DODEC : SHIP_CORIOLIS;
210 universe[1].type = 0;
211 add_new_ship (station, sx, sy, sz, rotmat, 0, -127);
212}
213
214
215
216
217void reset_weapons (void)
218{
219 laser_temp = 0;
220 laser_counter = 0;
221 laser = 0;
222 ecm_active = 0;
223 missile_target = MISSILE_UNARMED;
224}
225
226
227void launch_enemy (int un, int type, int flags, int bravery)
228{
229 int newship;
230 struct univ_object *ns;
231
232 newship = add_new_ship (type, universe[un].location.x, universe[un].location.y,
233 universe[un].location.z, universe[un].rotmat,
234 universe[un].rotx, universe[un].rotz);
235
236 if (newship == -1)
237 {
238 return;
239 }
240
241 ns = &universe[newship];
242
243 if ((universe[un].type == SHIP_CORIOLIS) || (universe[un].type == SHIP_DODEC))
244 {
245 ns->velocity = 32;
246 ns->location.x += ns->rotmat[2].x * 2;
247 ns->location.y += ns->rotmat[2].y * 2;
248 ns->location.z += ns->rotmat[2].z * 2;
249 }
250
251 ns->flags |= flags;
252 ns->rotz /= 2;
253 ns->rotz *= 2;
254 ns->bravery = bravery;
255
256 if ((type == SHIP_CARGO) || (type == SHIP_ALLOY) || (type == SHIP_ROCK))
257 {
258 ns->rotz = ((rand255() * 2) & 255) - 128;
259 ns->rotx = ((rand255() * 2) & 255) - 128;
260 ns->velocity = rand255() & 15;
261 }
262}
263
264
265void launch_loot (int un, int loot)
266{
267 int i,cnt;
268
269 if (loot == SHIP_ROCK)
270 {
271 cnt = rand255() & 3;
272 }
273 else
274 {
275 cnt = rand255();
276 if (cnt >= 128)
277 return;
278
279 cnt &= ship_list[universe[un].type]->max_loot;
280 cnt &= 15;
281 }
282
283 for (i = 0; i < cnt; i++)
284 {
285 launch_enemy (un, loot, 0,0);
286 }
287}
288
289
290
291
292int in_target (int type, double x, double y, double z)
293{
294 double size;
295
296 if (z < 0)
297 return 0;
298
299 size = ship_list[type]->size;
300
301 return ((x*x + y*y) <= size);
302}
303
304
305
306void make_angry (int un)
307{
308 int type;
309 int flags;
310
311 type = universe[un].type;
312 flags = universe[un].flags;
313
314 if (flags & FLG_INACTIVE)
315 return;
316
317 if ((type == SHIP_CORIOLIS) || (type == SHIP_DODEC))
318 {
319 universe[un].flags |= FLG_ANGRY;
320 return;
321 }
322
323 if (type > SHIP_ROCK)
324 {
325 universe[un].rotx = 4;
326 universe[un].acceleration = 2;
327 universe[un].flags |= FLG_ANGRY;
328 }
329}
330
331
332void explode_object (int un)
333{
334
335 cmdr.score++;
336
337 if ((cmdr.score & 255) == 0)
338 info_message ("Right On Commander!");
339
340 snd_play_sample (SND_EXPLODE);
341 universe[un].flags |= FLG_DEAD;
342
343 if (universe[un].type == SHIP_CONSTRICTOR)
344 cmdr.mission = 2;
345}
346
347
348void check_target (int un, struct univ_object *flip)
349{
350 struct univ_object *univ;
351
352 univ = &universe[un];
353
354 if (in_target (univ->type, flip->location.x, flip->location.y, flip->location.z))
355 {
356 if ((missile_target == MISSILE_ARMED) && (univ->type >= 0))
357 {
358 missile_target = un;
359 info_message ("Target Locked");
360 snd_play_sample (SND_BEEP);
361 }
362
363 if (laser)
364 {
365 snd_play_sample (SND_HIT_ENEMY);
366
367 if ((univ->type != SHIP_CORIOLIS) && (univ->type != SHIP_DODEC))
368 {
369 if ((univ->type == SHIP_CONSTRICTOR) || (univ->type == SHIP_COUGAR))
370 {
371 if (laser == (MILITARY_LASER & 127))
372 univ->energy -= laser / 4;
373 }
374 else
375 {
376 univ->energy -= laser;
377 }
378 }
379
380 if (univ->energy <= 0)
381 {
382 explode_object (un);
383
384 if (univ->type == SHIP_ASTEROID)
385 {
386 if (laser == (MINING_LASER & 127))
387 launch_loot (un, SHIP_ROCK);
388 }
389 else
390 {
391 launch_loot (un, SHIP_ALLOY);
392 launch_loot (un, SHIP_CARGO);
393 }
394 }
395
396 make_angry (un);
397 }
398 }
399}
400
401
402
403void activate_ecm (int ours)
404{
405 if (ecm_active == 0)
406 {
407 ecm_active = 32;
408 ecm_ours = ours;
409 snd_play_sample (SND_ECM);
410 }
411}
412
413
414void time_ecm (void)
415{
416 if (ecm_active != 0)
417 {
418 ecm_active--;
419 if (ecm_ours)
420 decrease_energy (-1);
421 }
422}
423
424
425void arm_missile (void)
426{
427 if ((cmdr.missiles != 0) && (missile_target == MISSILE_UNARMED))
428 missile_target = MISSILE_ARMED;
429}
430
431
432void unarm_missile (void)
433{
434 missile_target = MISSILE_UNARMED;
435 snd_play_sample (SND_BOOP);
436}
437
438void fire_missile (void)
439{
440 int newship;
441 struct univ_object *ns;
442 Matrix rotmat;
443
444 if (missile_target < 0)
445 return;
446
447 set_init_matrix (rotmat);
448 rotmat[2].z = 1.0;
449 rotmat[0].x = -1.0;
450
451 newship = add_new_ship (SHIP_MISSILE, 0, -28, 14, rotmat, 0, 0);
452
453 if (newship == -1)
454 {
455 info_message ("Missile Jammed");
456 return;
457 }
458
459 ns = &universe[newship];
460
461 ns->velocity = flight_speed * 2;
462 ns->flags = FLG_ANGRY;
463 ns->target = missile_target;
464
465 if (universe[missile_target].type > SHIP_ROCK)
466 universe[missile_target].flags |= FLG_ANGRY;
467
468 cmdr.missiles--;
469 missile_target = MISSILE_UNARMED;
470
471 snd_play_sample (SND_MISSILE);
472}
473
474
475
476void track_object (struct univ_object *ship, double direction, Vector nvec)
477{
478 double dir;
479 int rat;
480 double rat2;
481
482 rat = 3;
483 rat2 = 0.111;
484
485 dir = vector_dot_product (&nvec, &ship->rotmat[1]);
486
487 if (direction < -0.861)
488 {
489 ship->rotx = (dir < 0) ? 7 : -7;
490 ship->rotz = 0;
491 return;
492 }
493
494 ship->rotx = 0;
495
496 if ((fabs(dir) * 2) >= rat2)
497 {
498 ship->rotx = (dir < 0) ? rat : -rat;
499 }
500
501 if (abs(ship->rotz) < 16)
502 {
503 dir = vector_dot_product (&nvec, &ship->rotmat[0]);
504
505 ship->rotz = 0;
506
507 if ((fabs(dir) * 2) > rat2)
508 {
509 ship->rotz = (dir < 0) ? rat : -rat;
510
511 if (ship->rotx < 0)
512 ship->rotz = -ship->rotz;
513 }
514 }
515}
516
517
518
519void missile_tactics (int un)
520{
521 struct univ_object *missile;
522 struct univ_object *target;
523 Vector vec;
524 Vector nvec;
525 double direction;
526 double cnt2 = 0.223;
527
528 missile = &universe[un];
529
530 if (ecm_active)
531 {
532 snd_play_sample (SND_EXPLODE);
533 missile->flags |= FLG_DEAD;
534 return;
535 }
536
537 if (missile->target == 0)
538 {
539 if (missile->distance < 256)
540 {
541 missile->flags |= FLG_DEAD;
542 snd_play_sample (SND_EXPLODE);
543 damage_ship (250, missile->location.z >= 0.0);
544 return;
545 }
546
547 vec.x = missile->location.x;
548 vec.y = missile->location.y;
549 vec.z = missile->location.z;
550 }
551 else
552 {
553 target = &universe[missile->target];
554
555 vec.x = missile->location.x - target->location.x;
556 vec.y = missile->location.y - target->location.y;
557 vec.z = missile->location.z - target->location.z;
558
559 if ((fabs(vec.x) < 256) && (fabs(vec.y) < 256) && (fabs(vec.z) < 256))
560 {
561 missile->flags |= FLG_DEAD;
562
563 if ((target->type != SHIP_CORIOLIS) && (target->type != SHIP_DODEC))
564 explode_object (missile->target);
565 else
566 snd_play_sample (SND_EXPLODE);
567
568 return;
569 }
570
571 if ((rand255() < 16) && (target->flags & FLG_HAS_ECM))
572 {
573 activate_ecm (0);
574 return;
575 }
576 }
577
578 nvec = unit_vector(&vec);
579 direction = vector_dot_product (&nvec, &missile->rotmat[2]);
580 nvec.x = -nvec.x;
581 nvec.y = -nvec.y;
582 nvec.z = -nvec.z;
583 direction = -direction;
584
585 track_object (missile, direction, nvec);
586
587 if (direction <= -0.167)
588 {
589 missile->acceleration = -2;
590 return;
591 }
592
593 if (direction >= cnt2)
594 {
595 missile->acceleration = 3;
596 return;
597 }
598
599 if (missile->velocity < 6)
600 missile->acceleration = 3;
601 else
602 if (rand255() >= 200)
603 missile->acceleration = -2;
604 return;
605}
606
607
608
609void launch_shuttle (void)
610{
611 int type;
612
613 if ((ship_count[SHIP_TRANSPORTER] != 0) ||
614 (ship_count[SHIP_SHUTTLE] != 0) ||
615 (rand255() < 253) || (auto_pilot))
616 return;
617
618 type = rand255() & 1 ? SHIP_SHUTTLE : SHIP_TRANSPORTER;
619 launch_enemy (1, type, FLG_HAS_ECM | FLG_FLY_TO_PLANET, 113);
620}
621
622
623void tactics (int un)
624{
625 int type;
626 int energy;
627 int maxeng;
628 int flags;
629 struct univ_object *ship;
630 Vector nvec;
631 double cnt2 = 0.223;
632 double direction;
633 int attacking;
634
635 ship = &universe[un];
636 type = ship->type;
637 flags = ship->flags;
638
639 if ((type == SHIP_PLANET) || (type == SHIP_SUN))
640 return;
641
642 if (flags & FLG_DEAD)
643 return;
644
645 if (flags & FLG_INACTIVE)
646 return;
647
648 if (type == SHIP_MISSILE)
649 {
650 if (flags & FLG_ANGRY)
651 missile_tactics (un);
652 return;
653 }
654
655 if (((un ^ mcount) & 7) != 0)
656 return;
657
658 if ((type == SHIP_CORIOLIS) || (type == SHIP_DODEC))
659 {
660 if (flags & FLG_ANGRY)
661 {
662 if ((rand() & 255) < 240)
663 return;
664
665 if (ship_count[SHIP_VIPER] >= 4)
666 return;
667
668 launch_enemy (un, SHIP_VIPER, FLG_ANGRY | FLG_HAS_ECM, 113);
669 return;
670 }
671
672 launch_shuttle ();
673 return;
674 }
675
676 if (type == SHIP_HERMIT)
677 {
678 if (rand255() > 200)
679 {
680 launch_enemy (un, SHIP_SIDEWINDER + (rand255() & 3), FLG_ANGRY | FLG_HAS_ECM, 113);
681 ship->flags |= FLG_INACTIVE;
682 }
683
684 return;
685 }
686
687
688 if (ship->energy < ship_list[type]->energy)
689 ship->energy++;
690
691 if ((type == SHIP_THARGLET) && (ship_count[SHIP_THARGOID] == 0))
692 {
693 ship->flags = 0;
694 ship->velocity /= 2;
695 return;
696 }
697
698 if (flags & FLG_SLOW)
699 {
700 if (rand255() > 50)
701 return;
702 }
703
704 if (flags & FLG_POLICE)
705 {
706 if (cmdr.legal_status >= 64)
707 {
708 flags |= FLG_ANGRY;
709 ship->flags = flags;
710 }
711 }
712
713 if ((flags & FLG_ANGRY) == 0)
714 {
715 if ((flags & FLG_FLY_TO_PLANET) || (flags & FLG_FLY_TO_STATION))
716 {
717 auto_pilot_ship (&universe[un]);
718 }
719
720 return;
721 }
722
723
724 /* If we get to here then the ship is angry so start attacking... */
725
726 if (ship_count[SHIP_CORIOLIS] || ship_count[SHIP_DODEC])
727 {
728 if ((flags & FLG_BOLD) == 0)
729 ship->bravery = 0;
730 }
731
732
733 if (type == SHIP_ANACONDA)
734 {
735 if (rand255() > 200)
736 {
737 launch_enemy (un, rand255() > 100 ? SHIP_WORM : SHIP_SIDEWINDER,
738 FLG_ANGRY | FLG_HAS_ECM, 113);
739 return;
740 }
741 }
742
743
744 if (rand255() >= 250)
745 {
746 ship->rotz = rand255() | 0x68;
747 if (ship->rotz > 127)
748 ship->rotz = -(ship->rotz & 127);
749 }
750
751 maxeng = ship_list[type]->energy;
752 energy = ship->energy;
753
754 if (energy < (maxeng / 2))
755 {
756 if ((energy < (maxeng / 8)) && (rand255() > 230) && (type != SHIP_THARGOID))
757 {
758 ship->flags &= ~FLG_ANGRY;
759 ship->flags |= FLG_INACTIVE;
760 launch_enemy (un, SHIP_ESCAPE_CAPSULE, 0, 126);
761 return;
762 }
763
764 if ((ship->missiles != 0) && (ecm_active == 0) &&
765 (ship->missiles >= (rand255() & 31)))
766 {
767 ship->missiles--;
768 if (type == SHIP_THARGOID)
769 launch_enemy (un, SHIP_THARGLET, FLG_ANGRY, ship->bravery);
770 else
771 {
772 launch_enemy (un, SHIP_MISSILE, FLG_ANGRY, 126);
773 info_message ("INCOMING MISSILE");
774 }
775 return;
776 }
777 }
778
779 nvec = unit_vector(&universe[un].location);
780 direction = vector_dot_product (&nvec, &ship->rotmat[2]);
781
782 if ((ship->distance < 8192) && (direction <= -0.833) &&
783 (ship_list[type]->laser_strength != 0))
784 {
785 if (direction <= -0.917)
786 ship->flags |= FLG_FIRING | FLG_HOSTILE;
787
788 if (direction <= -0.972)
789 {
790 damage_ship (ship_list[type]->laser_strength, ship->location.z >= 0.0);
791 ship->acceleration--;
792 if (((ship->location.z >= 0.0) && (front_shield == 0)) ||
793 ((ship->location.z < 0.0) && (aft_shield == 0)))
794 snd_play_sample (SND_INCOMMING_FIRE_2);
795 else
796 snd_play_sample (SND_INCOMMING_FIRE_1);
797 }
798 else
799 {
800 nvec.x = -nvec.x;
801 nvec.y = -nvec.y;
802 nvec.z = -nvec.z;
803 direction = -direction;
804 track_object (&universe[un], direction, nvec);
805 }
806
807// if ((fabs(ship->location.z) < 768) && (ship->bravery <= ((rand255() & 127) | 64)))
808 if (fabs(ship->location.z) < 768)
809 {
810 ship->rotx = rand255() & 0x87;
811 if (ship->rotx > 127)
812 ship->rotx = -(ship->rotx & 127);
813
814 ship->acceleration = 3;
815 return;
816 }
817
818 if (ship->distance < 8192)
819 ship->acceleration = -1;
820 else
821 ship->acceleration = 3;
822 return;
823 }
824
825 attacking = 0;
826
827 if ((fabs(ship->location.z) >= 768) ||
828 (fabs(ship->location.x) >= 512) ||
829 (fabs(ship->location.y) >= 512))
830 {
831 if (ship->bravery > (rand255() & 127))
832 {
833 attacking = 1;
834 nvec.x = -nvec.x;
835 nvec.y = -nvec.y;
836 nvec.z = -nvec.z;
837 direction = -direction;
838 }
839 }
840
841 track_object (&universe[un], direction, nvec);
842
843 if ((attacking == 1) && (ship->distance < 2048))
844 {
845 if (direction >= cnt2)
846 {
847 ship->acceleration = -1;
848 return;
849 }
850
851 if (ship->velocity < 6)
852 ship->acceleration = 3;
853 else
854 if (rand255() >= 200)
855 ship->acceleration = -1;
856 return;
857 }
858
859 if (direction <= -0.167)
860 {
861 ship->acceleration = -1;
862 return;
863 }
864
865 if (direction >= cnt2)
866 {
867 ship->acceleration = 3;
868 return;
869 }
870
871 if (ship->velocity < 6)
872 ship->acceleration = 3;
873 else
874 if (rand255() >= 200)
875 ship->acceleration = -1;
876}
877
878
879void draw_laser_lines (void)
880{
881 if (wireframe)
882 {
883 gfx_draw_colour_line (32 * GFX_SCALE, GFX_VIEW_BY, laser_x, laser_y, GFX_COL_WHITE);
884 gfx_draw_colour_line (48 * GFX_SCALE, GFX_VIEW_BY, laser_x, laser_y, GFX_COL_WHITE);
885 gfx_draw_colour_line (208 * GFX_SCALE, GFX_VIEW_BY, laser_x, laser_y, GFX_COL_WHITE);
886 gfx_draw_colour_line (224 * GFX_SCALE, GFX_VIEW_BY, laser_x, laser_y, GFX_COL_WHITE);
887 }
888 else
889 {
890 gfx_draw_triangle (32 * GFX_SCALE, GFX_VIEW_BY, laser_x, laser_y, 48 * GFX_SCALE, GFX_VIEW_BY, GFX_COL_RED);
891 gfx_draw_triangle (208 * GFX_SCALE, GFX_VIEW_BY, laser_x, laser_y, 224 * GFX_SCALE, GFX_VIEW_BY, GFX_COL_RED);
892 }
893}
894
895
896int fire_laser (void)
897{
898 if ((laser_counter == 0) && (laser_temp < 242))
899 {
900 switch (current_screen)
901 {
902 case SCR_FRONT_VIEW:
903 laser = cmdr.front_laser;
904 break;
905
906 case SCR_REAR_VIEW:
907 laser = cmdr.rear_laser;
908 break;
909
910 case SCR_RIGHT_VIEW:
911 laser = cmdr.right_laser;
912 break;
913
914 case SCR_LEFT_VIEW:
915 laser = cmdr.left_laser;
916 break;
917
918 default:
919 laser = 0;
920 }
921
922 if (laser != 0)
923 {
924 laser_counter = (laser > 127) ? 0 : (laser & 0xFA);
925 laser &= 127;
926 laser2 = laser;
927
928 snd_play_sample (SND_PULSE);
929 laser_temp += 8;
930 if (energy > 1)
931 energy--;
932
933 laser_x = ((rand() & 3) + 128 - 2) * GFX_SCALE;
934 laser_y = ((rand() & 3) + 96 - 2) * GFX_SCALE;
935
936 return 2;
937 }
938 }
939
940 return 0;
941}
942
943
944void cool_laser (void)
945{
946 laser = 0;
947
948 if (laser_temp > 0)
949 laser_temp--;
950
951 if (laser_counter > 0)
952 laser_counter--;
953
954 if (laser_counter > 0)
955 laser_counter--;
956}
957
958
959int create_other_ship (int type)
960{
961 Matrix rotmat;
962 int x,y,z;
963 int newship;
964
965 set_init_matrix (rotmat);
966
967 z = 12000;
968 x = 1000 + (randint() & 8191);
969 y = 1000 + (randint() & 8191);
970
971 if (rand255() > 127)
972 x = -x;
973 if (rand255() > 127)
974 y = -y;
975
976 newship = add_new_ship (type, x, y, z, rotmat, 0, 0);
977
978 return newship;
979}
980
981
982void create_thargoid (void)
983{
984 int newship;
985
986 newship = create_other_ship (SHIP_THARGOID);
987 if (newship != -1)
988 {
989 universe[newship].flags = FLG_ANGRY | FLG_HAS_ECM;
990 universe[newship].bravery = 113;
991
992 if (rand255() > 64)
993 launch_enemy (newship, SHIP_THARGLET, FLG_ANGRY | FLG_HAS_ECM, 96);
994 }
995}
996
997
998
999void create_cougar (void)
1000{
1001 int newship;
1002
1003 if (ship_count[SHIP_COUGAR] != 0)
1004 return;
1005
1006 newship = create_other_ship (SHIP_COUGAR);
1007 if (newship != -1)
1008 {
1009 universe[newship].flags = FLG_HAS_ECM; // | FLG_CLOAKED;
1010 universe[newship].bravery = 121;
1011 universe[newship].velocity = 18;
1012 }
1013}
1014
1015
1016
1017void create_trader (void)
1018{
1019 int newship;
1020 int rnd;
1021 int type;
1022
1023 type = SHIP_COBRA3 + (rand255() & 3);
1024
1025 newship = create_other_ship (type);
1026
1027 if (newship != -1)
1028 {
1029 universe[newship].rotmat[2].z = -1.0;
1030 universe[newship].rotz = rand255() & 7;
1031
1032 rnd = rand255();
1033 universe[newship].velocity = (rnd & 31) | 16;
1034 universe[newship].bravery = rnd / 2;
1035
1036 if (rnd & 1)
1037 universe[newship].flags |= FLG_HAS_ECM;
1038
1039// if (rnd & 2)
1040// universe[newship].flags |= FLG_ANGRY;
1041 }
1042}
1043
1044
1045void create_lone_hunter (void)
1046{
1047 int rnd;
1048 int type;
1049 int newship;
1050
1051 if ((cmdr.mission == 1) && (cmdr.galaxy_number == 1) &&
1052 (docked_planet.d == 144) && (docked_planet.b == 33) &&
1053 (ship_count[SHIP_CONSTRICTOR] == 0))
1054 {
1055 type = SHIP_CONSTRICTOR;
1056 }
1057 else
1058 {
1059 rnd = rand255();
1060 type = SHIP_COBRA3_LONE + (rnd & 3) + (rnd > 127);
1061 }
1062
1063 newship = create_other_ship (type);
1064
1065 if (newship != -1)
1066 {
1067 universe[newship].flags = FLG_ANGRY;
1068 if ((rand255() > 200) || (type == SHIP_CONSTRICTOR))
1069 universe[newship].flags |= FLG_HAS_ECM;
1070
1071 universe[newship].bravery = ((rand255() * 2) | 64) & 127;
1072 in_battle = 1;
1073 }
1074}
1075
1076
1077
1078/* Check for a random asteroid encounter... */
1079
1080void check_for_asteroids (void)
1081{
1082 int newship;
1083 int type;
1084
1085 if ((rand255() >= 35) || (ship_count[SHIP_ASTEROID] >= 3))
1086 return;
1087
1088 if (rand255() > 253)
1089 type = SHIP_HERMIT;
1090 else
1091 type = SHIP_ASTEROID;
1092
1093 newship = create_other_ship (type);
1094
1095 if (newship != -1)
1096 {
1097// universe[newship].velocity = (rand255() & 31) | 16;
1098 universe[newship].velocity = 8;
1099 universe[newship].rotz = rand255() > 127 ? -127 : 127;
1100 universe[newship].rotx = 16;
1101 }
1102}
1103
1104
1105
1106/* If we've been a bad boy then send the cops after us... */
1107
1108void check_for_cops (void)
1109{
1110 int newship;
1111 int offense;
1112
1113 offense = carrying_contraband() * 2;
1114 if (ship_count[SHIP_VIPER] == 0)
1115 offense |= cmdr.legal_status;
1116
1117 if (rand255() >= offense)
1118 return;
1119
1120 newship = create_other_ship (SHIP_VIPER);
1121
1122 if (newship != -1)
1123 {
1124 universe[newship].flags = FLG_ANGRY;
1125 if (rand255() > 245)
1126 universe[newship].flags |= FLG_HAS_ECM;
1127
1128 universe[newship].bravery = ((rand255() * 2) | 64) & 127;
1129 }
1130}
1131
1132
1133void check_for_others (void)
1134{
1135 int x,y,z;
1136 int newship;
1137 Matrix rotmat;
1138 int gov;
1139 int rnd;
1140 int type;
1141 int i;
1142
1143 gov = current_planet_data.government;
1144 rnd = rand255();
1145
1146 if ((gov != 0) && ((rnd >= 90) || ((rnd & 7) < gov)))
1147 return;
1148
1149 if (rand255() < 100)
1150 {
1151 create_lone_hunter();
1152 return;
1153 }
1154
1155 /* Pack hunters... */
1156
1157 set_init_matrix (rotmat);
1158
1159 z = 12000;
1160 x = 1000 + (randint() & 8191);
1161 y = 1000 + (randint() & 8191);
1162
1163 if (rand255() > 127)
1164 x = -x;
1165 if (rand255() > 127)
1166 y = -y;
1167
1168 rnd = rand255() & 3;
1169
1170 for (i = 0; i <= rnd; i++)
1171 {
1172 type = SHIP_SIDEWINDER + (rand255() & rand255() & 7);
1173 newship = add_new_ship (type, x, y, z, rotmat, 0, 0);
1174 if (newship != -1)
1175 {
1176 universe[newship].flags = FLG_ANGRY;
1177 if (rand255() > 245)
1178 universe[newship].flags |= FLG_HAS_ECM;
1179
1180 universe[newship].bravery = ((rand255() * 2) | 64) & 127;
1181 in_battle++;
1182 }
1183 }
1184
1185}
1186
1187
1188void random_encounter (void)
1189{
1190 if ((ship_count[SHIP_CORIOLIS] != 0) || (ship_count[SHIP_DODEC] != 0))
1191 return;
1192
1193 if (rand255() == 136)
1194 {
1195 if (((int)(universe[0].location.z) & 0x3e) != 0)
1196 create_thargoid ();
1197 else
1198 create_cougar();
1199
1200 return;
1201 }
1202
1203 if ((rand255() & 7) == 0)
1204 {
1205 create_trader();
1206 return;
1207 }
1208
1209 check_for_asteroids();
1210
1211 check_for_cops();
1212
1213 if (ship_count[SHIP_VIPER] != 0)
1214 return;
1215
1216 if (in_battle)
1217 return;
1218
1219 if ((cmdr.mission == 5) && (rand255() >= 200))
1220 create_thargoid ();
1221
1222 check_for_others();
1223}
1224
1225
1226void abandon_ship (void)
1227{
1228 int i;
1229
1230 cmdr.escape_pod = 0;
1231 cmdr.legal_status = 0;
1232 cmdr.fuel = myship.max_fuel;
1233
1234 for (i = 0; i < NO_OF_STOCK_ITEMS; i++)
1235 cmdr.current_cargo[i] = 0;
1236
1237 snd_play_sample (SND_DOCK);
1238 dock_player();
1239 current_screen = SCR_BREAK_PATTERN;
1240}
1241