Wing Commander II
Reconstructed Win32 source (1996)
Loading...
Searching...
No Matches
fl.c
Go to the documentation of this file.
1/*
2 * Flight maneuvers.
3 *
4 * Retail object 0x440490-0x44276F (link order; see docs/ORDER.md).
5 */
6/* This unit owns the fl storage declared in globals.h (as statics). */
7#define FL_C
8#include "game.h"
9
10unsigned char g_abManeuverRerollChance[50] = {
11 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
13 0, 0, 0, 0, 3, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
14 0, 0, 0
15}; /* 0x0049b538 */
16/* perform_maneuver (0x4426AF) dispatches through this table; its guard admits
17 * maneuvers 0 through 0x31, and "Maneuver error %d" follows at 0x49B638. */
18void (*g_apManeuverHandlers[50])(short, short) = {
19 /* 00 */ (void (*)(short, short))Mnone,
20 /* 01 */ (void (*)(short, short))Mnone,
21 /* 02 */ (void (*)(short, short))Mveer_away,
22 /* 03 */ (void (*)(short, short))ShipAiState3,
23 /* 04 */ (void (*)(short, short))Mfull_ahead,
24 /* 05 */ (void (*)(short, short))Mthink,
25 /* 06 */ (void (*)(short, short))Mram_missile,
26 /* 07 */ (void (*)(short, short))Mturn_n_kick,
27 /* 08 */ (void (*)(short, short))Mtight_loop,
28 /* 09 */ (void (*)(short, short))Mhard_break,
29 /* 10 */ (void (*)(short, short))Msit_n_spin,
30 /* 11 */ (void (*)(short, short))Mturn_n_spin,
31 /* 12 */ (void (*)(short, short))Mburnout,
32 /* 13 */ (void (*)(short, short))Mwabble,
33 /* 14 */ (void (*)(short, short))Mroll_over,
34 /* 15 */ (void (*)(short, short))Mhard_turn,
35 /* 16 */ (void (*)(short, short))Mfish_hook,
36 /* 17 */ (void (*)(short, short))Msplit_left,
37 /* 18 */ (void (*)(short, short))Msit_n_fire,
38 /* 19 */ (void (*)(short, short))Mkickit,
39 /* 20 */ (void (*)(short, short))Mturn_n_kick,
40 /* 21 */ (void (*)(short, short))Mrout_me,
41 /* 22 */ (void (*)(short, short))Mdrop_a_mine,
42 /* 23 */ (void (*)(short, short))Msplit_right,
43 /* 24 */ (void (*)(short, short))Mzig_zag,
44 /* 25 */ (void (*)(short, short))Mgloat,
45 /* 26 */ (void (*)(short, short))Mtail_fire,
46 /* 27 */ (void (*)(short, short))Mtarget_laser,
47 /* 28 */ (void (*)(short, short))ShipAiState28,
48 /* 29 */ (void (*)(short, short))Mstrafe_enemy,
49 /* 30 */ (void (*)(short, short))Mbest_strafe,
50 /* 31 */ (void (*)(short, short))Mstrafe_n_roll,
51 /* 32 */ (void (*)(short, short))Mkill_missile,
52 /* 33 */ (void (*)(short, short))Msuicide_run,
53 /* 34 */ (void (*)(short, short))Mzig_zag_pitch,
54 /* 35 */ (void (*)(short, short))ShipAiState35,
55 /* 36 */ (void (*)(short, short))Mtarget_missile,
56 /* 37 */ (void (*)(short, short))Mget_distance,
57 /* 38 */ (void (*)(short, short))Mcorkscrew,
58 /* 39 */ (void (*)(short, short))Mtry2tail,
59 /* 40 */ (void (*)(short, short))Mzip_past,
60 /* 41 */ (void (*)(short, short))Mbuzz_debris,
61 /* 42 */ (void (*)(short, short))Mline_up_drop,
62 /* 43 */ (void (*)(short, short))Mchill,
63 /* 44 */ (void (*)(short, short))ShipAiState44,
64 /* 45 */ (void (*)(short, short))ShipAiState45,
65 /* 46 */ (void (*)(short, short))ShipAiState46,
66 /* 47 */ (void (*)(short, short))ShipAiState47,
67 /* 48 */ (void (*)(short, short))Mbest_strafe,
68 /* 49 */ (void (*)(short, short))Mreset
69};
70
71/* WC2 indexes the reroll table with the ship's current manoeuvre without
72 * checking it, and MANEUVER_NONE is -1. The byte in front of the table is
73 * zero in the retail image, so the port answers zero rather than reproduce
74 * the overrun. */
75#define MANEUVER_REROLL_CHANCE(m) g_abManeuverRerollChance[m]
76
77/* WC2 adds the target's collision radius before it has checked the target, so
78 * with nothing targeted it reads the word at 0x4950e6, in the zero-filled
79 * alignment gap before the radius table. Make that result explicit on the
80 * native port rather than cross a global's sanitizer redzone. */
81#define COLLISION_RADIUS_OF(obj) g_asObjectCollisionRadius[obj]
82
83/* Function start: 0x440490 */
84void HandleUnsupportedManeuver(short maneuver, short ship, short target)
85{
86 if (g_nOriginDevUnlock != 0)
87 printf("Maneuver error %d", maneuver);
88 Mzip_past(ship, target);
89}
90
91/* Function start: 0x4404CC */
92void BeginShipCloak(short ship)
93{
94 if (g_anShipCloakState[ship] != 1) {
95 g_anShipCloakState[ship] = 1;
98 if (g_asObjectScreenX[ship] != -0x7fff &&
100 PlaySfxWaveFileByNumber(44, ship, 0);
101 }
102}
103
104/* Function start: 0x440549 */
105void ResetShipCloakState(short ship)
106{
107 g_anShipCloakState[ship] = 0;
108 g_asShipCloakCooldown[ship] = 40;
109}
110
111/* Function start: 0x440571 */
112void chase_speed(short obj, short range)
113{
114 if (range < g_nTargetRange) {
116 if (range * 2 < g_nTargetRange)
117 fire_afterburner(obj, 2);
118 } else if (range > g_nTargetRange) {
120 } else {
121 approach_speed(obj,
123 g_acShipTarget[obj]]);
124 }
125}
126
127/* Function start: 0x440606 */
128void SetShipAiScratchWord(unsigned short v)
129{
131}
132
133/* Function start: 0x44061B */
134void maneuver_complete(short ship)
135{
138}
139
140/* Function start: 0x440642 */
141void Mline_up_drop(short ship, short target)
142{
143 /* The shipped comparison normalizes this test to 0/1, then compares it
144 with 9. We therefore believe this completion path is unreachable. */
145 if ((g_aeSpecialManeuver[target] ==
147 maneuver_complete(ship);
148 return;
149 }
150 if (CanSetNewShipTurnGoal(ship) != 0) {
151 point_ship_at_point(ship, &g_aShipPosition[target]);
152 g_anRollGoal[ship] = 360;
153 }
154}
155
156/* Function start: 0x4406BA */
157void Mwabble(short ship)
158{
159 g_asShipCount[ship]++;
160 if (g_asShipCount[ship] > 20) {
161 maneuver_complete(ship);
162 return;
163 }
164
165 fire_afterburner(ship, 20);
166 if (CanSetNewShipTurnGoal(ship) != 0) {
167 switch (RandomBelowOrEqual(2)) {
168 case 0:
169 g_anYawGoal[ship] = signed_random(6) * 5;
170 break;
171 case 1:
172 g_anPitchGoal[ship] = signed_random(6) * 5;
173 break;
174 default:
175 g_anRollGoal[ship] = signed_random(10) * 5;
176 }
177 }
178}
179
180/* Function start: 0x4407B0 */
181void advance(short ship)
182{
183 if (g_asShipManeuver[ship] != MANEUVER_NONE)
184 g_acShipSequence[ship]++;
185}
186
187/* Function start: 0x4407DA */
188void ShipAiState35(short ship, short target)
189{
190 HandleUnsupportedManeuver(1, ship, target);
191
192}
193
194/* Function start: 0x4407F7 */
195void Mfull_ahead(short ship, short target)
196{
197 HandleUnsupportedManeuver(2, ship, target);
198
199}
200
201/* Function start: 0x440814 */
202void Mchill(short ship, short target)
203{
204 HandleUnsupportedManeuver(3, ship, target);
205
206}
207
208/* Function start: 0x440831 */
209void Mdrop_a_mine(short ship, short target)
210{
211 HandleUnsupportedManeuver(4, ship, target);
212
213}
214
215/* Function start: 0x44084E */
216void Mthink(short ship, short target)
217{
218 HandleUnsupportedManeuver(5, ship, target);
219
220}
221
222/* Function start: 0x44086B */
223void Mtight_loop(short ship)
224{
226 switch (g_acShipSequence[ship]) {
227 case 0:
228 g_anPitchGoal[ship] = 180;
229 advance(ship);
230 return;
231 case 1:
232 if (no_goal(ship) != 0)
233 advance(ship);
235 break;
236 case 2:
237 g_anPitchGoal[ship] = 180;
238 advance(ship);
239 return;
240 case 3:
241 if (no_goal(ship) != 0)
242 maneuver_complete(ship);
243 break;
244 default:
245 maneuver_complete(ship);
246 }
247}
248
249/* Function start: 0x440967 */
250void Mhard_break(short ship)
251{
252 short advanceSequence;
253
254 advanceSequence = 1;
255 switch (g_acShipSequence[ship]) {
256 case 0:
258 break;
259 case 1:
260 advanceSequence = ++g_asShipCount[ship] > 3;
261 if (advanceSequence != 0)
262 g_asShipCount[ship] = 0;
263 break;
264 case 2:
265 fire_super_brake(ship);
266 break;
267 case 3:
268 advanceSequence = ++g_asShipCount[ship] > 3;
269 if (advanceSequence != 0)
270 maneuver_complete(ship);
271 break;
272 }
273 if (advanceSequence != 0)
274 advance(ship);
275}
276
277#pragma function(labs)
278/* Function start: 0x440A93 */
279void Msit_n_spin(short ship, short target)
280{
281 short advanceSequence;
282 FixedVector aimPoint;
283
284 advanceSequence = 1;
285 switch (g_acShipSequence[ship]) {
286 case 0:
287 if (++g_asShipCount[ship] < 4) {
288 approach_speed(ship, g_anShipSpeed[target]);
290 g_nTargetRange * 2, &aimPoint);
292 &aimPoint, &aimPoint);
293 point_ship_at_point(ship, &aimPoint);
294 advanceSequence = 0;
295 } else {
296 g_asShipCount[ship] = 0;
297 }
298 break;
299 case 1:
300 steady_object(ship);
301 break;
302 case 2:
303 break;
304 case 3:
305 if (labs(g_anShipSpeed[ship] -
306 g_anShipSpeed[target]) < 0x200) {
307 approach_speed(ship, g_anShipSpeed[target]);
308 advanceSequence = 0;
309 }
310 break;
311 case 4:
313 break;
314 case 5:
315 steady_object(ship);
316 point_ship_at_object(ship, target);
317 break;
318 case 6:
319 advanceSequence = no_goal(ship);
320 break;
321 case 7:
322 if (g_nFacingToTarget > 85)
323 fire(ship, target);
324 if (++g_asShipCount[ship] <= 5)
325 advanceSequence = 0;
326 break;
327 case 8:
328 veer_random(ship, 35);
329 break;
330 case 9:
331 advanceSequence = no_goal(ship);
332 break;
333 case 10:
336 break;
337 }
338 if (advanceSequence != 0)
339 advance(ship);
340}
341
342/* Function start: 0x440D0B */
343void Mturn_n_spin(short ship, short target)
344{
345 short advanceSequence;
346
347 advanceSequence = 1;
348 switch (g_acShipSequence[ship]) {
349 case 0:
350 veer_random(ship, 90);
351 break;
352 case 1:
353 ++g_asShipCount[ship];
354 advanceSequence = g_asShipCount[ship] > 2;
355 break;
356 case 2:
357 advanceSequence = g_nTargetFacing <= 80;
358 if (advanceSequence == 0) {
359 maneuver_complete(ship);
360 } else {
362 point_ship_at_object(ship, target);
363 }
364 break;
365 case 3:
366 if (no_goal(ship) != 0)
367 maneuver_complete(ship);
368 break;
369 }
370 if (advanceSequence != 0)
371 advance(ship);
372}
373
374/* Function start: 0x440E46 */
375void Mburnout(short ship, short target)
376{
377 (void)target;
378
379 switch (g_acShipSequence[ship]) {
380 case 0:
381 fire_afterburner(ship, 10);
382 advance(ship);
383 break;
384 case 1:
385 g_anYawGoal[ship] =
386 (short)((RandomBelowOrEqual(2) * 2 - 1) * 90);
387 advance(ship);
388 break;
389 default:
390 if (no_goal(ship) != 0)
391 maneuver_complete(ship);
392 break;
393 }
394}
395
396/* Function start: 0x440F01 */
397void Mkickit(short ship)
398{
399 switch (g_acShipSequence[ship]) {
400 case 0:
401 fire_afterburner(ship, 10);
402 advance(ship);
403 break;
404 default:
405 if (g_aeSpecialManeuver[ship] ==
407 maneuver_complete(ship);
408 }
409}
410
411/* Function start: 0x440F76 */
412void Mturn_n_kick(short ship)
413{
414 short pointed;
415 short obj;
416
417 pointed = 0;
418 switch (g_acShipSequence[ship]) {
419 case 0:
420 for (obj = 0; obj < 10; obj++) {
422 g_acShipTarget[obj] == ship) {
423 point_perpendicular(ship, obj);
424 pointed = 1;
425 break;
426 }
427 }
428 if (pointed == 0)
429 veer_random(ship, 90);
430 advance(ship);
431 break;
432 case 1:
433 if (no_goal(ship) != 0) {
434 fire_afterburner(ship, 10);
435 advance(ship);
436 } else {
438 }
439 break;
440 case 2:
442 maneuver_complete(ship);
443 }
444}
445
446/* Function start: 0x4410C0 */
447void Mroll_over(short ship)
448{
449 if (g_acShipSequence[ship] == 0) {
450 advance(ship);
451 g_anRollGoal[ship] =
452 (RandomBelowOrEqual(2) * 2 - 1) * 180;
453 } else if (g_anRollGoal[ship] == 0) {
454 maneuver_complete(ship);
455 } else {
457 }
458}
459
460/* Function start: 0x441146 */
461void Mhard_turn(short ship)
462{
464 switch (g_acShipSequence[ship]) {
465 case 0:
466 g_anYawGoal[ship] =
467 (RandomBelowOrEqual(2) * 2 - 1) * 180;
468 advance(ship);
469 break;
470 default:
471 if (no_goal(ship) != 0)
472 maneuver_complete(ship);
473 }
474}
475
476/* Function start: 0x4411E1 */
477void Mfish_hook(short ship, short target)
478{
479 short advanceSequence = 1;
480
481 (void)target;
482 switch (g_acShipSequence[ship]) {
483 case 0:
484 g_anYawGoal[ship] =
485 (RandomBelowOrEqual(2) * 2 - 1) * 120;
486 fire_afterburner(ship, 5);
487 break;
488 case 1:
489 advanceSequence = no_goal(ship);
491 break;
492 case 2:
493 fire_super_brake(ship);
494 g_anYawGoal[ship] =
495 (RandomBelowOrEqual(2) * 2 - 1) * 45;
496 break;
497 case 3:
498 advanceSequence =
501 real_velocity(ship);
502 break;
503 case 4:
504 advanceSequence = no_goal(ship);
505 break;
506 case 5:
507 fire_afterburner(ship, 10);
508 break;
509 default:
510 if (normal_speed(ship) != 0)
511 maneuver_complete(ship);
512 }
513 if (advanceSequence != 0)
514 advance(ship);
515}
516
517/* Function start: 0x441379 */
518void Mtry2tail(short ship, short target)
519{
520 FixedVector position;
521
522 if (unactive(target) == 0) {
523 position = g_aShipPosition[target];
524 position_relative(&position, g_aShipRightVector[target],
525 (short)-(g_asObjectCollisionRadius[target] +
526 1000));
527 point_ship_at_point(ship, &position);
528 fire_afterburner(ship, 10);
530 g_nTargetRange < 0x1f40)
531 maneuver_complete(ship);
532 } else {
533 maneuver_complete(ship);
534 }
535}
536
537/* Function start: 0x44145A */
538void Msplit_left(short ship)
539{
541 switch (g_acShipSequence[ship]) {
542 case 0:
543 g_anYawGoal[ship] = 90;
544 advance(ship);
545 break;
546 case 1:
547 fire_afterburner(ship, 10);
548 advance(ship);
549 /* The retail switch falls through into the completion test. */
550 default:
551 if (no_goal(ship) != 0 &&
553 maneuver_complete(ship);
554 break;
555 }
556}
557
558/* Function start: 0x44151B */
559void Msplit_right(short ship)
560{
562 switch (g_acShipSequence[ship]) {
563 case 0:
564 g_anYawGoal[ship] = -90;
565 advance(ship);
566 break;
567 case 1:
568 fire_afterburner(ship, 10);
569 advance(ship);
570 /* The retail switch falls through into the completion test. */
571 default:
572 if (no_goal(ship) != 0 &&
574 maneuver_complete(ship);
575 break;
576 }
577}
578
579/* Function start: 0x4415DC */
580void Mgloat(short ship)
581{
582 switch (g_acShipSequence[ship]) {
583 case 0:
585 advance(ship);
586 break;
587 case 1:
588 g_anPitchGoal[ship] = 15;
589 if (RandomBelow(100) < 50)
590 advance(ship);
591 break;
592 default:
593 g_anPitchGoal[ship] = -30;
594 if (RandomBelow(100) < 50) {
595 if (++g_asShipCount[ship] < 10)
596 g_acShipSequence[ship] = 1;
597 else
598 maneuver_complete(ship);
599 }
600 break;
601 }
602}
603
604/* Function start: 0x4416D5 */
605void Mtail_fire(short ship, short target)
606{
607 if (CanSetNewShipTurnGoal(ship) != 0)
608 point_ship_at_object(ship, target);
609 chase_speed(ship,
610 (short)(g_asObjectCollisionRadius[ship] * 6 +
612 fire(ship, target);
613}
614
615/* Function start: 0x441742 */
616void Mzip_past(short ship, short target)
617{
618 if (unactive(target) == 0) {
619 if (close_behind(
620 g_asObjectCollisionRadius[target] + 2000) != 0) {
621 Mtail_fire(ship, target);
622 } else {
624 if (g_nTargetRange > 3000 &&
626 fire_afterburner(ship, 3);
627 if (CanSetNewShipTurnGoal(ship) != 0) {
628 if (g_nTargetFacing > 80)
629 point_ship_below_object(ship, target);
630 else
631 point_ship_behind_object(ship, target);
632 }
633 }
634 } else {
635 maneuver_complete(ship);
636 }
637}
638
639/* Function start: 0x441837 */
640/* Dispatch slot 47: cloak and break off, or zip past when the cloak is
641 * unavailable. */
642void ShipAiState47(short ship, short target)
643{
644 if (g_asShipCloakCooldown[ship] == 0 &&
645 g_anShipCloakState[ship] == 0) {
646 maneuver_complete(ship);
647 BeginShipCloak(ship);
648 } else {
649 Mzip_past(ship, target);
650 }
651}
652
653/* Function start: 0x441895 */
654/* Dispatch slot 28: unimplemented in WC2. */
655void ShipAiState28(short ship, short target)
656{
657 HandleUnsupportedManeuver(6, ship, target);
658
659}
660
661/* Function start: 0x4418B2 */
662/* Dispatch slot 46: pick a random roll and yaw, burn out of the fight, then
663 * wait for the turn to finish. */
664void ShipAiState46(short ship)
665{
666 switch (g_acShipSequence[ship]) {
667 case 0:
668 g_anRollGoal[ship] =
669 (short)((2 * RandomBelowOrEqual(2) - 1) * 180);
670 g_anYawGoal[ship] =
671 (short)((2 * RandomBelowOrEqual(2) - 1) * 60);
673 fire_afterburner(ship, 10);
674 advance(ship);
675 break;
676 default:
678 if (no_goal(ship) != 0) {
680 maneuver_complete(ship);
681 }
682 }
683}
684
685/* Function start: 0x44199B */
686void Mram_missile(short ship, short target)
687{
689 if (CanSetNewShipTurnGoal(ship) != 0)
690 point_ship_at_object(ship, target);
691 if (g_nFacingToTarget > 75 &&
692 g_nTargetRange < 6000) {
693 fire_missile(ship);
694 maneuver_complete(ship);
695 }
696}
697
698/* Function start: 0x441A13 */
699void Mbuzz_debris(short ship)
700{
701 switch (g_acShipSequence[ship]) {
702 case 0:
703 veer_random(ship, 10);
704 advance(ship);
705 break;
706 case 1:
707 if (CanSetNewShipTurnGoal(ship) != 0) {
708 fire_afterburner(ship, 10);
709 advance(ship);
710 } else {
712 }
713 break;
714 default:
715 if (g_aeSpecialManeuver[ship] ==
717 maneuver_complete(ship);
718 } else if (g_nFacingToTarget > 95) {
719 veer_random(ship, 10);
720 }
721 }
722}
723
724/* Function start: 0x441AFC */
725void Mstrafe_enemy(short ship, short target)
726{
727 point_ship_at_object(ship, target);
728 if (g_asObjectType[ship] == 0x33 &&
729 (g_asShipMissionType[ship] == 2 ||
730 g_aeObjectClass[target] >= 0xd)) {
731 if (g_nTargetRange < 3000)
733 else
735 }
736 if (g_nTargetRange > 5000)
737 fire_afterburner(ship, 10);
738 fire(ship, target);
739 maneuver_complete(ship);
740}
741
742/* Function start: 0x441BC1 */
743void Mbest_strafe(short ship, short target)
744{
745 if (g_nTargetFacing < 0x50) {
746 Mstrafe_enemy(ship, target);
747 return;
748 }
749 Mzip_past(ship, target);
750}
751
752/* Function start: 0x441C01 */
753void Mtarget_missile(short ship, short target)
754{
755
756 switch (g_acShipSequence[ship]) {
757 case 0:
758 point_ship_at_object(ship, target);
759 advance(ship);
760 break;
761 case 1:
762 if (CanSetNewShipTurnGoal(ship) != 0) {
763 fire_afterburner(ship, 10);
764 advance(ship);
765 }
766 break;
767 case 2:
768 Mstrafe_enemy(ship, target);
769 advance(ship);
770 break;
771 case 3:
772 if (no_goal(ship) != 0 &&
773 g_aeSpecialManeuver[ship] != -1)
774 maneuver_complete(ship);
775 break;
776 }
777
778}
779
780/* Function start: 0x441D00 */
781void Msit_n_fire(short ship, short target)
782{
783 if (CanSetNewShipTurnGoal(ship) != 0)
784 point_ship_at_object(ship, target);
785 if (g_nTargetRange > 3000)
787 else
789 fire(ship, target);
790}
791
792/* Function start: 0x441D71 */
793void Mstrafe_n_roll(short ship, short target)
794{
795 if (0 < g_asObjectCounter[ship]) {
796 g_anRollGoal[ship] = 0x2d;
797 return;
798 }
799 Mstrafe_enemy(ship, target);
800}
801
802/* Function start: 0x441DB3 */
803void Mkill_missile(short ship, short target)
804{
805 if (FindMissileTargetingObject(ship) == 0) {
806 maneuver_complete(ship);
807 return;
808 }
810 if (g_nFacingToTarget < 0) {
812 Mfish_hook(ship, target);
813 return;
814 }
815 if (g_nFacingToTarget < 80) {
817 Mburnout(ship, target);
818 return;
819 }
821 if (g_nTargetRange < 8000)
822 fire(ship, g_acShipTarget[ship]);
823}
824
825/* Function start: 0x441E9C */
826void Msuicide_run(short ship, short target)
827{
828 point_ship_at_object(ship, target);
829 fire_afterburner(ship, 160);
830}
831
832/* Function start: 0x441EC8 */
833void Mget_distance(short ship, short target)
834{
835 if (g_nTargetRange > 2000) {
836 maneuver_complete(ship);
837 return;
838 }
839 if (g_nTargetRange < 700 && normal_speed(ship) != 0)
840 fire_afterburner(ship, 10);
841 else
843 if (g_nFacingToTarget > 0 && CanSetNewShipTurnGoal(ship) != 0)
844 steer_away_from_object(ship, target,
846}
847
848/* Function start: 0x441F86 */
849void general_zig(short ship, unsigned int target, short pitch)
850{
851 short complete;
852
853 (void)target;
854 complete = 1;
855 switch (g_acShipSequence[ship] % 6) {
856 case 0:
857 fire_afterburner(ship, 10);
858 g_anYawGoal[ship] = -60;
859 g_anPitchGoal[ship] = pitch;
860 break;
861 case 3:
862 fire_afterburner(ship, 10);
863 g_anYawGoal[ship] = 60;
864 g_anPitchGoal[ship] = (short)-pitch;
865 break;
866 case 1:
867 case 4:
868 complete = no_goal(ship);
869 g_asShipCount[ship] = 0;
870 break;
871 case 2:
872 case 5:
873 g_asShipCount[ship]++;
874 complete = (short)(g_asShipCount[ship] >= 2);
875 break;
876 }
877 if (g_acShipSequence[ship] >= 12 &&
879 no_goal(ship) != 0)
880 maneuver_complete(ship);
881 if (complete != 0)
882 advance(ship);
883}
884
885/* Function start: 0x44210C */
886void Mzig_zag(short ship, unsigned int target)
887{
888 general_zig(ship, target, 0);
889}
890
891/* Function start: 0x442129 */
892void Mzig_zag_pitch(short ship, unsigned int target)
893{
894 general_zig(ship, target, 0x23);
895}
896
897/* Function start: 0x442146 */
898void Mcorkscrew(short ship)
899{
901 if (no_goal(ship) != 0) {
902 if (--g_asShipCount[ship] <= 0) {
903 switch (g_acShipSequence[ship] % 4) {
904 case 0:
905 g_anYawGoal[ship] = -20;
906 break;
907 case 2:
908 g_anYawGoal[ship] = 20;
909 break;
910 case 1:
911 case 3:
912 g_anRollGoal[ship] = 20;
913 break;
914 }
915 g_asShipCount[ship] = 4;
916 advance(ship);
917 }
918 }
919 if (g_acShipSequence[ship] > 8)
920 maneuver_complete(ship);
921}
922
923/* Function start: 0x442252 */
924void Mveer_away(short ship, short target)
925{
926 switch (g_acShipSequence[ship]) {
927 case 0:
928 if (g_nFacingToTarget > 80)
929 steer_away_from_object(ship, target, 40);
930 else
931 steer_away_from_object(ship, target, 10);
932 advance(ship);
933 break;
934 default:
935 if (g_asObjectCollisionRadius[target] * 3 <
937 veer_random(ship, 8);
938 maneuver_complete(ship);
939 } else {
940 if (no_goal(ship) != 0) {
941 if (g_nFacingToTarget > 80) {
942 steer_away_from_object(ship, target, 40);
943 } else if (g_nFacingToTarget < -65 ||
944 RandomBelowOrEqual(100) < 4) {
945 veer_random(ship, 16);
946 }
947 }
949 RandomBelowOrEqual(100) < 10) &&
950 normal_speed(ship) != 0)
951 fire_afterburner(ship, 10);
952 else
954 }
955 }
956}
957
958/* Function start: 0x4423E2 */
959void ShipAiState44(short ship)
960{
961 g_acShipStress[ship] = 0;
962 maneuver_complete(ship);
963}
964
965/* Function start: 0x442404 */
966/* Dispatch slot 8: unimplemented in WC2. */
967void Mtarget_laser(short ship, short target)
968{
969 HandleUnsupportedManeuver(8, ship, target);
970}
971
972/* Function start: 0x442421 */
973void Mrout_me(short ship)
974{
975 try2rout(ship);
976}
977
978/* Function start: 0x442438 */
979/* Dispatch slot 3: unimplemented in WC2. */
980void ShipAiState3(short ship, short target)
981{
982 HandleUnsupportedManeuver(9, ship, target);
983
984}
985
986/* Function start: 0x442455 */
987/* Dispatch slot 45: close on the target at full speed and afterburn once it
988 * is roughly ahead. */
989void ShipAiState45(short ship, short target)
990{
991 if (unactive(target) == 0) {
993 point_ship_at_object(ship, target);
994 if (g_nFacingToTarget > 80)
995 fire_afterburner(ship, 10);
996 } else {
997 maneuver_complete(ship);
998 }
999}
1000
1001/* Function start: 0x4424C2 */
1002/* Empty in the original: dispatch-table slots 0 and 1 (no-op / invalid state). */
1003void Mnone(void)
1004{
1005}
1006
1007/* Function start: 0x4424CD */
1008void Mreset(short ship)
1009{
1010 maneuver_complete(ship);
1011}
1012
1013/* Function start: 0x4424E4 */
1014void perform_maneuver(short obj)
1015{
1016 short previous;
1017 short range;
1018 short weaponSlot;
1019 short target;
1020
1021 target = g_acShipTarget[obj];
1022 if (g_asIntelligenceEvent[obj] == 6) {
1023 weaponSlot = find_weapon(obj, OBJECT_DATA_CHAFF_POD);
1024 if (weaponSlot != -1)
1025 fire_weapon(obj, weaponSlot);
1026 }
1028
1029 previous = g_asShipManeuver[obj];
1032 range = g_nTargetRange;
1033 if (g_nTargetFacing < 0)
1035 (unsigned short)(g_asObjectCollisionRadius[obj] * 4 +
1036 COLLISION_RADIUS_OF(target)));
1037 else
1039 (unsigned short)(g_asObjectCollisionRadius[obj] * 6 +
1040 COLLISION_RADIUS_OF(target)));
1041
1042 if (unactive(target) != 0) {
1043 switch (g_asShipManeuver[obj]) {
1044 case MANEUVER_GLOAT:
1045 ((void (__cdecl *)(short, short))Mgloat)(obj, target);
1046 break;
1048 Mline_up_drop(obj, target);
1049 break;
1050 case MANEUVER_VEER_AWAY:
1051 Mveer_away(obj, target);
1052 break;
1053 default:
1054 maneuver_complete(obj);
1055 }
1056 } else if (g_asShipManeuver[obj] >= 0 &&
1057 g_asShipManeuver[obj] <
1060 g_asShipManeuver[obj]](obj, target);
1061 } else {
1062 if (g_nOriginDevUnlock != 0) {
1063 printf("bigtime_maneuver_error %d %d %d %d", obj,
1064 g_asShipManeuver[obj],
1066 g_asShipIntelSlot[obj]);
1067 getch();
1068 }
1069 maneuver_complete(obj);
1070 }
1071
1072 if (g_asShipManeuver[obj] == previous &&
1074 maneuver_complete(obj);
1075}
void(__cdecl *g_pIxFree)(void *)
#define MANEUVER_REROLL_CHANCE(m)
Definition fl.c:75
#define COLLISION_RADIUS_OF(obj)
Definition fl.c:81
unsigned int approach_full_speed(short ship)
Definition logic.c:537
unsigned int approach_zero_speed(short ship)
Definition logic.c:508
void Mkill_missile(short ship, short target)
Definition fl.c:803
void Mwabble(short ship)
Definition fl.c:157
void Mturn_n_kick(short ship)
Definition fl.c:412
void set_special(short ship, short special)
Definition logic.c:493
void Mtry2tail(short ship, short target)
Definition fl.c:518
void ShipAiState47(short ship, short target)
Definition fl.c:642
void Mbuzz_debris(short ship)
Definition fl.c:699
void ShipAiState44(short ship)
Definition fl.c:959
void fire_super_brake(short ship)
Definition ship.c:2750
short fire_missile(short ship)
Definition ship.c:2681
void Mroll_over(short ship)
Definition fl.c:447
void steer_away_from_object(short obj, short other, short amount)
Definition smart.c:40
void Mreset(short ship)
Definition fl.c:1008
void point_ship_at_object(short obj, short other)
Definition geom.c:686
void perform_maneuver(short obj)
Definition fl.c:1014
void ShipAiState46(short ship)
Definition fl.c:664
void Mzig_zag(short ship, unsigned int target)
Definition fl.c:886
void Mhard_turn(short ship)
Definition fl.c:461
void Mtarget_laser(short ship, short target)
Definition fl.c:967
void general_zig(short ship, unsigned int target, short pitch)
Definition fl.c:849
void fire_afterburner(short obj, short time)
Definition ship.c:2733
void AddFixedVectors(const FixedVector *left, const FixedVector *right, FixedVector *sum)
Definition geom.c:211
void Mzig_zag_pitch(short ship, unsigned int target)
Definition fl.c:892
signed char CanSetNewShipTurnGoal(short ship)
Definition logic.c:303
short unactive(short ship)
Definition logic.c:186
void ScaleFixedVector(FixedVector *vector, int scale, FixedVector *result)
Definition geom.c:237
void Mbest_strafe(short ship, short target)
Definition fl.c:743
void Mstrafe_n_roll(short ship, short target)
Definition fl.c:793
void Mfish_hook(short ship, short target)
Definition fl.c:477
short MinShort(short a, short b)
Definition disk.c:27
void Mveer_away(short ship, short target)
Definition fl.c:924
void Msplit_right(short ship)
Definition fl.c:559
short fire_weapon(short obj, short weapon)
Definition ship.c:2465
void Msit_n_fire(short ship, short target)
Definition fl.c:781
void Mrout_me(short ship)
Definition fl.c:973
void Mburnout(short ship, short target)
Definition fl.c:375
void Mfull_ahead(short ship, short target)
Definition fl.c:195
void BeginShipCloak(short ship)
Definition fl.c:92
unsigned int approach_speed(short ship, int targetSpeed)
Definition ship.c:682
void SetShipAiScratchWord(unsigned short v)
Definition fl.c:128
short signed_random(short range)
Definition logic.c:19
void point_perpendicular(short obj, short other)
Definition geom.c:734
void Mkickit(short ship)
Definition fl.c:397
void ResetShipCloakState(short ship)
Definition fl.c:105
short find_weapon(short obj, short weaponType)
Definition ship.c:2666
void steady_object(short ship)
Definition ship.c:698
void Mthink(short ship, short target)
Definition fl.c:216
void ShipAiState3(short ship, short target)
Definition fl.c:980
void Mram_missile(short ship, short target)
Definition fl.c:686
void Mtail_fire(short ship, short target)
Definition fl.c:605
signed char no_goal(short ship)
Definition logic.c:313
void ShipAiState28(short ship, short target)
Definition fl.c:655
void Mhard_break(short ship)
Definition fl.c:250
void advance(short ship)
Definition fl.c:181
short real_velocity(short obj)
Definition ship.c:705
short close_behind()
short RandomBelow(short n)
Definition eventmgr.c:12
void Mdrop_a_mine(short ship, short target)
Definition fl.c:209
void point_ship_behind_object(short obj, short other)
Definition geom.c:712
void position_relative(FixedVector *position, FixedVector direction, short distance)
Definition geom.c:101
void Mline_up_drop(short ship, short target)
Definition fl.c:141
void Mchill(short ship, short target)
Definition fl.c:202
short try2rout(short obj)
Definition logic.c:272
unsigned int veer_random(short obj, short amount)
Definition smart.c:211
void Mgloat(short ship)
Definition fl.c:580
short FindMissileTargetingObject(short obj)
Definition logic.c:357
void Mstrafe_enemy(short ship, short target)
Definition fl.c:725
void get_facing_range_from_object(short obj, short other)
Definition geom.c:578
void PlaySfxWaveFileByNumber(int soundNumber, int sourceObject, int looping)
Definition music.c:490
void ShipAiState45(short ship, short target)
Definition fl.c:989
void Mtight_loop(short ship)
Definition fl.c:223
void Mget_distance(short ship, short target)
Definition fl.c:833
unsigned int approach_cruise_speed(short ship)
Definition logic.c:529
void fire(short obj, short target)
Definition ship.c:2059
void Mtarget_missile(short ship, short target)
Definition fl.c:753
void Mzip_past(short ship, short target)
Definition fl.c:616
void recalc_max_velocity(short ship)
Definition geom.c:28
void maneuver_complete(short ship)
Definition fl.c:134
void Msuicide_run(short ship, short target)
Definition fl.c:826
short normal_speed(short obj)
Definition logic.c:68
void Msplit_left(short ship)
Definition fl.c:538
void HandleUnsupportedManeuver(short maneuver, short ship, short target)
Definition fl.c:84
void Mnone(void)
Definition fl.c:1003
void ShipAiState35(short ship, short target)
Definition fl.c:188
void point_ship_at_point(short obj, const FixedVector *point)
Definition geom.c:676
void Msit_n_spin(short ship, short target)
Definition fl.c:279
void Mcorkscrew(short ship)
Definition fl.c:898
void Mturn_n_spin(short ship, short target)
Definition fl.c:343
void reset_maneuver(short ship, short maneuver)
Definition logic.c:476
short RandomBelowOrEqual(short n)
Definition eventmgr.c:43
void chase_speed(short obj, short range)
Definition fl.c:112
void point_ship_below_object(short obj, short other)
Definition geom.c:723
Shared Win32 declarations, types and library interfaces.
#define OBJECT_DATA_CHAFF_POD
Definition game_data.h:1614
@ SPECIAL_MANEUVER_NORMAL
Definition game_data.h:260
@ SPECIAL_MANEUVER_KILL_ENGINES
Definition game_data.h:265
@ SPECIAL_MANEUVER_NONE
Definition game_data.h:259
#define MANEUVER_HANDLER_COUNT
Definition game_data.h:1593
@ MANEUVER_ROLL_OVER
Definition game_data.h:223
@ MANEUVER_FISH_HOOK
Definition game_data.h:225
@ MANEUVER_GLOAT
Definition game_data.h:234
@ MANEUVER_VEER_AWAY
Definition game_data.h:211
@ MANEUVER_NONE
Definition game_data.h:208
@ MANEUVER_LINE_UP_DROP
Definition game_data.h:251
@ MANEUVER_BURNOUT
Definition game_data.h:221
@ OBJECT_CLASS_MISSILE
Definition game_data.h:48
short g_asShipCloakCooldown[10]
Definition viewrect.c:180
short g_asObjectCollisionRadius[SPACE_OBJECT_COUNT]
Definition viewrect.c:120
short g_asProjectileEvasionTicks[8]
Definition viewrect.c:186
short g_nFacingToTarget
Definition viewrect.c:45
short g_bAiMissileFiringEnabled
Definition ship.c:9
signed char g_acShipSequence[14]
Definition viewrect.c:176
short g_aeObjectClass[SPACE_OBJECT_COUNT]
Definition viewrect.c:125
signed char g_acShipTarget[16]
Definition viewrect.c:167
short g_asObjectType[SPACE_OBJECT_COUNT]
Definition viewrect.c:124
short g_anRollGoal[12]
Definition viewrect.c:132
FL_STATIC short g_nShipAiScratchValue
Definition globals.h:957
ObjectTypeData g_aObjectTypeData[OBJECT_DATA_COUNT]
Definition campglob.c:310
FixedVector g_aShipForwardVector[SPACE_OBJECT_COUNT]
Definition viewrect.c:107
short g_asObjectScreenX[SPACE_OBJECT_COUNT]
Definition viewrect.c:95
short g_asShipIntelSlot[10]
Definition viewrect.c:155
short g_asShipCloakElapsedFrames[10]
Definition viewrect.c:181
short g_aeSpecialManeuver[12]
Definition viewrect.c:141
FixedVector g_aShipRightVector[SPACE_OBJECT_COUNT]
Definition viewrect.c:105
short g_anYawGoal[12]
Definition viewrect.c:131
FL_STATIC unsigned char g_bCurrentManeuverReroll
Definition globals.h:958
short g_nTargetFacing
Definition viewrect.c:46
short g_asShipCount[12]
Definition viewrect.c:177
short g_anPitchGoal[12]
Definition viewrect.c:130
int g_anShipSpeed[SPACE_OBJECT_COUNT]
Definition viewrect.c:116
short g_nTargetShip
Definition viewrect.c:48
unsigned char g_abManeuverRerollChance[50]
Definition fl.c:10
int g_anShipCloakState[10]
Definition viewrect.c:179
FixedVector g_aShipPosition[SPACE_OBJECT_COUNT]
Definition viewrect.c:108
short g_asShipManeuver[12]
Definition viewrect.c:169
signed char g_acShipStress[16]
Definition viewrect.c:187
short g_nTargetRange
Definition viewrect.c:47
short g_nOriginDevUnlock
Definition main.c:1944
short g_asIntelligenceEvent[12]
Definition spc.c:16
short g_asShipMissionType[12]
Definition viewrect.c:163
signed char g_acObjectType[SPACE_OBJECT_COUNT]
Definition viewrect.c:101
short g_asObjectCounter[SPACE_OBJECT_COUNT]
Definition viewrect.c:110
short g_nCannedSceneMode
Definition taperec.c:14
void(* g_apManeuverHandlers[50])(short, short)
Definition fl.c:18
short cruiseVelocity
Definition game_data.h:378