Ignore binary.
[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,
1a8abebd 56 FLG_TARGET, // missile
84bbd123 57 0, // coriolis
58 FLG_SLOW | FLG_FLY_TO_PLANET, // escape
1a8abebd 59 FLG_INACTIVE | FLG_TARGET, // alloy
60 FLG_INACTIVE | FLG_TARGET, // cargo
61 FLG_INACTIVE | FLG_TARGET, // boulder
62 FLG_INACTIVE | FLG_TARGET, // asteroid
63 FLG_INACTIVE | FLG_TARGET, // rock
84bbd123 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
1a8abebd 72 FLG_BOLD | FLG_ANGRY | FLG_TARGET, // sidewinder
73 FLG_BOLD | FLG_ANGRY | FLG_TARGET, // mamba
74 FLG_BOLD | FLG_ANGRY | FLG_TARGET, // krait
75 FLG_BOLD | FLG_ANGRY | FLG_TARGET, // adder
76 FLG_BOLD | FLG_ANGRY | FLG_TARGET, // gecko
77 FLG_BOLD | FLG_ANGRY | FLG_TARGET, // cobra1
78 FLG_SLOW | FLG_ANGRY | FLG_TARGET, // worm
79 FLG_BOLD | FLG_ANGRY | FLG_TARGET, // cobra3
80 FLG_BOLD | FLG_ANGRY | FLG_TARGET, // asp2
81 FLG_BOLD | FLG_ANGRY | FLG_TARGET, // python
82 FLG_POLICE, // fer_de_lance
83 FLG_BOLD | FLG_ANGRY | FLG_TARGET, // moray
84 FLG_BOLD | FLG_ANGRY | FLG_TARGET, // thargoid
85 FLG_ANGRY | FLG_TARGET, // thargon
84bbd123 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
1a8abebd 314 if (flags & FLG_INACTIVE) {
315 universe[un].flags |= FLG_TACTICAL;
316 return;
317 }
318
84bbd123 319 if ((type == SHIP_CORIOLIS) || (type == SHIP_DODEC))
320 {
321 universe[un].flags |= FLG_ANGRY;
322 return;
323 }
324
325 if (type > SHIP_ROCK)
326 {
327 universe[un].rotx = 4;
328 universe[un].acceleration = 2;
1a8abebd 329 universe[un].flags |= FLG_ANGRY | FLG_TACTICAL;
84bbd123 330 }
331}
332
333
334void explode_object (int un)
335{
336
337 cmdr.score++;
338
339 if ((cmdr.score & 255) == 0)
340 info_message ("Right On Commander!");
341
342 snd_play_sample (SND_EXPLODE);
343 universe[un].flags |= FLG_DEAD;
344
345 if (universe[un].type == SHIP_CONSTRICTOR)
346 cmdr.mission = 2;
347}
348
349
350void check_target (int un, struct univ_object *flip)
351{
352 struct univ_object *univ;
353
354 univ = &universe[un];
355
356 if (in_target (univ->type, flip->location.x, flip->location.y, flip->location.z))
357 {
358 if ((missile_target == MISSILE_ARMED) && (univ->type >= 0))
359 {
360 missile_target = un;
361 info_message ("Target Locked");
362 snd_play_sample (SND_BEEP);
363 }
364
365 if (laser)
366 {
367 snd_play_sample (SND_HIT_ENEMY);
368
369 if ((univ->type != SHIP_CORIOLIS) && (univ->type != SHIP_DODEC))
370 {
371 if ((univ->type == SHIP_CONSTRICTOR) || (univ->type == SHIP_COUGAR))
372 {
373 if (laser == (MILITARY_LASER & 127))
374 univ->energy -= laser / 4;
375 }
376 else
377 {
378 univ->energy -= laser;
379 }
380 }
381
382 if (univ->energy <= 0)
383 {
384 explode_object (un);
385
386 if (univ->type == SHIP_ASTEROID)
387 {
388 if (laser == (MINING_LASER & 127))
389 launch_loot (un, SHIP_ROCK);
390 }
391 else
392 {
393 launch_loot (un, SHIP_ALLOY);
394 launch_loot (un, SHIP_CARGO);
395 }
396 }
397
398 make_angry (un);
399 }
400 }
401}
402
403
404
405void activate_ecm (int ours)
406{
407 if (ecm_active == 0)
408 {
409 ecm_active = 32;
410 ecm_ours = ours;
411 snd_play_sample (SND_ECM);
412 }
413}
414
415
416void time_ecm (void)
417{
418 if (ecm_active != 0)
419 {
420 ecm_active--;
421 if (ecm_ours)
422 decrease_energy (-1);
423 }
424}
425
426
427void arm_missile (void)
428{
429 if ((cmdr.missiles != 0) && (missile_target == MISSILE_UNARMED))
430 missile_target = MISSILE_ARMED;
431}
432
433
434void unarm_missile (void)
435{
436 missile_target = MISSILE_UNARMED;
437 snd_play_sample (SND_BOOP);
438}
439
440void fire_missile (void)
441{
442 int newship;
443 struct univ_object *ns;
444 Matrix rotmat;
445
446 if (missile_target < 0)
447 return;
448
449 set_init_matrix (rotmat);
450 rotmat[2].z = 1.0;
451 rotmat[0].x = -1.0;
452
453 newship = add_new_ship (SHIP_MISSILE, 0, -28, 14, rotmat, 0, 0);
454
455 if (newship == -1)
456 {
457 info_message ("Missile Jammed");
458 return;
459 }
460
461 ns = &universe[newship];
462
463 ns->velocity = flight_speed * 2;
1a8abebd 464 ns->flags |= FLG_TACTICAL;
84bbd123 465 ns->target = missile_target;
466
467 if (universe[missile_target].type > SHIP_ROCK)
468 universe[missile_target].flags |= FLG_ANGRY;
469
470 cmdr.missiles--;
471 missile_target = MISSILE_UNARMED;
472
473 snd_play_sample (SND_MISSILE);
474}
475
476
477
478void track_object (struct univ_object *ship, double direction, Vector nvec)
479{
480 double dir;
481 int rat;
482 double rat2;
483
484 rat = 3;
485 rat2 = 0.111;
486
487 dir = vector_dot_product (&nvec, &ship->rotmat[1]);
488
489 if (direction < -0.861)
490 {
491 ship->rotx = (dir < 0) ? 7 : -7;
492 ship->rotz = 0;
493 return;
494 }
495
496 ship->rotx = 0;
497
498 if ((fabs(dir) * 2) >= rat2)
499 {
500 ship->rotx = (dir < 0) ? rat : -rat;
501 }
502
503 if (abs(ship->rotz) < 16)
504 {
505 dir = vector_dot_product (&nvec, &ship->rotmat[0]);
506
507 ship->rotz = 0;
508
509 if ((fabs(dir) * 2) > rat2)
510 {
511 ship->rotz = (dir < 0) ? rat : -rat;
512
513 if (ship->rotx < 0)
514 ship->rotz = -ship->rotz;
515 }
516 }
517}
518
519
520
521void missile_tactics (int un)
522{
523 struct univ_object *missile;
524 struct univ_object *target;
525 Vector vec;
526 Vector nvec;
527 double direction;
528 double cnt2 = 0.223;
529
530 missile = &universe[un];
531
532 if (ecm_active)
533 {
534 snd_play_sample (SND_EXPLODE);
535 missile->flags |= FLG_DEAD;
536 return;
537 }
538
539 if (missile->target == 0)
540 {
541 if (missile->distance < 256)
542 {
543 missile->flags |= FLG_DEAD;
544 snd_play_sample (SND_EXPLODE);
545 damage_ship (250, missile->location.z >= 0.0);
546 return;
547 }
548
549 vec.x = missile->location.x;
550 vec.y = missile->location.y;
551 vec.z = missile->location.z;
552 }
553 else
554 {
555 target = &universe[missile->target];
556
557 vec.x = missile->location.x - target->location.x;
558 vec.y = missile->location.y - target->location.y;
559 vec.z = missile->location.z - target->location.z;
560
561 if ((fabs(vec.x) < 256) && (fabs(vec.y) < 256) && (fabs(vec.z) < 256))
562 {
563 missile->flags |= FLG_DEAD;
564
565 if ((target->type != SHIP_CORIOLIS) && (target->type != SHIP_DODEC))
566 explode_object (missile->target);
567 else
568 snd_play_sample (SND_EXPLODE);
569
570 return;
571 }
572
573 if ((rand255() < 16) && (target->flags & FLG_HAS_ECM))
574 {
575 activate_ecm (0);
576 return;
577 }
1a8abebd 578 }
579
580 if ((rand255() < 16) &&
581 (ship_count[SHIP_CORIOLIS] || ship_count[SHIP_DODEC])) {
582 activate_ecm(0);
583 return;
584 }
84bbd123 585
586 nvec = unit_vector(&vec);
587 direction = vector_dot_product (&nvec, &missile->rotmat[2]);
588 nvec.x = -nvec.x;
589 nvec.y = -nvec.y;
590 nvec.z = -nvec.z;
591 direction = -direction;
592
593 track_object (missile, direction, nvec);
594
595 if (direction <= -0.167)
596 {
597 missile->acceleration = -2;
598 return;
599 }
600
601 if (direction >= cnt2)
602 {
603 missile->acceleration = 3;
604 return;
605 }
606
607 if (missile->velocity < 6)
608 missile->acceleration = 3;
609 else
610 if (rand255() >= 200)
611 missile->acceleration = -2;
612 return;
613}
614
615
616
617void launch_shuttle (void)
618{
619 int type;
620
621 if ((ship_count[SHIP_TRANSPORTER] != 0) ||
622 (ship_count[SHIP_SHUTTLE] != 0) ||
623 (rand255() < 253) || (auto_pilot))
624 return;
625
626 type = rand255() & 1 ? SHIP_SHUTTLE : SHIP_TRANSPORTER;
627 launch_enemy (1, type, FLG_HAS_ECM | FLG_FLY_TO_PLANET, 113);
628}
629
630
631void tactics (int un)
632{
633 int type;
634 int energy;
635 int maxeng;
636 int flags;
637 struct univ_object *ship;
638 Vector nvec;
639 double cnt2 = 0.223;
640 double direction;
641 int attacking;
642
643 ship = &universe[un];
644 type = ship->type;
645 flags = ship->flags;
646
647 if ((type == SHIP_PLANET) || (type == SHIP_SUN))
648 return;
649
650 if (flags & FLG_DEAD)
651 return;
652
653 if (flags & FLG_INACTIVE)
654 return;
655
656 if (type == SHIP_MISSILE)
657 {
658 if (flags & FLG_ANGRY)
659 missile_tactics (un);
660 return;
661 }
662
663 if (((un ^ mcount) & 7) != 0)
664 return;
665
666 if ((type == SHIP_CORIOLIS) || (type == SHIP_DODEC))
667 {
668 if (flags & FLG_ANGRY)
669 {
670 if ((rand() & 255) < 240)
671 return;
672
673 if (ship_count[SHIP_VIPER] >= 4)
674 return;
675
676 launch_enemy (un, SHIP_VIPER, FLG_ANGRY | FLG_HAS_ECM, 113);
677 return;
678 }
679
680 launch_shuttle ();
681 return;
682 }
683
684 if (type == SHIP_HERMIT)
685 {
686 if (rand255() > 200)
687 {
688 launch_enemy (un, SHIP_SIDEWINDER + (rand255() & 3), FLG_ANGRY | FLG_HAS_ECM, 113);
1a8abebd 689 ship->flags |= FLG_INACTIVE | FLG_TARGET;
84bbd123 690 }
691
692 return;
693 }
694
695
696 if (ship->energy < ship_list[type]->energy)
697 ship->energy++;
698
699 if ((type == SHIP_THARGLET) && (ship_count[SHIP_THARGOID] == 0))
700 {
1a8abebd 701 ship->flags &= FLG_TARGET | FLG_TACTICAL;
84bbd123 702 ship->velocity /= 2;
703 return;
704 }
705
706 if (flags & FLG_SLOW)
707 {
708 if (rand255() > 50)
709 return;
710 }
711
712 if (flags & FLG_POLICE)
713 {
714 if (cmdr.legal_status >= 64)
715 {
716 flags |= FLG_ANGRY;
717 ship->flags = flags;
718 }
719 }
720
721 if ((flags & FLG_ANGRY) == 0)
722 {
723 if ((flags & FLG_FLY_TO_PLANET) || (flags & FLG_FLY_TO_STATION))
724 {
725 auto_pilot_ship (&universe[un]);
726 }
727
728 return;
729 }
730
731
732 /* If we get to here then the ship is angry so start attacking... */
733
734 if (ship_count[SHIP_CORIOLIS] || ship_count[SHIP_DODEC])
735 {
736 if ((flags & FLG_BOLD) == 0)
737 ship->bravery = 0;
738 }
739
740
741 if (type == SHIP_ANACONDA)
742 {
743 if (rand255() > 200)
744 {
745 launch_enemy (un, rand255() > 100 ? SHIP_WORM : SHIP_SIDEWINDER,
746 FLG_ANGRY | FLG_HAS_ECM, 113);
747 return;
748 }
749 }
750
751
752 if (rand255() >= 250)
753 {
754 ship->rotz = rand255() | 0x68;
755 if (ship->rotz > 127)
756 ship->rotz = -(ship->rotz & 127);
757 }
758
759 maxeng = ship_list[type]->energy;
760 energy = ship->energy;
761
762 if (energy < (maxeng / 2))
763 {
764 if ((energy < (maxeng / 8)) && (rand255() > 230) && (type != SHIP_THARGOID))
765 {
766 ship->flags &= ~FLG_ANGRY;
767 ship->flags |= FLG_INACTIVE;
768 launch_enemy (un, SHIP_ESCAPE_CAPSULE, 0, 126);
769 return;
770 }
771
772 if ((ship->missiles != 0) && (ecm_active == 0) &&
773 (ship->missiles >= (rand255() & 31)))
774 {
775 ship->missiles--;
1a8abebd 776 ship->flags |= FLG_TACTICAL;
84bbd123 777 if (type == SHIP_THARGOID)
778 launch_enemy (un, SHIP_THARGLET, FLG_ANGRY, ship->bravery);
779 else
780 {
781 launch_enemy (un, SHIP_MISSILE, FLG_ANGRY, 126);
1a8abebd 782 ship->flags |= FLG_HOSTILE;
84bbd123 783 info_message ("INCOMING MISSILE");
784 }
785 return;
786 }
787 }
788
789 nvec = unit_vector(&universe[un].location);
790 direction = vector_dot_product (&nvec, &ship->rotmat[2]);
791
792 if ((ship->distance < 8192) && (direction <= -0.833) &&
793 (ship_list[type]->laser_strength != 0))
794 {
795 if (direction <= -0.917)
1a8abebd 796 ship->flags |= FLG_FIRING | FLG_HOSTILE | FLG_TACTICAL;
84bbd123 797
798 if (direction <= -0.972)
799 {
800 damage_ship (ship_list[type]->laser_strength, ship->location.z >= 0.0);
801 ship->acceleration--;
802 if (((ship->location.z >= 0.0) && (front_shield == 0)) ||
803 ((ship->location.z < 0.0) && (aft_shield == 0)))
804 snd_play_sample (SND_INCOMMING_FIRE_2);
805 else
806 snd_play_sample (SND_INCOMMING_FIRE_1);
807 }
808 else
809 {
810 nvec.x = -nvec.x;
811 nvec.y = -nvec.y;
812 nvec.z = -nvec.z;
813 direction = -direction;
814 track_object (&universe[un], direction, nvec);
815 }
816
817// if ((fabs(ship->location.z) < 768) && (ship->bravery <= ((rand255() & 127) | 64)))
818 if (fabs(ship->location.z) < 768)
819 {
820 ship->rotx = rand255() & 0x87;
821 if (ship->rotx > 127)
822 ship->rotx = -(ship->rotx & 127);
823
824 ship->acceleration = 3;
825 return;
826 }
827
828 if (ship->distance < 8192)
829 ship->acceleration = -1;
830 else
831 ship->acceleration = 3;
832 return;
833 }
834
835 attacking = 0;
836
837 if ((fabs(ship->location.z) >= 768) ||
838 (fabs(ship->location.x) >= 512) ||
839 (fabs(ship->location.y) >= 512))
840 {
841 if (ship->bravery > (rand255() & 127))
842 {
843 attacking = 1;
844 nvec.x = -nvec.x;
845 nvec.y = -nvec.y;
846 nvec.z = -nvec.z;
847 direction = -direction;
848 }
849 }
850
851 track_object (&universe[un], direction, nvec);
852
853 if ((attacking == 1) && (ship->distance < 2048))
854 {
855 if (direction >= cnt2)
856 {
857 ship->acceleration = -1;
858 return;
859 }
860
861 if (ship->velocity < 6)
862 ship->acceleration = 3;
863 else
864 if (rand255() >= 200)
865 ship->acceleration = -1;
866 return;
867 }
868
869 if (direction <= -0.167)
870 {
871 ship->acceleration = -1;
872 return;
873 }
874
875 if (direction >= cnt2)
876 {
877 ship->acceleration = 3;
878 return;
879 }
880
881 if (ship->velocity < 6)
882 ship->acceleration = 3;
883 else
884 if (rand255() >= 200)
885 ship->acceleration = -1;
886}
887
888
889void draw_laser_lines (void)
890{
891 if (wireframe)
892 {
893 gfx_draw_colour_line (32 * GFX_SCALE, GFX_VIEW_BY, laser_x, laser_y, GFX_COL_WHITE);
894 gfx_draw_colour_line (48 * GFX_SCALE, GFX_VIEW_BY, laser_x, laser_y, GFX_COL_WHITE);
895 gfx_draw_colour_line (208 * GFX_SCALE, GFX_VIEW_BY, laser_x, laser_y, GFX_COL_WHITE);
896 gfx_draw_colour_line (224 * GFX_SCALE, GFX_VIEW_BY, laser_x, laser_y, GFX_COL_WHITE);
897 }
898 else
899 {
900 gfx_draw_triangle (32 * GFX_SCALE, GFX_VIEW_BY, laser_x, laser_y, 48 * GFX_SCALE, GFX_VIEW_BY, GFX_COL_RED);
901 gfx_draw_triangle (208 * GFX_SCALE, GFX_VIEW_BY, laser_x, laser_y, 224 * GFX_SCALE, GFX_VIEW_BY, GFX_COL_RED);
902 }
903}
904
905
906int fire_laser (void)
907{
908 if ((laser_counter == 0) && (laser_temp < 242))
909 {
910 switch (current_screen)
911 {
912 case SCR_FRONT_VIEW:
913 laser = cmdr.front_laser;
914 break;
915
916 case SCR_REAR_VIEW:
917 laser = cmdr.rear_laser;
918 break;
919
920 case SCR_RIGHT_VIEW:
921 laser = cmdr.right_laser;
922 break;
923
924 case SCR_LEFT_VIEW:
925 laser = cmdr.left_laser;
926 break;
927
928 default:
929 laser = 0;
930 }
931
932 if (laser != 0)
933 {
934 laser_counter = (laser > 127) ? 0 : (laser & 0xFA);
935 laser &= 127;
936 laser2 = laser;
937
938 snd_play_sample (SND_PULSE);
939 laser_temp += 8;
940 if (energy > 1)
941 energy--;
942
943 laser_x = ((rand() & 3) + 128 - 2) * GFX_SCALE;
944 laser_y = ((rand() & 3) + 96 - 2) * GFX_SCALE;
945
946 return 2;
947 }
948 }
949
950 return 0;
951}
952
953
954void cool_laser (void)
955{
956 laser = 0;
957
958 if (laser_temp > 0)
959 laser_temp--;
960
961 if (laser_counter > 0)
962 laser_counter--;
963
964 if (laser_counter > 0)
965 laser_counter--;
966}
967
968
969int create_other_ship (int type)
970{
971 Matrix rotmat;
972 int x,y,z;
973 int newship;
974
975 set_init_matrix (rotmat);
976
977 z = 12000;
978 x = 1000 + (randint() & 8191);
979 y = 1000 + (randint() & 8191);
980
981 if (rand255() > 127)
982 x = -x;
983 if (rand255() > 127)
984 y = -y;
985
986 newship = add_new_ship (type, x, y, z, rotmat, 0, 0);
987
988 return newship;
989}
990
991
992void create_thargoid (void)
993{
994 int newship;
995
996 newship = create_other_ship (SHIP_THARGOID);
997 if (newship != -1)
998 {
1a8abebd 999 universe[newship].flags = FLG_ANGRY | FLG_HAS_ECM | FLG_TARGET;
84bbd123 1000 universe[newship].bravery = 113;
1001
1002 if (rand255() > 64)
1a8abebd 1003 launch_enemy (newship, SHIP_THARGLET, FLG_ANGRY | FLG_HAS_ECM,
1004 96);
1005 in_battle = 1;
84bbd123 1006 }
1007}
1008
1009
1010
1011void create_cougar (void)
1012{
1013 int newship;
1014
1015 if (ship_count[SHIP_COUGAR] != 0)
1016 return;
1017
1018 newship = create_other_ship (SHIP_COUGAR);
1019 if (newship != -1)
1020 {
1021 universe[newship].flags = FLG_HAS_ECM; // | FLG_CLOAKED;
1022 universe[newship].bravery = 121;
1023 universe[newship].velocity = 18;
1024 }
1025}
1026
1027
1028
1029void create_trader (void)
1030{
1031 int newship;
1032 int rnd;
1033 int type;
1034
1035 type = SHIP_COBRA3 + (rand255() & 3);
1036
1037 newship = create_other_ship (type);
1038
1039 if (newship != -1)
1040 {
1041 universe[newship].rotmat[2].z = -1.0;
1042 universe[newship].rotz = rand255() & 7;
1043
1044 rnd = rand255();
1045 universe[newship].velocity = (rnd & 31) | 16;
1046 universe[newship].bravery = rnd / 2;
1047
1048 if (rnd & 1)
1049 universe[newship].flags |= FLG_HAS_ECM;
1050
1a8abebd 1051 if (rnd > 200)
1052 universe[newship].flags |= FLG_ANGRY | FLG_TARGET;
84bbd123 1053 }
1054}
1055
1056
1057void create_lone_hunter (void)
1058{
1059 int rnd;
1060 int type;
1061 int newship;
1062
1063 if ((cmdr.mission == 1) && (cmdr.galaxy_number == 1) &&
1064 (docked_planet.d == 144) && (docked_planet.b == 33) &&
1065 (ship_count[SHIP_CONSTRICTOR] == 0))
1066 {
1067 type = SHIP_CONSTRICTOR;
1068 }
1069 else
1070 {
1071 rnd = rand255();
1072 type = SHIP_COBRA3_LONE + (rnd & 3) + (rnd > 127);
1073 }
1074
1075 newship = create_other_ship (type);
1076
1077 if (newship != -1)
1078 {
1a8abebd 1079 // universe[newship].flags = FLG_ANGRY;
84bbd123 1080 if ((rand255() > 200) || (type == SHIP_CONSTRICTOR))
1081 universe[newship].flags |= FLG_HAS_ECM;
1082
1083 universe[newship].bravery = ((rand255() * 2) | 64) & 127;
1a8abebd 1084 if (type == SHIP_FER_DE_LANCE) {
1085 if (rand255() > 160)
1086 universe[newship].flags |= FLG_ANGRY | FLG_TARGET;
1087 else {
1088 universe[newship].rotmat[2].z = -1.0;
1089 universe[newship].rotz = rand255() & 7;
1090 rnd = rand255();
1091 universe[newship].velocity = (rnd & 31) | 16;
1092 }
1093 }
1094
1095 if (universe[newship].flags & FLG_ANGRY)
1096 in_battle = 1;
84bbd123 1097 }
1098}
1099
1100
1101
1102/* Check for a random asteroid encounter... */
1103
1104void check_for_asteroids (void)
1105{
1106 int newship;
1107 int type;
1108
1109 if ((rand255() >= 35) || (ship_count[SHIP_ASTEROID] >= 3))
1110 return;
1111
1112 if (rand255() > 253)
1113 type = SHIP_HERMIT;
1114 else
1115 type = SHIP_ASTEROID;
1116
1117 newship = create_other_ship (type);
1118
1119 if (newship != -1)
1120 {
1121// universe[newship].velocity = (rand255() & 31) | 16;
1122 universe[newship].velocity = 8;
1123 universe[newship].rotz = rand255() > 127 ? -127 : 127;
1124 universe[newship].rotx = 16;
1125 }
1126}
1127
1128
1129
1130/* If we've been a bad boy then send the cops after us... */
1131
1132void check_for_cops (void)
1133{
1134 int newship;
1135 int offense;
1136
1137 offense = carrying_contraband() * 2;
1138 if (ship_count[SHIP_VIPER] == 0)
1139 offense |= cmdr.legal_status;
1140
1141 if (rand255() >= offense)
1142 return;
1143
1144 newship = create_other_ship (SHIP_VIPER);
1145
1146 if (newship != -1)
1147 {
1a8abebd 1148 universe[newship].flags |= FLG_ANGRY;
84bbd123 1149 if (rand255() > 245)
1150 universe[newship].flags |= FLG_HAS_ECM;
1151
1152 universe[newship].bravery = ((rand255() * 2) | 64) & 127;
1153 }
1154}
1155
1156
1157void check_for_others (void)
1158{
1159 int x,y,z;
1160 int newship;
1161 Matrix rotmat;
1162 int gov;
1163 int rnd;
1164 int type;
1165 int i;
1166
1167 gov = current_planet_data.government;
1168 rnd = rand255();
1169
1170 if ((gov != 0) && ((rnd >= 90) || ((rnd & 7) < gov)))
1171 return;
1172
1173 if (rand255() < 100)
1174 {
1175 create_lone_hunter();
1176 return;
1177 }
1178
1179 /* Pack hunters... */
1180
1181 set_init_matrix (rotmat);
1182
1183 z = 12000;
1184 x = 1000 + (randint() & 8191);
1185 y = 1000 + (randint() & 8191);
1186
1187 if (rand255() > 127)
1188 x = -x;
1189 if (rand255() > 127)
1190 y = -y;
1191
1192 rnd = rand255() & 3;
1193
1194 for (i = 0; i <= rnd; i++)
1195 {
1196 type = SHIP_SIDEWINDER + (rand255() & rand255() & 7);
1197 newship = add_new_ship (type, x, y, z, rotmat, 0, 0);
1198 if (newship != -1)
1199 {
1a8abebd 1200 universe[newship].flags |= FLG_ANGRY | FLG_TARGET;
84bbd123 1201 if (rand255() > 245)
1202 universe[newship].flags |= FLG_HAS_ECM;
1203
1204 universe[newship].bravery = ((rand255() * 2) | 64) & 127;
1205 in_battle++;
1206 }
1207 }
1208
1209}
1210
1211
1212void random_encounter (void)
1213{
1214 if ((ship_count[SHIP_CORIOLIS] != 0) || (ship_count[SHIP_DODEC] != 0))
1215 return;
1216
1217 if (rand255() == 136)
1218 {
1219 if (((int)(universe[0].location.z) & 0x3e) != 0)
1220 create_thargoid ();
1221 else
1222 create_cougar();
1223
1224 return;
1225 }
1226
1227 if ((rand255() & 7) == 0)
1228 {
1229 create_trader();
1230 return;
1231 }
1232
1233 check_for_asteroids();
1234
1235 check_for_cops();
1236
1237 if (ship_count[SHIP_VIPER] != 0)
1238 return;
1239
1240 if (in_battle)
1241 return;
1242
1243 if ((cmdr.mission == 5) && (rand255() >= 200))
1244 create_thargoid ();
1245
1246 check_for_others();
1247}
1248
1249
1250void abandon_ship (void)
1251{
1252 int i;
1253
1254 cmdr.escape_pod = 0;
1255 cmdr.legal_status = 0;
1256 cmdr.fuel = myship.max_fuel;
1257
1258 for (i = 0; i < NO_OF_STOCK_ITEMS; i++)
1259 cmdr.current_cargo[i] = 0;
1260
1261 snd_play_sample (SND_DOCK);
1262 dock_player();
1263 current_screen = SCR_BREAK_PATTERN;
1264}
1265