Wing Commander
Reconstructed Win32 source (1996)
Loading...
Searching...
No Matches
fl.c
Go to the documentation of this file.
1/**
2 * @file
3 * @ingroup flight
4 * @brief Flight manoeuvre handlers and their dispatch.
5 *
6 * Address range 4060a0-40770f. The Mac fl symbol run corroborates this
7 * group; its dispatch tables precede the cutscene data.
8 */
9#include "wc1.h"
10#include <malloc.h>
11#include <float.h>
12#include <assert.h>
13
14typedef void (*ShipManeuverHandler)(short, short);
15
16/* 0x00465678 */
17static unsigned char abManeuverRerollChance[47] = {
18 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
19 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
20 0, 0, 0, 0, 3, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0
21};
23 /* 00 */ (void (*)(short, short))Mnone,
24 /* 01 */ (void (*)(short, short))Mnone,
25 /* 02 */ Mveer_away,
26 /* 03 */ (void (*)(short, short))Mreset,
27 /* 04 */ (void (*)(short, short))Mfull_ahead,
28 /* 05 */ (void (*)(short, short))Mthink,
29 /* 06 */ Mram_missile,
30 /* 07 */ (void (*)(short, short))Mturn_n_kick,
31 /* 08 */ (void (*)(short, short))Mtight_loop,
32 /* 09 */ (void (*)(short, short))Mhard_break,
33 /* 10 */ Msit_n_spin,
34 /* 11 */ Mturn_n_spin,
35 /* 12 */ Mburnout,
36 /* 13 */ (void (*)(short, short))Mwabble,
37 /* 14 */ (void (*)(short, short))Mroll_over,
38 /* 15 */ (void (*)(short, short))Mhard_turn,
39 /* 16 */ Mfish_hook,
40 /* 17 */ (void (*)(short, short))Msplit_left,
41 /* 18 */ Msit_n_fire,
42 /* 19 */ (void (*)(short, short))Mkickit,
43 /* 20 */ (void (*)(short, short))Mturn_n_kick,
44 /* 21 */ (void (*)(short, short))Mrout_me,
45 /* 22 */ (void (*)(short, short))Mdrop_a_mine,
46 /* 23 */ (void (*)(short, short))Msplit_right,
47 /* 24 */ Mzig_zag,
48 /* 25 */ Mgloat,
49 /* 26 */ Mtail_fire,
50 /* 27 */ Mtarget_laser,
51 /* 28 */ Mtarget_missile,
52 /* 29 */ Mstrafe_enemy,
53 /* 30 */ Mbest_strafe,
54 /* 31 */ Mstrafe_n_roll,
55 /* 32 */ Mkill_missile,
56 /* 33 */ Msuicide_run,
57 /* 34 */ Mzig_zag_pitch,
58 /* 35 */ ShipAiState35,
59 /* 36 */ Mbest_strafe,
60 /* 37 */ Mget_distance,
61 /* 38 */ (void (*)(short, short))Mcorkscrew,
62 /* 39 */ Mtry2tail,
63 /* 40 */ Mzip_past,
64 /* 41 */ (void (*)(short, short))Mbuzz_debris,
65 /* 42 */ Mline_up_drop,
66 /* 43 */ Mchill,
67 /* 44 */ (void (*)(short, short))ShipAiState44,
68 /* 45 */ Mbest_strafe,
69 /* 46 */ (void (*)(short, short))Mreset
70}; /* 0x004656a8 */
71
72static short nManeuverProximityRange; /* 0x00475e78 */
73static unsigned char bCurrentManeuverReroll; /* 0x00475e7c */
74
75/* Linker commons defined here; LINK orders them by identifier hash. */
76short nScrambleCanopyOffset; /* 0x005a8736 */
77short nFuneralMainDist; /* 0x005a8738 */
78signed char bScrambleCanopyClosed; /* 0x005a873a */
79short nCutsceneFuneralGuardFrame; /* 0x005a873c */
81struct Shape *pScrambleOverlayShape; /* 0x005a8744 */
82
83/* Function start: 0x4060A0 */
84void SetManeuverProximityRange(unsigned short v)
85{
87}
88
89/* Function start: 0x4060B0 */
95
96/* Function start: 0x4060D0 */
97void Mline_up_drop(short ship, short target)
98{
99 /* The shipped comparison normalizes this test to 0/1, then compares it
100 with 9. We therefore believe this completion path is unreachable. */
101 if ((aeSpecialManeuvers[target] ==
103 maneuver_complete(ship);
104 return;
105 }
106 if (no_goal(ship) != 0) {
108 anRollGoal[ship] = 360;
109 }
110}
111
112/* Function start: 0x406130 */
113void Mwabble(short ship)
114{
115 short choice;
116
117 asShipTotal[ship]++;
118 if (asShipTotal[ship] > 20) {
119 maneuver_complete(ship);
120 return;
121 }
122
124 if (no_goal(ship) != 0) {
125 choice = RandomBelowOrEqual(2);
126 switch (choice) {
127 case 0:
128 anYawTarget[ship] = signed_random(6) * 5;
129 break;
130 case 1:
131 anPitchGoal[ship] = signed_random(6) * 5;
132 break;
133 default:
134 anRollGoal[ship] = signed_random(10) * 5;
135 break;
136 }
137 }
138}
139
140/* Function start: 0x4061E0 */
141void advance(short ship)
142{
144 acShipSequence[ship] = acShipSequence[ship] + 1;
145}
146
147/* Function start: 0x406200 */
148void ShipAiState35(short ship, short target)
149{
150 (void)target;
151
152 switch (acShipSequence[ship]) {
153 case 0:
154 if (nTgtRange < 750 ||
155 ++asShipTotal[ship] > 10) {
156 advance(ship);
157 asShipTotal[ship] = 0;
158 }
159 break;
160 case 1:
161 veer_random(ship, 45);
162 advance(ship);
163 break;
164 case 2:
165 if (++asShipTotal[ship] > 5) {
166 acShipSequence[ship] = 0;
167 asShipTotal[ship] = 0;
168 }
169 if (nTargetFacingValue < 75)
170 advance(ship);
171 break;
172 case 3:
173 point_ship(ship, 0, &vToTgt);
174 approach_speed(ship, 0x500);
175 if (nFacingToTargetValue > 10)
177 if (nTgtRange > 1500 ||
179 maneuver_complete(ship);
180 break;
181 }
182}
183
184/* Function start: 0x406310 */
185void Mfull_ahead(short ship)
186{
187 short *counter;
188 short count;
189
191 counter = &asShipTotal[ship];
192 count = *counter;
193 *counter = count - 1;
194 if (count < 1)
195 maneuver_complete(ship);
196}
197
198/* Function start: 0x406350 */
199void Mchill(short ship, short target)
200{
201 FixedVector destination;
202
203 get_front_spot(target, 900, &destination);
204 chase_location(ship, &destination, target);
205 if (close_behind(1000) != 0)
206 reset_maneuver(ship, acShipSequence[ship]);
207}
208
209/* Function start: 0x4063B0 */
210void Mdrop_a_mine(short ship)
211{
212 short weapon;
213
214 weapon = -1;
215 if (nTgtRange > 1500)
216 weapon = mine_available(ship);
217 if (weapon != -1)
218 fire_weapon(ship, weapon);
220 maneuver_complete(ship);
221}
222
223/* Function start: 0x406400 */
224void Mthink(short ship)
225{
227 if (asShipTotal[ship] == 0)
228 asShipTotal[ship] = 2;
229 if (--asShipTotal[ship] <= 1)
230 maneuver_complete(ship);
231}
232
233/* Function start: 0x406440 */
234void Mtight_loop(short ship)
235{
237 switch (acShipSequence[ship]) {
238 case 0:
239 anPitchGoal[ship] = 180;
240 advance(ship);
241 return;
242 case 1:
243 if (no_goal(ship) != 0)
244 advance(ship);
246 break;
247 case 2:
248 anPitchGoal[ship] = 180;
249 advance(ship);
250 return;
251 case 3:
252 if (no_goal(ship) != 0)
253 maneuver_complete(ship);
254 break;
255 default:
256 maneuver_complete(ship);
257 break;
258 }
259}
260
261/* Function start: 0x4064F0 */
262void Mhard_break(short ship)
263{
264 short advanceSequence;
265
266 advanceSequence = 1;
267 switch (acShipSequence[ship]) {
268 case 0:
270 break;
271 case 1:
272 advanceSequence = ++asShipTotal[ship] > 3;
273 if (advanceSequence != 0)
274 asShipTotal[ship] = 0;
275 break;
276 case 2:
277 fire_super_brake(ship);
278 break;
279 case 3:
280 advanceSequence = ++asShipTotal[ship] > 3;
281 if (advanceSequence != 0)
282 maneuver_complete(ship);
283 break;
284 }
285 if (advanceSequence != 0)
286 advance(ship);
287}
288
289/* Function start: 0x4065A0 */
290void Msit_n_spin(short ship, short target)
291{
292 short advanceSequence;
293 FixedVector destination;
294
295 advanceSequence = 1;
296 switch (acShipSequence[ship]) {
297 case 0:
298 if (++asShipTotal[ship] < 4) {
299 approach_speed(ship, anShipSpeed[target]);
301 nTgtRange * 2, &destination);
303 &destination, &destination);
304 point_ship_at_point(ship, &destination);
305 advanceSequence = 0;
306 } else {
307 asShipTotal[ship] = 0;
308 }
309 break;
310 case 1:
311 steady_object(ship);
312 if (close_behind(1000) == 0) {
313 advanceSequence = 0;
315 acShipSequence[ship] = 10;
316 }
317 break;
318 case 2:
319 break;
320 case 3:
321 if (abs(anShipSpeed[ship] -
322 anShipSpeed[target]) < 0x200) {
323 approach_speed(ship, anShipSpeed[target]);
324 advanceSequence = 0;
325 }
326 break;
327 case 4:
329 break;
330 case 5:
331 steady_object(ship);
332 point_ship_at_object(ship, target);
333 break;
334 case 6:
335 advanceSequence = no_goal(ship);
336 break;
337 case 7:
338 if (nFacingToTargetValue > 85)
339 fire(ship, target);
340 if (++asShipTotal[ship] <= 5)
341 advanceSequence = 0;
342 break;
343 case 8:
344 veer_random(ship, 35);
345 break;
346 case 9:
347 advanceSequence = no_goal(ship);
348 break;
349 case 10:
352 break;
353 }
354 if (advanceSequence != 0)
355 advance(ship);
356}
357
358/* Function start: 0x4067A0 */
359void Mturn_n_spin(short ship, short target)
360{
361 short advanceSequence;
362
363 advanceSequence = 1;
364 switch (acShipSequence[ship]) {
365 case 0:
366 veer_random(ship, 90);
367 break;
368 case 1:
369 advanceSequence = ++asShipTotal[ship] > 2;
370 break;
371 case 2:
372 advanceSequence = nTargetFacingValue <= 80;
373 if (advanceSequence != 0) {
375 point_ship_at_object(ship, target);
376 } else {
377 maneuver_complete(ship);
378 }
379 break;
380 case 3:
381 if (no_goal(ship) != 0)
382 maneuver_complete(ship);
383 break;
384 }
385 if (advanceSequence != 0)
386 advance(ship);
387}
388
389/* Function start: 0x406860 */
390void Mburnout(short ship, short target)
391{
392 (void)target;
393
394 switch (acShipSequence[ship]) {
395 case 0:
396 fire_afterburner(ship, 10);
397 advance(ship);
398 break;
399 case 1:
401 anYawTarget[ship] = 180;
402 advance(ship);
403 }
404 break;
405 default:
406 if (no_goal(ship) != 0)
407 maneuver_complete(ship);
408 break;
409 }
410}
411
412/* Function start: 0x4068D0 */
413void Mkickit(short ship)
414{
415 switch (acShipSequence[ship]) {
416 case 0:
417 fire_afterburner(ship, 10);
418 advance(ship);
419 break;
420 default:
421 if (aeSpecialManeuvers[ship] ==
423 maneuver_complete(ship);
424 break;
425 }
426}
427
428/* Function start: 0x406910 */
429void Mturn_n_kick(short ship)
430{
431 switch (acShipSequence[ship]) {
432 case 0:
433 veer_random(ship, 90);
434 advance(ship);
435 break;
436 case 1:
437 if (no_goal(ship) != 0) {
438 fire_afterburner(ship, 10);
439 advance(ship);
440 } else {
442 }
443 break;
444 case 2:
446 maneuver_complete(ship);
447 break;
448 }
449}
450
451/* Function start: 0x406990 */
452void Mroll_over(short ship)
453{
454 if (acShipSequence[ship] == 0) {
455 advance(ship);
456 anRollGoal[ship] =
457 RandomBelowOrEqual(2) * 360 - 180;
458 } else if (anRollGoal[ship] == 0) {
459 maneuver_complete(ship);
460 } else {
462 }
463}
464
465/* Function start: 0x4069F0 */
466void Mhard_turn(short ship)
467{
469 switch (acShipSequence[ship]) {
470 case 0:
471 anYawTarget[ship] =
472 RandomBelowOrEqual(2) * 360 - 180;
473 advance(ship);
474 break;
475 default:
476 if (no_goal(ship) != 0)
477 maneuver_complete(ship);
478 break;
479 }
480}
481
482/* Function start: 0x406A50 */
483void Mfish_hook(short ship, short target)
484{
485 short advanceSequence = 1;
486
487 (void)target;
488 switch (acShipSequence[ship]) {
489 case 0:
490 anYawTarget[ship] =
491 RandomBelowOrEqual(2) * 240 - 120;
492 fire_afterburner(ship, 5);
493 break;
494 case 1:
495 advanceSequence = no_goal(ship);
497 break;
498 case 2:
499 fire_super_brake(ship);
500 anYawTarget[ship] =
501 RandomBelowOrEqual(2) * 90 - 45;
502 break;
503 case 3:
504 advanceSequence =
507 real_velocity(ship);
508 break;
509 case 4:
510 advanceSequence = no_goal(ship);
511 break;
512 case 5:
513 fire_afterburner(ship, 10);
514 break;
515 default:
516 if (normal_speed(ship) != 0)
517 maneuver_complete(ship);
518 break;
519 }
520 if (advanceSequence != 0)
521 advance(ship);
522}
523
524/* Function start: 0x406B60 */
525void Mtry2tail(short ship, short target)
526{
527 if (unactive(target) == 0) {
529 if (no_goal(ship) != 0)
530 point_ship_at_object(ship, target);
531 if (RandomBelowOrEqual(100) < 4)
532 veer_random(ship, 5);
533 } else {
534 maneuver_complete(ship);
535 }
536}
537
538/* Function start: 0x406BD0 */
539void Msplit_left(short ship)
540{
541 switch (acShipSequence[ship]) {
542 case 0:
543 anYawTarget[ship] = 90;
544 advance(ship);
545 break;
546 default:
547 if (no_goal(ship) != 0)
548 maneuver_complete(ship);
549 break;
550 }
551}
552
553/* Function start: 0x406C20 */
554void Msplit_right(short ship)
555{
556 switch (acShipSequence[ship]) {
557 case 0:
558 anYawTarget[ship] = -90;
559 advance(ship);
560 break;
561 default:
562 if (no_goal(ship) != 0)
563 maneuver_complete(ship);
564 break;
565 }
566}
567
568/* Function start: 0x406C70 */
569void Mgloat(short ship, short target)
570{
571 switch (acShipSequence[ship]) {
572 case 0:
574 advance(ship);
575 break;
576 case 1:
577 anPitchGoal[ship] = 15;
578 if (RandomBelow(100) < 50)
579 advance(ship);
580 break;
581 default:
582 anPitchGoal[ship] = -30;
583 if (RandomBelow(100) < 50) {
584 if (++asShipTotal[ship] < 10)
585 acShipSequence[ship] = 1;
586 else
587 maneuver_complete(ship);
588 }
589 break;
590 }
591}
592
593/* Function start: 0x406D20 */
594void Mtail_fire(short ship, short target)
595{
596 if (no_goal(ship) != 0)
597 point_ship_at_object(ship, target);
598 chase_speed(ship,
599 (short)((asObjectCollisionRadius[target] +
600 asObjectCollisionRadius[ship] * 6) >> 1));
601 fire_when_ready(ship, 1);
602}
603
604/* Function start: 0x406D80 */
605void Mzip_past(short ship, short target)
606{
607 if (unactive(target) == 0) {
608 if (close_behind(
609 asObjectCollisionRadius[target] + 2000) != 0) {
610 Mtail_fire(ship, target);
611 return;
612 }
614 if (no_goal(ship) != 0) {
615 if (nTargetFacingValue > 80)
616 point_ship_below_object(ship, target);
617 else
618 point_ship_behind_object(ship, target);
619 }
620 } else {
621 maneuver_complete(ship);
622 }
623}
624
625/* Function start: 0x406E10 */
626void Mtarget_missile(short ship, short target)
627{
628 int objectIndex;
629 short object;
630
631 if (no_goal(ship) != 0)
632 point_ship_at_object(ship, target);
634
635 for (object = 0; object < 10; object++) {
636 objectIndex = object;
637 if (acObjOwnersTable[objectIndex] == ship &&
638 aeObjectClass[objectIndex] == OBJECT_CLASS_MISSILE) {
640 return;
641 }
642 }
643
644 if (nFacingToTargetValue > 85 &&
645 nTgtRange < 6000 &&
646 (nTargetFacingValue > 80 ||
647 nTargetFacingValue < -80) &&
648 RandomBelowOrEqual(5) == 0) {
649 fire_missile(ship);
650 maneuver_complete(ship);
651 }
652}
653
654/* Function start: 0x406EC0 */
655void Mram_missile(short ship, short target)
656{
658 if (no_goal(ship) != 0)
659 point_ship_at_object(ship, target);
660 if (nFacingToTargetValue > 75 &&
661 nTgtRange < 6000) {
662 fire_missile(ship);
663 maneuver_complete(ship);
664 }
665}
666
667/* Function start: 0x406F20 */
668void Mbuzz_debris(short ship)
669{
670 switch (acShipSequence[ship]) {
671 case 0:
672 veer_random(ship, 10);
673 advance(ship);
674 break;
675 case 1:
676 if (no_goal(ship) != 0) {
677 fire_afterburner(ship, 10);
678 advance(ship);
679 } else {
681 }
682 break;
683 default:
684 if (aeSpecialManeuvers[ship] ==
686 maneuver_complete(ship);
687 } else if (nFacingToTargetValue > 95) {
688 veer_random(ship, 10);
689 }
690 break;
691 }
692}
693
694/* Function start: 0x406FB0 */
695void Mstrafe_enemy(short ship, short target)
696{
697 short aimed;
698
700 if (abs(anPitchGoal[ship]) != 0 ||
701 abs(anYawTarget[ship]) != 0)
702 aimed = 0;
703 else
704 aimed = 1;
705 if (aimed != 0) {
706 ship_vs_ship(ship, target);
707 point_ship_at_object(ship, target);
708 }
709 fire_when_ready(ship, (short)(aimed == 0));
710}
711
712/* Function start: 0x407030 */
713void Mbest_strafe(short ship, short target)
714{
715 if (nTargetFacingValue < 0x50) {
716 Mstrafe_enemy(ship, target);
717 return;
718 }
719 Mzip_past(ship, target);
720}
721
722/* Function start: 0x407060 */
723void Msit_n_fire(short ship, short target)
724{
726 Mbest_strafe(ship, target);
727 return;
728 }
729 if (no_goal(ship) != 0)
730 point_ship_at_object(ship, target);
731 if (nTgtRange > 3000)
733 else
735 fire_when_ready(ship, 1);
736}
737
738/* Function start: 0x4070D0 */
739void Mstrafe_n_roll(short ship, short target)
740{
741 if (0 < asObjectCounterArray[ship]) {
742 anRollGoal[ship] = 0x2d;
743 return;
744 }
745 Mstrafe_enemy(ship, target);
746}
747
748/* Function start: 0x407100 */
749void Mkill_missile(short ship, short target)
750{
751 if (missile_on_tail(ship) == 0) {
752 maneuver_complete(ship);
753 return;
754 }
756 if (nFacingToTargetValue < 0) {
758 Mfish_hook(ship, target);
759 return;
760 }
761 if (nFacingToTargetValue < 80) {
763 Mburnout(ship, target);
764 return;
765 }
767 if (nTgtRange < 8000)
768 fire(ship, acShipTargetTable[ship]);
769}
770
771/* Function start: 0x4071B0 */
772void Msuicide_run(short ship, short target)
773{
775 if (no_goal(ship) != 0)
776 point_ship_at_object(ship, target);
777}
778
779/* Function start: 0x4071E0 */
780void Mget_distance(short ship, short target)
781{
782 short amount;
783
784 amount = nTgtRange;
785 if (amount > 2000) {
786 maneuver_complete(ship);
787 return;
788 }
789 if (amount < 700 && normal_speed(ship) != 0)
790 fire_afterburner(ship, 10);
791 else
793 if (nFacingToTargetValue > 0 && no_goal(ship) != 0) {
794 amount = MinShort(20, nFacingToTargetValue);
795 steer_away_from_object(ship, target, amount);
796 }
797}
798
799/* Function start: 0x407270 */
800void general_zig(short ship, short target, short pitch)
801{
802 short complete = 1;
803
804 (void)target;
806 switch (acShipSequence[ship] % 6) {
807 case 0:
808 anYawTarget[ship] = -35;
809 anPitchGoal[ship] = pitch;
810 break;
811 case 1:
812 case 4:
813 complete = no_goal(ship);
814 asShipTotal[ship] = 0;
815 break;
816 case 2:
817 case 5:
818 complete = ++asShipTotal[ship] >= 4;
819 break;
820 case 3:
821 pitch = -pitch;
822 anYawTarget[ship] = 35;
823 anPitchGoal[ship] = pitch;
824 break;
825 }
826 if (acShipSequence[ship] >= 12)
827 maneuver_complete(ship);
828 if (complete != 0)
829 advance(ship);
830}
831
832/* Function start: 0x407350 */
833void Mzig_zag(short ship, short target)
834{
835 general_zig(ship, target, 0);
836}
837
838/* Function start: 0x407370 */
839void Mzig_zag_pitch(short ship, short target)
840{
841 general_zig(ship, target, 0x23);
842}
843
844/* Function start: 0x407390 */
845void Mcorkscrew(short ship)
846{
848 if (no_goal(ship) != 0) {
849 if (--asShipTotal[ship] <= 0) {
850 switch (acShipSequence[ship] % 4) {
851 case 0:
852 anYawTarget[ship] = -20;
853 break;
854 case 1:
855 case 3:
856 anRollGoal[ship] = 20;
857 break;
858 case 2:
859 anYawTarget[ship] = 20;
860 break;
861 }
862 asShipTotal[ship] = 4;
863 advance(ship);
864 }
865 }
866 if (acShipSequence[ship] > 8)
867 maneuver_complete(ship);
868}
869
870/* Function start: 0x407450 */
871void Mveer_away(short ship, short target)
872{
873 switch (acShipSequence[ship]) {
874 case 0:
875 if (nFacingToTargetValue > 80)
876 steer_away_from_object(ship, target, 40);
877 else
878 steer_away_from_object(ship, target, 10);
879 advance(ship);
880 return;
881 default:
882 break;
883 }
884 if (asObjectCollisionRadius[target] * 3 <
885 nTgtRange) {
886 veer_random(ship, 8);
887 maneuver_complete(ship);
888 return;
889 }
890 if (no_goal(ship) != 0) {
891 if (nFacingToTargetValue > 80) {
892 steer_away_from_object(ship, target, 40);
893 } else if (nFacingToTargetValue < -65 ||
894 RandomBelowOrEqual(100) < 4) {
895 veer_random(ship, 16);
896 }
897 }
899 RandomBelowOrEqual(100) < 10) &&
900 normal_speed(ship) != 0) {
901 fire_afterburner(ship, 10);
902 return;
903 }
905}
906
907/* Function start: 0x407560 */
908void ShipAiState44(short ship)
909{
910 acShipStressList[ship] = 0;
911 maneuver_complete(ship);
912}
913
914/* Function start: 0x407580 */
915void Mtarget_laser(short ship, short target)
916{
917 Mbest_strafe(ship, target);
918}
919
920/* Function start: 0x4075A0 */
921void Mrout_me(short ship)
922{
923 try2rout(ship);
924}
925
926/* Function start: 0x4075B0 */
927/* Empty in the original: dispatch-table slots 0 and 1 (no-op / invalid state). */
928void Mnone(void)
929{
930}
931
932/* Function start: 0x4075C0 */
933void Mreset(short ship)
934{
935 maneuver_complete(ship);
936}
937
938/* Function start: 0x4075D0 */
939void perform_maneuver(short obj)
940{
941 short target = acShipTargetTable[obj];
942 enum ShipManeuver previous = aeShipManeuversTable[obj];
943 short range;
944
946 abManeuverRerollChance[previous];
947 ship_vs_ship(obj, target);
948 range = nTgtRange;
949 if (nTargetFacingValue < 0)
950 SetManeuverProximityRange((unsigned short)((asObjectCollisionRadius[target] +
951 asObjectCollisionRadius[obj] * 4) >> 1));
952 else
953 SetManeuverProximityRange((unsigned short)((asObjectCollisionRadius[target] +
954 asObjectCollisionRadius[obj] * 6) >> 1));
955
956 if (unactive(target) != 0) {
957 switch (aeShipManeuversTable[obj]) {
959 Mveer_away(obj, target);
960 break;
961 case MANEUVER_GLOAT:
962 Mgloat(obj, target);
963 break;
965 Mline_up_drop(obj, target);
966 break;
967 default:
969 break;
970 }
971 } else if (aeShipManeuversTable[obj] >= 0 &&
972 aeShipManeuversTable[obj] < 47) {
974 aeShipManeuversTable[obj]](obj, target);
975 } else {
977 }
978
979 if (range < nManeuverProximityRange) {
980 try2reset_maneuver(obj, 2);
981 } else if (aeShipManeuversTable[obj] == previous &&
982 RandomBelowOrEqual(100) <
985 }
986}
void(__cdecl *pIxFree)(void *)
static ShipManeuverHandler apShipAiManeuverHandlers[47]
Definition fl.c:22
static short nManeuverProximityRange
Definition fl.c:72
void(*) ShipManeuverHandler(short, short)
Definition fl.c:14
static unsigned char abManeuverRerollChance[47]
Definition fl.c:17
static unsigned char bCurrentManeuverReroll
Definition fl.c:73
short anRollGoal[16]
Definition ending.c:21
signed char acShipStressList[16]
Definition ending.c:20
enum ShipManeuver aeShipManeuversTable[12]
Definition screen.c:25
ObjectTypeData aObjectTypeData[OBJECT_TYPE_COUNT]
Definition objdata.c:86
short asShipTotal[16]
Definition game.c:551
short anPitchGoal[16]
Definition screen.c:13
short nTgtRange
Definition joycal.c:27
struct Shape * pScrambleOverlayShape
Definition fl.c:81
short nFacingToTargetValue
Definition screen.c:19
FixedVector vToTgt
Definition comm.c:58
enum ObjectClass aeObjectClass[SPACE_OBJECT_COUNT]
Definition video.c:21
short asObjectCollisionRadius[64]
Definition ending.c:27
int anShipSpeed[64]
Definition data.c:248
ShortPoint stScrambleOverlay
Definition fl.c:80
short nScrambleCanopyOffset
Definition fl.c:76
short nTargetFacingValue
Definition input.c:17
short asObjectCounterArray[SPACE_OBJECT_COUNT]
Definition game.c:547
signed char acObjOwnersTable[64]
Definition joycal.c:29
signed char bScrambleCanopyClosed
Definition fl.c:78
enum ObjectType aeObjectTypeList[SPACE_OBJECT_COUNT]
Definition data.c:255
short nFuneralMainDist
Definition fl.c:77
char acShipSequence[10]
Definition input.c:16
FixedVector aShipPositionsArray[SPACE_OBJECT_COUNT]
Definition game.c:556
short nTargetShip
Definition game.c:548
FixedVector aShipFwdVec[64]
Definition smart.c:17
signed char acShipTargetTable[16]
Definition joycal.c:30
short anYawTarget[16]
Definition smart.c:22
enum SpecialManeuver aeSpecialManeuvers[12]
Definition game.c:549
short nCutsceneFuneralGuardFrame
Definition fl.c:79
short cruiseVelocity
Definition wcdata.h:379
Umbrella header for the game core.
unsigned int approach_full_speed(short ship)
Definition logic.c:779
unsigned int approach_zero_speed(short ship)
Definition logic.c:746
void Mkill_missile(short ship, short target)
Definition fl.c:749
void Mwabble(short ship)
Definition fl.c:113
unsigned int close_behind()
void Mturn_n_kick(short ship)
Definition fl.c:429
void Mtry2tail(short ship, short target)
Definition fl.c:525
void Mbuzz_debris(short ship)
Definition fl.c:668
void ShipAiState44(short ship)
Definition fl.c:908
void Mroll_over(short ship)
Definition fl.c:452
void Mreset(short ship)
Definition fl.c:933
unsigned int fire_super_brake(short ship)
Definition ship.c:1992
void point_ship_at_object(short obj, short other)
Definition geom.c:812
void perform_maneuver(short obj)
Definition fl.c:939
void ship_vs_ship(short obj, short other)
Definition geom.c:710
unsigned int steady_object(short ship)
Definition ship.c:422
void Mhard_turn(short ship)
Definition fl.c:466
void general_zig(short ship, short target, short pitch)
Definition fl.c:800
void Mtarget_laser(short ship, short target)
Definition fl.c:915
unsigned int get_front_spot(short obj, unsigned short distance, FixedVector *point)
Definition logic.c:794
void fire_afterburner(short obj, short time)
Definition ship.c:1976
int missile_on_tail(short obj)
Definition logic.c:562
void AddFixedVectors(const FixedVector *left, const FixedVector *right, FixedVector *sum)
Definition geom.c:296
void Mbest_strafe(short ship, short target)
Definition fl.c:713
void fire_when_ready(short obj, short aimed)
Definition logic.c:956
void Mstrafe_n_roll(short ship, short target)
Definition fl.c:739
void Mfish_hook(short ship, short target)
Definition fl.c:483
int fire_missile(short ship)
Definition ship.c:1905
void Mgloat(short ship, short target)
Definition fl.c:569
short MinShort(short a, short b)
Definition mathutil.c:20
void Mveer_away(short ship, short target)
Definition fl.c:871
void Msplit_right(short ship)
Definition fl.c:554
void Msit_n_fire(short ship, short target)
Definition fl.c:723
void Mrout_me(short ship)
Definition fl.c:921
void Mburnout(short ship, short target)
Definition fl.c:390
void point_ship(short obj, short turnRate, const FixedVector *direction)
Definition geom.c:793
void Mdrop_a_mine(short ship)
Definition fl.c:210
unsigned int approach_speed(short ship, int targetSpeed)
Definition ship.c:405
short mine_available(short obj)
Definition logic.c:1389
short signed_random(short range)
Definition logic.c:160
void Mkickit(short ship)
Definition fl.c:413
unsigned int chase_location(short obj, const FixedVector *destination, short reference)
Definition smart.c:246
unsigned int set_special(short ship, enum SpecialManeuver special)
Definition logic.c:729
void ScaleFixedVector(const FixedVector *vector, int scale, FixedVector *result)
Definition geom.c:322
void Mram_missile(short ship, short target)
Definition fl.c:655
void Mtail_fire(short ship, short target)
Definition fl.c:594
signed char no_goal(short ship)
Definition logic.c:495
void Mhard_break(short ship)
Definition fl.c:262
void advance(short ship)
Definition fl.c:141
short real_velocity(short obj)
Definition ship.c:431
short RandomBelow(short n)
Definition mathfp.c:29
void Mzig_zag_pitch(short ship, short target)
Definition fl.c:839
void SetManeuverProximityRange(unsigned short v)
Definition fl.c:84
void point_ship_behind_object(short obj, short other)
Definition geom.c:828
void Mline_up_drop(short ship, short target)
Definition fl.c:97
void Mchill(short ship, short target)
Definition fl.c:199
short try2rout(short obj)
Definition logic.c:464
unsigned int veer_random(short obj, short amount)
Definition smart.c:172
void Mstrafe_enemy(short ship, short target)
Definition fl.c:695
void try2reset_maneuver(short obj, short maneuver)
Definition logic.c:720
void Mtight_loop(short ship)
Definition fl.c:234
void Mget_distance(short ship, short target)
Definition fl.c:780
unsigned int approach_cruise_speed(short ship)
Definition logic.c:770
void Mzig_zag(short ship, short target)
Definition fl.c:833
void fire(short obj, short target)
Definition ship.c:1445
void Mthink(short ship)
Definition fl.c:224
unsigned int chase_speed(short obj, short range)
Definition smart.c:672
void Mfull_ahead(short ship)
Definition fl.c:185
void Mtarget_missile(short ship, short target)
Definition fl.c:626
void Mzip_past(short ship, short target)
Definition fl.c:605
void maneuver_complete(short ship)
Definition fl.c:90
void Msuicide_run(short ship, short target)
Definition fl.c:772
short normal_speed(short obj)
Definition logic.c:220
void Msplit_left(short ship)
Definition fl.c:539
void Mnone(void)
Definition fl.c:928
void ShipAiState35(short ship, short target)
Definition fl.c:148
int fire_weapon(short obj, short weapon)
Definition ship.c:1737
void point_ship_at_point(short obj, const FixedVector *point)
Definition geom.c:802
void Msit_n_spin(short ship, short target)
Definition fl.c:290
void Mcorkscrew(short ship)
Definition fl.c:845
void Mturn_n_spin(short ship, short target)
Definition fl.c:359
void reset_maneuver(short ship, short maneuver)
Definition logic.c:712
short RandomBelowOrEqual(short n)
Definition mathfp.c:59
unsigned int unactive(short ship)
Definition logic.c:353
unsigned int steer_away_from_object(short obj, short other, short amount)
Definition smart.c:25
void point_ship_below_object(short obj, short other)
Definition geom.c:839
@ SPECIAL_MANEUVER_NORMAL
Definition wcdata.h:259
@ SPECIAL_MANEUVER_KILL_ENGINES
Definition wcdata.h:264
@ SPECIAL_MANEUVER_NONE
Definition wcdata.h:258
ShipManeuver
Definition wcdata.h:206
@ MANEUVER_ROLL_OVER
Definition wcdata.h:222
@ MANEUVER_FISH_HOOK
Definition wcdata.h:224
@ MANEUVER_GLOAT
Definition wcdata.h:233
@ MANEUVER_CHILL
Definition wcdata.h:251
@ MANEUVER_VEER_AWAY
Definition wcdata.h:210
@ MANEUVER_TAIL_FIRE
Definition wcdata.h:234
@ MANEUVER_NONE
Definition wcdata.h:207
@ MANEUVER_LINE_UP_DROP
Definition wcdata.h:250
@ MANEUVER_STRAFE_ENEMY
Definition wcdata.h:237
@ MANEUVER_BURNOUT
Definition wcdata.h:220
@ OBJECT_CLASS_MISSILE
Definition wcdata.h:49
@ OBJECT_CLASS_CAPITAL_SHIP
Definition wcdata.h:51