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