Wing Commander
Reconstructed Win32 source (1996)
Loading...
Searching...
No Matches
ship.c
Go to the documentation of this file.
1/**
2 * @file
3 * @ingroup flight
4 * @brief Ships: damage, explosions and weapons.
5 *
6 * Address range 41dee0-4219bf, the Mac ship compilation unit: its symbols,
7 * initialize_object through your_afterburner, map in order onto this range.
8 */
9#include "wc1.h"
10#include <sys/stat.h>
11#include <setjmp.h>
12
14 0, 8, 6, 5, 0, 3, 5, 5, 7, 6,
15 0, 8, 6, 5, 4, 3, 4, 0, 4, 4,
16 1, 2, 5, 2, 7, 3, 4, 7, 5, 1,
17 1, 4, 1, 5, 2, 3, 4, 7, 2, 1,
18 4, 4, 4, 4, 0, 8, 6, 5, 4, 0
19}; /* 0x00469878 */
20
48
54
55signed char acGunRefireDelay[4] = {6, 10, 4, 0}; /* 0x0046995c */
56
57/* Linker commons defined here; LINK orders them by identifier hash. */
58int nMemoryConfig; /* 0x005a7cd4 */
59int dwOriginalFreeMem; /* 0x005a7cd8 */
60struct Shape *pMouseCursorResource; /* 0x005a7cdc */
61int nAvailableGameMemory; /* 0x005a7ce0 */
62int nSceneResourceBudgetValue; /* 0x005a7ce4 */
63int nAfterburnerSoundDeadline; /* 0x005a7ce8 */
64int bAfterburnerSfxEnabled; /* 0x005a7cec */
65
66/* Function start: 0x41DEE0 */
67short initialize_object(short obj, enum ObjectType type, short owner)
68{
69 if (obj != -1) {
70 set_objects_data(obj, type, owner);
73 }
74 return obj;
75}
76
77/* Function start: 0x41DF40 */
78short borrow_dust(void)
79{
80 short i = 0x22;
81
82 do {
84 return i;
85 i = i + 1;
86 } while (i < 0x2a);
87 return -1;
88}
89
90/* Function start: 0x41DF70 */
91short new_object(enum ObjectType type, short owner)
92{
93 short obj;
94
96 if (obj == -1 && owner == 0)
97 obj = borrow_dust();
98 return initialize_object(obj, type, owner);
99}
100
101/* Function start: 0x41DFA0 */
102short initialize_ship(enum ObjectType type, short owner)
103{
104 short obj = get_ship_slot();
105
106 if (obj != -1) {
107 initialize_object(obj, type, owner);
109 }
110 return obj;
111}
112
113/* Function start: 0x41DFE0 */
114short any_selected(signed char *loadout, enum ObjectClass objectClass)
115{
116 short selected;
117 short weapon;
118
119 selected = 0;
120 for (weapon = 0; weapon < loadout[0] && selected == 0;
121 weapon++) {
122 if (aObjectTypeData[
123 ((ShipWeaponSlot *)(loadout + 1))[weapon].type]
124 .objectClass == objectClass &&
125 ((ShipWeaponSlot *)(loadout + 1))[weapon].disabled == 0)
126 selected = 1;
127 }
128 return selected;
129}
130
131/* Function start: 0x41E040 */
132unsigned int remove_weapon(short obj, short weapon)
133{
134 enum ObjectType preferredType;
135 enum ObjectClass objectClass;
136 signed char *loadout;
137 short slot;
138
139 loadout = aShipWeaponsTable[obj];
140 preferredType =
141 ((ShipWeaponSlot *)&aShipWeaponsTable[obj][1])[weapon].type;
142 objectClass = aObjectTypeData[preferredType].objectClass;
143 if (weapon < loadout[0] - 1) {
144 for (slot = weapon; slot < loadout[0] - 1; slot++) {
145 signed char *entry = loadout + slot * 7;
146
147 ((ShipWeaponSlot *)(entry + 1))[0].type =
148 ((ShipWeaponSlot *)(entry + 1))[1].type;
149 ((ShipWeaponSlot *)(entry + 1))[0].hardpoint =
150 ((ShipWeaponSlot *)(entry + 1))[1].hardpoint;
151 ((ShipWeaponSlot *)(entry + 1))[0].disabled =
152 ((ShipWeaponSlot *)(entry + 1))[1].disabled;
153 }
154 loadout[loadout[0] * 7 + 7] = 1;
155 }
156 loadout[0]--;
157 if (obj == 0) {
158 if (any_selected(loadout, objectClass) == 0) {
159 if (objectClass == OBJECT_CLASS_PROJECTILE) {
161 } else {
163 select_new_release_weapon(preferredType);
164 }
165 }
166 if (get_mode(0) == 1)
168 }
169 return 0;
170}
171
172/* Function start: 0x41E120 */
173void set_objects_data(short obj, enum ObjectType type, short owner)
174{
175 ObjectTypeData *typeData;
176 enum ObjectClass objectClass;
177 short value;
178 short weapon;
179
180 if (type == OBJECT_TYPE_SPACE_DUST) {
183 return;
184 }
185 if (aObjectTypeData[type].shapeSet == 0
186 ) {
187 switch (type) {
190 break;
193 break;
196 break;
199 break;
202 break;
205 break;
208 break;
209 }
210 }
211 typeData = &aObjectTypeData[type];
212 aeObjectTypeList[obj] = type;
213 aeObjectClass[obj] = typeData->objectClass;
214 if (type == OBJECT_TYPE_ROCK_CHUNK)
215 apObjShapeArray[obj] =
217 else
218 apObjShapeArray[obj] = typeData->shapeSet;
219 init_ijk(obj);
221 awObjMassArray[obj] = typeData->mass;
222 awObjectScales[obj] = typeData->scale;
224 typeData->afterburnerVelocity;
225 asShipAccumulatedDmg[obj] = 0;
228 acObjOwnersTable[obj] = (signed char)owner;
229 acLastCollisionObjects[obj] = -1;
230 objectClass = aeObjectClass[obj];
231
232 if (objectClass >= OBJECT_CLASS_MISSILE) {
233 asObjectViewFrames[obj] = 0;
234 acShipTargetTable[obj] = -1;
235 if (objectClass >= OBJECT_CLASS_SHIP) {
236 value = typeData->shieldFore;
237 aasShipShield[obj][0] = value;
238 aasShipMaximumShieldTable[obj][0] = value;
239 value = typeData->shieldAft;
240 aasShipShield[obj][1] = value;
241 aasShipMaximumShieldTable[obj][1] = value;
242 aasShipArmor[obj][0] = typeData->armorFront;
243 aasShipArmor[obj][2] = typeData->armorLeft;
244 aasShipArmor[obj][3] = typeData->armorRight;
245 aasShipArmor[obj][1] = typeData->armorRear;
246 anShipFuelsTable[obj] = typeData->lifetime;
247 acShipIonDriveDmg[obj] = 0;
248 acShipDmg[obj] = 0;
250 acPilotHitPointsArray[obj] = 4;
251 memcpy(aShipWeaponsTable[obj], typeData->weaponLoadout,
252 sizeof(typeData->weaponLoadout));
253
254 if (obj == 0) {
256 eSelectedGunType = (enum ObjectType)-1;
257 for (weapon = (short)aShipWeaponsTable[obj][0];
258 weapon-- > 0;) {
259 if (((ShipWeaponSlot *)&aShipWeaponsTable[obj][1])[weapon]
260 .disabled == 0) {
262 &aShipWeaponsTable[obj][1])[weapon].type]
263 .objectClass == OBJECT_CLASS_PROJECTILE)
265 &aShipWeaponsTable[obj][1])[weapon].type;
266 else
268 }
269 }
270 }
271 acPreviousAttackers[obj] = -1;
272 asShipWpnEnergyList[obj] = 100;
273 }
274 return;
275 }
276
277 if (typeData->animation == 0) {
278 asObjectViewFrames[obj] = typeData->yawRate;
279 return;
280 }
281 asObjectAnimationDelay[obj] = 1;
282 asObjectAnimIndexes[obj] = 0;
283 animate_shape(obj);
284}
285
286/* Function start: 0x41E400 */
287unsigned int match_rotation_goal(short *rotation, short *goal,
288 short totalError, short rate)
289{
290 short step;
291
292 if (totalError != 0) {
293 if (*goal > 180)
294 *goal = *goal - 360;
295 if (*goal < -180)
296 *goal = *goal + 360;
297 step = MaxShort(1, (short)(abs(*rotation - *goal) *
298 rate / totalError));
299 if (*goal != *rotation || step < abs(*rotation)) {
300 if (*goal > 0) {
301 *rotation = (short)(*rotation +
302 MaxShort(
303 MinShort(
304 (short)(MinShort(*goal, step) - *rotation),
305 step),
306 (short)-step));
307 } else {
308 *rotation = (short)(*rotation +
309 MinShort(
310 MaxShort(
311 (short)(MaxShort(*goal, (short)-step) -
312 *rotation),
313 (short)-step),
314 step));
315 }
316 }
317 }
318 if (*goal != 0) {
319 if (*goal > 0)
320 *goal = MaxShort((short)(*goal - *rotation), 0);
321 else
322 *goal = MinShort((short)(*goal - *rotation), 0);
323 }
324 return 0;
325}
326
327/* Function start: 0x41E520 */
329{
330 ObjectTypeData *typeData;
331 short totalError;
332
333 typeData = &aObjectTypeData[aeObjectTypeList[obj]];
334 if (aeSpecialManeuvers[obj] ==
336 if ((short)alert_flag(obj, 1) != 0) {
338 } else {
339 if (asObjectCounterArray[obj] == -1 &&
340 skill_check(obj, 7) != 0)
341 aeSpecialManeuvers[obj] =
343 return 0;
344 }
345 }
346 totalError = (short)(abs(anObjectYawRotation[obj] -
347 anYawTarget[obj]) +
348 abs(anObjPitchRot[obj] -
349 anPitchGoal[obj]) +
350 abs(anObjectRollRotationList[obj] -
351 anRollGoal[obj]));
353 &anPitchGoal[obj], totalError,
354 typeData->yawRate);
356 &anYawTarget[obj], totalError,
357 typeData->pitchRate);
359 &anRollGoal[obj], totalError,
360 typeData->rollRate);
361}
362
363/* Function start: 0x41E650 */
364unsigned int check_for_lost_control(short obj)
365{
366 short overshoot;
367 short turnRate;
368
369 if (obj != 0 && aeSpecialManeuvers[obj] !=
372 turnRate = (short)(aObjectTypeData[aeObjectTypeList[obj]].yawRate +
373 turnRate);
374 turnRate = (short)(aObjectTypeData[aeObjectTypeList[obj]].rollRate +
375 turnRate);
376 overshoot = (short)(abs(anObjPitchRot[obj]) +
377 abs(anObjectRollRotationList[obj]) +
378 abs(anObjectYawRotation[obj]));
379 overshoot = (short)(overshoot / turnRate);
380 if (skill_check(obj, overshoot) == 0) {
383 (short)(RandomBelowOrEqual(6) + 5);
384 }
385 }
386 return 0;
387}
388
389/* Function start: 0x41E710 */
390unsigned int celerate(short ship, int delta)
391{
392 int maximumSpeed = (int)asShipMaximumSpeedArray[ship] << 8;
393 int speed;
394
395 speed = anShipSpeed[ship] + delta;
396 anShipSpeed[ship] = speed;
397 if (speed > maximumSpeed)
398 anShipSpeed[ship] = maximumSpeed;
399 if (anShipSpeed[ship] < 0)
400 anShipSpeed[ship] = 0;
401 return 0;
402}
403
404/* Function start: 0x41E750 */
405unsigned int approach_speed(short ship, int targetSpeed)
406{
407 int delta;
408 int acceleration;
409
410 acceleration = GetShipAccelerationRate(ship);
411 delta = targetSpeed - anShipSpeed[ship];
412
413 if ((short)alert_flag(ship, 1))
414 acceleration += acceleration;
415 if ((delta < 0 ? -delta : delta) > acceleration)
416 delta = MultiplyFixed(SignFixed(delta), acceleration);
417 celerate(ship, delta);
418 return 0;
419}
420
421/* Function start: 0x41E7C0 */
422unsigned int steady_object(short ship)
423{
424 anYawTarget[ship] = 0;
425 anPitchGoal[ship] = 0;
426 anRollGoal[ship] = 0;
427 return 0;
428}
429
430/* Function start: 0x41E7F0 */
431short real_velocity(short obj)
432{
435}
436
437/* Function start: 0x41E820 */
438unsigned int fix_velocity(short obj)
439{
441 anShipSpeed[obj],
442 &aShipVelocity[obj]);
443 return 0;
444}
445
446/* Function start: 0x41E860 */
447unsigned int sort_viable_target_list(void)
448{
449 short outer;
450 signed char target;
451 short innerDistance;
452 short count;
453 short inner;
454
455 if (cViableTargetCount > 1) {
456 count = cViableTargetCount;
457 for (outer = 0; outer < count - 1; outer++) {
458 for (inner = outer + 1; inner < count; inner++) {
459 short distance;
460 int outerIndex;
461
462 outerIndex = outer;
463 distance = asViableTgtDistList[outerIndex];
464 innerDistance = asViableTgtDistList[inner];
465 if (distance > innerDistance) {
466 target = acViableTargetList[outerIndex];
467 asViableTgtDistList[outerIndex] = innerDistance;
468 acViableTargetList[outerIndex] =
469 acViableTargetList[inner];
470 asViableTgtDistList[inner] = distance;
471 acViableTargetList[inner] = target;
472 }
473 }
474 }
475 }
476 return 0;
477}
478
479/* Function start: 0x41E900 */
480void send_appropriate_message(short attacker, short victim)
481{
482 if (aeObjectClass[attacker] >= OBJECT_CLASS_SHIP) {
483 if (nYourWingman != -1 &&
484 (short)acObjOwnersTable[attacker] ==
485 nYourWingman &&
486 nYourWingman != attacker &&
487 aeShipSide[victim] == SIDE_KILRATHI) {
488 if (RandomBelowOrEqual(100) < 50 &&
489 aeSpecialManeuvers[attacker] !=
492 } else if (
494 (short)acObjOwnersTable[attacker]] ==
496 nYourWingman == victim) {
497 send_message((short)acObjOwnersTable[attacker], 5);
498 }
499 }
500}
501
502/* Function start: 0x41E9B0 */
503int inflict_damage(short attacker, short victim, short damage,
504 const FixedVector *impactDirection)
505{
506 short *strength;
507 short quadrant;
508 short destroyed;
509 int sideDot;
510
511 if (bPlayerVulnerable == 0 && victim == 0)
512 return 0;
513 if (damage == 0 ||
514 aeSpecialManeuvers[victim] ==
517 return 0;
518
519 if (aeObjectClass[victim] < OBJECT_CLASS_SHIP) {
520 asShipAccumulatedDmg[victim] = (short)(
521 asShipAccumulatedDmg[victim] + damage);
522 if (aObjectTypeData[
523 aeObjectTypeList[victim]].damageCapacity == -1)
524 return 0;
525 if (aObjectTypeData[
526 aeObjectTypeList[victim]].damageCapacity <=
527 asShipAccumulatedDmg[victim])
528 return explode(attacker, victim);
529 /* The original survivor path returns without clearing EAX. */
530 return;
531 } else {
532 if (victim == 0) {
534 }
535
536 if (attacker != -1 &&
537 nYourWingman == victim &&
538 acObjOwnersTable[attacker] == 0)
539 send_message(victim, 10);
540
541 quadrant = (short)(dot_product(impactDirection,
542 &aShipFwdVec[victim]) > 0);
543 strength = &aasShipShield[victim][quadrant];
544 damage = (short)(damage - *strength);
545 if (damage > 0) {
546 *strength = 0;
547 if (attacker != -1 &&
548 aeObjectClass[attacker] ==
550 PlaySfxWaveFileByNumber(9, victim, 0);
551
552 sideDot = dot_product(impactDirection,
553 &aShipRightVector[victim]);
554 if (sideDot > 0xb5)
555 quadrant = 3;
556 else if (sideDot < -0xb5)
557 quadrant = 2;
558 strength = &aasShipArmor[victim][quadrant];
559 damage = (short)(damage - *strength);
560 if (damage > 0) {
561 *strength = 0;
562
563 if (asObjectScreenXList[victim] !=
564 (short)0x8001 &&
565 aeObjectClass[victim] !=
567 RandomBelowOrEqual(1) == 0)
568 Create_ship_hit_debris(attacker, 1);
569 if (RandomBelowOrEqual(99) == 0) {
570 if (attacker != 0 &&
571 attacker != nYourWingman &&
572 aeObjectClass[attacker] ==
574 if (aeShipSide[attacker] ==
576 send_message(attacker, 6);
577 destroyed = explode(attacker, victim);
578 }
579 } else {
580 destroyed = internal_damage(attacker, victim, damage,
581 quadrant);
582 }
583 if (destroyed == 1)
584 send_appropriate_message(attacker, victim);
585 return destroyed;
586 }
587 *strength = (short)-damage;
588 } else {
589 *strength = (short)-damage;
590 if (attacker != -1 &&
591 aeObjectClass[attacker] ==
593 PlaySfxWaveFileByNumber(10, victim, 0);
594 }
595 }
596 return 0;
597}
598
599/* Function start: 0x41EC60 */
600short pilot_hit(short obj)
601{
602 if (acPilotHitPointsArray[obj] > 0) {
604 if (acPilotHitPointsArray[obj] == 0) {
605 if (obj == 0) {
606 if (bPlayerVulnerable != 0)
607 nArcadeState = 4;
608 return -1;
609 }
610 } else if (skill_check(obj, 9) == 0 && obj != 0) {
612 (short)(RandomBelowOrEqual(20) + 30);
614 }
615 }
616 return acPilotHitPointsArray[obj];
617}
618
619/* Function start: 0x41ECE0 */
620int onboard_explosion(short obj)
621{
622 short debris;
623 FixedVector offset;
624
625 debris = find_vacant_3d_object();
626 if (debris != -1) {
628 awObjectScales[debris] <<= 2;
629 aShipVelocity[debris] = aShipVelocity[obj];
630 asObjectCounterArray[debris] = 6;
632 (short)(asObjectCollisionRadius[obj] >> 2),
633 (short)(asObjectCollisionRadius[obj] >> 1),
634 &offset);
636 &aShipPositionsArray[debris]);
637 }
638 return debris != -1;
639}
640
641/* Function start: 0x41EDB0 */
642void call_enemy(short obj)
643{
644 int otherIndex;
645 short other;
646
647 other = 0;
648 for (; other < 10; other++) {
649 otherIndex = other;
650 if (aeObjectClass[otherIndex] >= OBJECT_CLASS_SHIP &&
651 aeSpecialManeuvers[otherIndex] !=
653 aeShipSide[obj] != aeShipSide[otherIndex] &&
654 RandomBelow(100) < 50)
655 acShipTargetTable[otherIndex] = obj;
656 }
657}
658
659/* Function start: 0x41EE20 */
660int internal_damage(short attacker, short victim, short damage,
661 short quadrant)
662{
663 enum ObjectType type;
664 short damageCapacity;
665 int victimIndex;
666 short system;
667 signed char weaponCount;
668
669 if (victim == 0)
670 return your_internal_damage(attacker, damage, quadrant);
671 victimIndex = victim;
672 type = aeObjectTypeList[victimIndex];
673 damageCapacity = aObjectTypeData[type].damageCapacity;
674 if (aeObjectClass[victimIndex] == OBJECT_CLASS_CAPITAL_SHIP) {
675 if (aeShipSide[victimIndex] == SIDE_KILRATHI) {
676 asShipAccumulatedDmg[victimIndex] = (short)(
677 asShipAccumulatedDmg[victimIndex] +
678 MaxShort(1, (short)(damage >> 3)));
679 if (attacker != -1 && attacker < 10 &&
680 any_enemy(attacker, 10000) == 0)
681 call_enemy(attacker);
682 } else {
683 asShipAccumulatedDmg[victimIndex] = (short)(
684 asShipAccumulatedDmg[victimIndex] +
685 MaxShort(1, (short)(damage / 10)));
686 if (RandomBelowOrEqual(1000) < 35 && attacker != 0)
687 send_message(victim, 4);
688 }
689 if (asShipAccumulatedDmg[victimIndex] >= damageCapacity)
690 return explode(attacker, victim);
691 else
692 onboard_explosion(victim);
693 return 0;
694 }
695
696 if (acShipRating[victimIndex] != -1) {
697 damage = MaxShort(1, (short)(damage / 40));
698 damage = MinShort(RandomInRange(3, 4), damage);
699 } else {
700 damage = MaxShort(1, (short)(damage / 6));
701 }
702 asShipAccumulatedDmg[victimIndex] = (short)(
703 asShipAccumulatedDmg[victimIndex] + damage);
704
705 while (damage > 0) {
706 if (damage == 1 && acShipRating[victimIndex] != -1)
707 system = 4;
708 else
709 system = RandomBelowOrEqual(9);
710 switch (system) {
711 case 0:
712 damage--;
713 pilot_hit(victim);
714 break;
715 case 1:
716 if (quadrant == 1) {
717 damage--;
718 damage_ion_drive(victim, 1, 3);
719 }
720 break;
721 case 2:
722 if (quadrant == 1)
723 return explode(attacker, victim);
724 break;
725 case 3:
726 aasShipMaximumShieldTable[victimIndex][0] = 0;
727 aasShipShield[victimIndex][0] = 0;
728 aasShipMaximumShieldTable[victimIndex][1] = 0;
729 aasShipShield[victimIndex][1] = 0;
730 break;
731 case 4:
732 damage--;
733 acShipDmg[victimIndex]++;
734 if ((short)acShipDmg[victimIndex] >
735 damageCapacity)
736 return explode(attacker, victim);
737 break;
738 case 5:
739 if (quadrant == 0) {
740 weaponCount = aShipWeaponsTable[victimIndex][0];
741 if (weaponCount > 0) {
742 system = (short)(weaponCount - 1);
743 damage--;
744 remove_weapon(victim,
745 (short)(signed char)RandomBelowOrEqual(system));
746 }
747 }
748 break;
749 case 6:
750 if (quadrant == 0 &&
751 acShipDestroyedWeaponCountArray[victimIndex] < 5) {
752 damage--;
753 acShipDestroyedWeaponCountArray[victimIndex]++;
754 }
755 break;
756 case 7:
757 if (quadrant == 1) {
758 damage--;
759 drain_fuel(victim,
760 (short)(aObjectTypeData[
761 type].lifetime / 4));
762 if (RandomBelowOrEqual(1) != 0 ||
763 anShipFuelsTable[victimIndex] < 0)
764 return explode(attacker, victim);
765 }
766 break;
767 case 8:
768 if (quadrant == 0 &&
769 acShipCommunicatorArray[victimIndex] != -1) {
770 acShipCommunicatorArray[victimIndex] = -1;
771 damage--;
772 }
773 break;
774 }
775 }
776 /* The original leaves the return register unset on this path. */
777 return;
778}
779
780/* Function start: 0x41F1A0 */
781void revise_shields(short obj)
782{
784 MaxShort(0, (short)(aasShipMaximumShieldTable[obj][0] -
786 aeObjectTypeList[obj]].shieldFore >> 2)));
788 MaxShort(0, (short)(aasShipMaximumShieldTable[obj][0] -
790 aeObjectTypeList[obj]].shieldAft >> 2)));
791}
792
793/* Function start: 0x41F220 */
794int your_internal_damage(short attacker, short damage, short quadrant)
795{
796 enum ObjectType playerType;
797 short tableGroup;
798 short events;
799 signed char severity;
800
801 if (aeObjectClass[attacker] == OBJECT_CLASS_PROJECTILE) {
802 tableGroup = quadrant == 1 ? 2 : 0;
803 events = MaxShort(1, (short)(damage >> 4));
804 } else if (aeObjectClass[attacker] == OBJECT_CLASS_ASTEROID ||
805 aeObjectClass[attacker] >= OBJECT_CLASS_SHIP) {
806 tableGroup = 4;
807 events = MaxShort(1, (short)(damage >> 7));
808 } else {
809 tableGroup = quadrant == 1 ? 3 : 1;
810 events = MaxShort(1, (short)(damage >> 5));
811 }
812 playerType = aeObjectTypeList[0];
813 severity = (signed char)RandomBelowOrEqual(10);
814 asShipAccumulatedDmg[0] = (short)(
815 asShipAccumulatedDmg[0] + events);
816 if (events > 1)
818
819 while (events > 0) {
820 events--;
821 switch ((short)(signed char)asPlayerDamageSystemTable[
822 tableGroup * 10 + RandomBelowOrEqual(9)]) {
823 case 0:
824 if (severity < 4)
825 pilot_hit(0);
826 else if (severity < 7)
827 damage_your_component(7, 2, 4);
828 else
829 damage_your_component(6, 4, 4);
830 break;
831 case 1:
832 if (quadrant != 1) {
833 events++;
834 break;
835 }
836 damage_your_component(0, 1, 3);
837 damage_ion_drive(0, 1, 3);
838 break;
839 case 2:
840 if (quadrant != 1) {
841 events++;
842 break;
843 }
844 if (RandomBelowOrEqual(3) == 0)
845 return explode(attacker, 0);
846 if (damage_your_component(1, 1, 4) == 4)
847 return explode(attacker, 0);
848 break;
849 case 3:
850 if (severity < 9) {
851 damage_your_component(2, 1, 4);
853 } else
854 damage_your_component(8, 2, 4);
855 break;
856 case 4:
857 acShipDmg[0]++;
858 if (acShipDmg[0] == 1) {
859 events--;
860 pilot_hit(0);
861 } else if ((short)acShipDmg[0] >
862 aObjectTypeData[playerType].
863 damageCapacity) {
864 return explode(attacker, 0);
865 }
866 break;
867 case 5:
868 if (quadrant != 0) {
869 events++;
870 } else {
871 if (aShipWeaponsTable[0][0] > 0) {
873 (signed char)RandomBelowOrEqual(
874 (short)(aShipWeaponsTable[0][0] - 1)));
876 "Weapon destroyed",
877 cRedColour, 8);
878 }
879 }
880 break;
881 case 6:
882 if (quadrant != 0)
883 events++;
884 else if (acShipDestroyedWeaponCountArray[0] < 5) {
887 }
888 break;
889 case 7:
890 drain_fuel(0,
891 (short)(aObjectTypeData[
892 playerType].lifetime / 4));
893 if (RandomBelowOrEqual(1) != 0 ||
894 anShipFuelsTable[0] < 0)
895 return explode(attacker, 0);
896 ShowComponentHitHudMessage("Fuel tanks hit",
897 cRedColour, 8);
898 break;
899 case 8:
900 if (quadrant != 0) {
901 events++;
902 } else {
903 if (severity < 7) {
904 damage_your_component(4, 2, 3);
905 if (acPlayerComponentDamageList[4] >= 4)
907 } else
908 damage_your_component(5, 4, 4);
909 }
910 break;
911 }
912 }
913}
914
915/* Function start: 0x41F5D0 */
916unsigned int check_computer_damage(void)
917{
918 damage_your_component(3, 1, 3);
919 return 0;
920}
921
922/* Function start: 0x41F5F0 */
923short ReportComponentRepaired(short component, short minimumDamage)
924{
925 char message[80];
926
927 if (minimumDamage <
928 (short)acPlayerComponentDamageList[component]) {
929 acPlayerComponentDamageList[component] =
930 (signed char)(acPlayerComponentDamageList[component] - 1);
931 sprintf(message, "%s FIXD",
932 apszComponentNames[component]);
934 return 1;
935 }
936 return 0;
937}
938
939/* Function start: 0x41F660 */
941{
942 short repair;
943 short component;
944
945 if ((short)acPlayerComponentDamageList[component] >= 4)
946 return;
947 if (RandomBelowOrEqual(500) >= 2)
948 return;
949 repair = RandomBelowOrEqual(2);
950 switch (repair) {
951 case 0:
953 break;
954 case 1:
955 if (ReportComponentRepaired(0, 2) != 0)
956 damage_ion_drive(0, -1, 3);
957 break;
958 case 2:
959 if (aObjectTypeData[
960 aeObjectTypeList[0]].damageCapacity - 3 <
961 (short)acShipDmg[0])
962 acShipDmg[0]--;
963 break;
964 }
965}
966
967/* Function start: 0x41F700 */
968void Create_ship_hit_debris(short obj, short count)
969{
970 FixedVector offset;
971 short created;
972 short debris;
973
974 created = 0;
975 if (created >= count)
976 return;
977 do {
978 debris = find_vacant_3d_object();
979 if (debris == -1)
980 return;
981 set_objects_data(debris,
983 RandomBelowOrEqual(2)], -1);
984 asObjectCounterArray[debris] = 40;
987 &aShipPositionsArray[debris]);
989 6, &aShipVelocity[debris]);
990 created++;
991 } while (created < count);
992}
993
994/* Function start: 0x41F7C0 */
996{
997 short obj;
998
999 if (nCurrentWave == -1)
1000 return;
1001 for (obj = 0; obj < 10; obj++) {
1002 if (aeObjectClass[obj] == OBJECT_CLASS_SHIP &&
1003 aeShipSide[obj] == SIDE_KILRATHI)
1004 return;
1005 }
1007}
1008
1009/* Function start: 0x41F800 */
1010unsigned int Create_explosion_debris(short obj)
1011{
1012 FixedVector vector;
1013 short debris;
1014 short index;
1015 short set;
1016
1017 remove_object(obj);
1019 set = RandomBelowOrEqual(3);
1020 for (index = 0; index < 7; index++) {
1021 debris = find_vacant_3d_object();
1022 if (debris == -1)
1023 break;
1024 set_objects_data(debris,
1025 aaeExplosionDebris[set][index], -1);
1026 asObjectCounterArray[debris] = 40;
1028 AddFixedVectors(&aShipPositionsArray[obj], &vector,
1029 &aShipPositionsArray[debris]);
1031 25, &aShipVelocity[debris]);
1032 divide_vector(&aShipVelocity[obj], 0x200, &vector);
1033 AddFixedVectors(&vector,
1034 &aShipVelocity[debris],
1035 &aShipVelocity[debris]);
1036 }
1037 for (index = 0; index < 8; index++) {
1038 debris = find_vacant_3d_object();
1039 if (debris == -1)
1040 break;
1042 AddFixedVectors(&aShipPositionsArray[obj], &vector,
1043 &aShipPositionsArray[debris]);
1045 25, &aShipVelocity[debris]);
1046 divide_vector(&aShipVelocity[obj], 0x200, &vector);
1047 AddFixedVectors(&vector,
1048 &aShipVelocity[debris],
1049 &aShipVelocity[debris]);
1050 asObjScreenAngles[debris] =
1051 (short)(RandomBelowOrEqual(3) + 0x10);
1052 asObjectCounterArray[debris] = 40;
1055 }
1056 return 0;
1057}
1058
1059/* Function start: 0x41F9E0 */
1060unsigned int affect_mission_score(short pilot, int event, short amount)
1061{
1062 short score;
1063
1064 switch (event) {
1065 case 0:
1066 score = amount;
1067 break;
1068 case 1:
1069 score = 7;
1070 break;
1071 case 2:
1072 score = 10;
1073 break;
1074 case 3:
1075 case 4:
1076 score = 15;
1077 break;
1078 case 5:
1079 case 6:
1080 score = 25;
1081 break;
1082 case 7:
1083 score = 50;
1084 break;
1085 case 8:
1086 score = 75;
1087 break;
1088 case 9:
1089 case 10:
1090 case 11:
1091 score = 25;
1092 break;
1093 case 12:
1094 score = (short)(amount * 2);
1095 break;
1096 default:
1097 score = amount;
1098 break;
1099 }
1101 (short)(stCampaignState.missionScore + score);
1102 if (pilot == 0) {
1104 (short)(nMissionMedalScoreValue + score);
1105 nCurrentArcadeScore += score * 10;
1106 }
1107 return 0;
1108}
1109
1110/* Function start: 0x41FA90 */
1111unsigned int score_for_kill(short pilot, short victim)
1112{
1113 int event;
1114
1115 if (aeShipSide[victim] == SIDE_KILRATHI) {
1116 switch (aeObjectTypeList[victim]) {
1117 case OBJECT_TYPE_SALTHI:
1118 event = 1;
1119 break;
1121 case OBJECT_TYPE_KRANT:
1122 event = 2;
1123 break;
1124 case OBJECT_TYPE_GRATHA:
1125 case OBJECT_TYPE_JALTHI:
1126 event = 3;
1127 break;
1129 case OBJECT_TYPE_RALARI:
1130 event = 6;
1131 break;
1132 case OBJECT_TYPE_DORKIR:
1134 event = 4;
1135 break;
1138 event = 7;
1139 break;
1140 case OBJECT_TYPE_SIVAR:
1142 event = 8;
1143 break;
1144 }
1145 affect_mission_score(pilot, event, -1);
1146 }
1147 return 0;
1148}
1149
1150/* Function start: 0x41FB40 */
1151unsigned int analyze_kill(short attacker, short victim)
1152{
1153 int enemy;
1154
1155 enemy = aeShipSide[victim] !=
1156 aeShipSide[attacker];
1157 new_space_music_changes(attacker, victim);
1158 if (enemy) {
1159 send_message(attacker, 5);
1160 score_for_kill(attacker, victim);
1161 if (attacker == 0)
1163 else if (nYourWingman == attacker)
1165 }
1166 return 0;
1167}
1168
1169/* Function start: 0x41FBC0 */
1170short ShipExplosion(short obj)
1171{
1172 unsigned short originalScale;
1173 short explosion;
1174
1175 originalScale = (unsigned short)awObjectScales[obj];
1176 explosion = find_vacant_3d_object();
1177 if (explosion == -1) {
1178 if (aeObjectClass[obj] ==
1182 explosion = obj;
1183 } else {
1184 copy_frame(obj, explosion);
1185 aShipPositionsArray[explosion] =
1187 aShipVelocity[explosion] =
1188 aShipVelocity[obj];
1189 acObjOwnersTable[explosion] = (signed char)obj;
1190 }
1192 (short)acObjOwnersTable[explosion]);
1193 awObjectScales[explosion] = (short)(
1194 (unsigned short)awObjectScales[explosion] *
1195 originalScale >> 8);
1196 return explosion;
1197}
1198
1199/* Function start: 0x41FCD0 */
1200short Explosion(short obj)
1201{
1202 enum ObjectClass objectClass;
1203 enum ObjectType explosionType;
1204 short missionShip;
1205 short explosion;
1206
1207 objectClass = aeObjectClass[obj];
1208 explosion = obj;
1209 if (objectClass >= OBJECT_CLASS_SHIP) {
1210 missionShip = -1;
1211 if (objectClass == OBJECT_CLASS_CAPITAL_SHIP)
1212 missionShip = find_ship_index(obj);
1213 if (obj < 10 &&
1214 (acShipRating[obj] != -1 ||
1215 (missionShip != -1 &&
1216 anShipMissionShips[obj] == missionShip) ||
1217 RandomBelow(100) < 3)) {
1218 send_message(obj, 7);
1219 }
1220 if (acShipRating[obj] != -1 &&
1222 personality_killed((short)acShipRating[obj]);
1223 if (nYourWingman == obj) {
1225 missionShip = 0;
1226 for (; missionShip < 10; missionShip++) {
1227 if (acShipRating[missionShip] >
1229 break;
1230 }
1231 if (missionShip < 10)
1232 send_message(missionShip, 5);
1233 nYourWingman = -1;
1234 }
1236 asObjectCounterArray[obj] = 8;
1238 nShipMissionIndices[obj]].state = 3;
1239 if (aeObjectClass[obj] ==
1241 short count = 4;
1242
1243 for (; count != 0; count--) {
1244 onboard_explosion(obj);
1245 }
1247 (short)(aObjectTypeData[
1248 aeObjectTypeList[obj]].damageCapacity >> 2) + 8;
1249 } else {
1250 explosion = ShipExplosion(obj);
1252 obj, aObjectTypeData[
1253 aeObjectTypeList[obj]].explosionDamage);
1254 }
1255 } else {
1257 objectClass == OBJECT_CLASS_ASTEROID)
1258 explosionType = OBJECT_TYPE_EXPLOSION0;
1259 else
1260 explosionType = OBJECT_TYPE_EXPLOSION2;
1261 explosion = obj;
1262 set_objects_data(obj, explosionType,
1263 acObjOwnersTable[obj]);
1265 awObjectScales[obj] = 0x380;
1267 obj, aObjectTypeData[
1268 aeObjectTypeList[obj]].explosionDamage);
1269 }
1270 if (asObjectScreenXList[obj] != (short)0x8001)
1271 PlaySfxWaveFileByNumber(4, obj, 0);
1272 return explosion;
1273}
1274
1275/* Function start: 0x41FEB0 */
1276short the_creator(short obj)
1277{
1278 signed char owner;
1279
1280 for (;;) {
1281 if (obj == -1)
1282 return -1;
1283 owner = acObjOwnersTable[obj];
1284 if (obj == owner || owner == -1)
1285 return obj;
1286 obj = owner;
1287 }
1288 return -1;
1289}
1290
1291/* Function start: 0x41FEE0 */
1292int explosion_shock_wave(short obj, short blastDamage)
1293{
1294 short other;
1295 FixedVector delta;
1296 FixedVector force;
1297 short distance;
1298 short divisor;
1299 short damage;
1300
1301 other = 0;
1302 for (; other < 10; other++) {
1303 if (other != obj &&
1304 aeObjectClass[other] >= OBJECT_CLASS_SHIP) {
1306 &aShipPositionsArray[other], &delta);
1307 distance = FixedToShortSaturating(
1308 Vector_magnitude(&delta));
1309 distance = MaxShort(0,
1310 (short)(distance -
1311 asObjectCollisionRadius[other]));
1312 if (distance > 1000) {
1313 damage = 0;
1314 } else {
1315 if (distance > 750) {
1316 divisor = 40;
1317 } else {
1318 divisor = 30;
1319 if (distance <= 500)
1320 divisor = find_ratio(0, 500, distance, 8, 25);
1321 }
1322 damage = (short)((blastDamage / divisor) / divisor);
1323 if (other == 0)
1324 damage = MaxShort(1,
1325 (short)(damage * 3 >> 2));
1326 }
1327 if (damage > 1) {
1328 NormalizeFixedVector(&delta);
1329 ScaleFixedVector(&delta, (int)damage << 8, &force);
1330 apply_force_to_objects_center(&force, other);
1331 inflict_damage(the_creator(obj), other,
1332 MinShort(100, damage), &delta);
1333 }
1334 }
1335 }
1336 return 0;
1337}
1338
1339/* Function start: 0x420040 */
1340int explode(short attacker, short victim)
1341{
1342 if (victim < 10 && acShipRating[victim] != -1 &&
1343 acShipRating[victim] != RATING_ACE_ICEMAN) {
1344 if (acShipRating[victim] > RATING_ACE_ICEMAN) {
1345 if (ace_status(
1346 (short)(acShipRating[victim] -
1348 0x20) != 0) {
1349 unflag_ace(
1350 (short)(acShipRating[victim] -
1352 0x20);
1353 acShipStressList[victim] = -25;
1355 acShipDmg[victim] =
1356 (signed char)(acShipDmg[victim] / 2);
1357 send_message(victim, 6);
1358 return 0;
1359 }
1360 if (RandomBelowOrEqual(1) == 0)
1361 return 0;
1362 } else if (RandomBelowOrEqual(1) == 0)
1363 return 0;
1364 }
1365 if (aeSpecialManeuvers[victim] ==
1368 return 0;
1369
1370 if (victim == 0) {
1371 if (bPlayerVulnerable == 0)
1372 return 0;
1374 nArcadeState = 4;
1375 return 1;
1376 }
1377
1378 if (nExternalViewShip == victim)
1379 nExternalViewShip = -1;
1380 attacker = the_creator(attacker);
1381 if (attacker != -1 &&
1383 analyze_kill(attacker, victim);
1384 Explosion(victim);
1385 return 1;
1386}
1387
1388/* Function start: 0x420190 */
1389int send_at_point(short obj, FixedVector *point, short speed)
1390{
1392 &aShipVelocity[obj]);
1394 speed);
1395 return 0;
1396}
1397
1398/* Function start: 0x4201D0 */
1399short find_child_object(short parent, enum ObjectClass objectClass)
1400{
1401 short obj = 0;
1402 short wantedParent = parent;
1403 enum ObjectClass wantedClass = objectClass;
1404
1405 do {
1406 if ((short)acObjOwnersTable[obj] == wantedParent &&
1407 aeObjectClass[obj] == wantedClass)
1408 return obj;
1409 obj++;
1410 } while (obj < SPACE_OBJECT_COUNT);
1411 return -1;
1412}
1413
1414/* Function start: 0x420210 */
1415short find_child_ship(short parent, enum ObjectClass objectClass,
1416 short target)
1417{
1418 short obj;
1419
1420 for (obj = 0; obj < 10; obj++) {
1421 if ((short)acObjOwnersTable[obj] == parent &&
1422 aeObjectClass[obj] == objectClass &&
1423 (target == -1 ||
1424 acShipTargetTable[obj] == target))
1425 return obj;
1426 }
1427 return -1;
1428}
1429
1430/* Function start: 0x420260 */
1431int launch_object(short parent, short child, FixedVector direction,
1432 short speed)
1433{
1434 NormalizeFixedVector(&direction);
1436 &direction,
1437 &aShipVelocity[child]);
1438 ScaleFixedVector(&direction, (int)speed << 8, &direction);
1439 AddFixedVectors(&direction, &aShipVelocity[child],
1440 &aShipVelocity[child]);
1441 return 0;
1442}
1443
1444/* Function start: 0x4202D0 */
1445void fire(short obj, short target)
1446{
1447 ObjectTypeData *weaponData;
1448 enum ObjectType weaponType;
1449 enum ObjectClass weaponClass;
1450 FixedVector direction;
1451 FixedVector *interceptPoint;
1452 short velocityAngle;
1453 short mineTime;
1454 short closingSpeed;
1455 short weaponVelocity;
1456 short weapon;
1457 short range;
1458 short firedObject;
1459 short predictionTime;
1460 short predictedSeparation;
1461 short shouldFire;
1462 int canFire;
1463 int fireMissile;
1464 int minePresent = 0;
1465 int targetInRange;
1466
1467 canFire = asObjectCounterArray[obj] <= 0;
1468 get_facing_range_from_object(obj, target);
1469 range = nTgtRange;
1470 closingSpeed = (short)(((anShipSpeed[target] *
1471 (int)nTargetFacingValue) / 100) >> 8);
1472 fireMissile = RandomBelowOrEqual(19) == 0 &&
1473 RandomBelowOrEqual(7000) > range;
1474 if (fireMissile &&
1475 find_child_ship(obj, OBJECT_CLASS_MISSILE, target) != -1)
1476 fireMissile = 0;
1477 if (find_child_object(obj, OBJECT_CLASS_MINE) != -1)
1478 minePresent = 1;
1479
1480 for (weapon = 0; weapon < aShipWeaponsTable[obj][0]; weapon++) {
1481 weaponType =
1482 ((ShipWeaponSlot *)&aShipWeaponsTable[obj][1])[weapon].type;
1483 weaponData = &aObjectTypeData[weaponType];
1484 weaponVelocity = weaponData->maximumVelocity;
1485 if (closingSpeed < 0)
1486 weaponVelocity = (short)(weaponVelocity + closingSpeed / 100);
1487 targetInRange =
1488 (short)(weaponData->lifetime * weaponVelocity) > range;
1489 shouldFire = 0;
1490 weaponClass = weaponData->objectClass;
1491
1492 switch (weaponClass) {
1494 if (canFire && targetInRange) {
1495 switch (weaponType) {
1497 shouldFire = nFacingToTargetValue > 70;
1498 break;
1500 shouldFire = nFacingToTargetValue > 80;
1501 break;
1503 shouldFire = nFacingToTargetValue > 85;
1504 break;
1505 case OBJECT_TYPE_TURRET:
1506 shouldFire = nFacingToTargetValue > 10;
1507 break;
1508 }
1509 }
1510 ((ShipWeaponSlot *)&aShipWeaponsTable[obj][1])[weapon].disabled =
1511 (signed char)!shouldFire;
1512 if (shouldFire) {
1513 firedObject = (short)fire_weapon(obj, weapon);
1514 if (weaponType == OBJECT_TYPE_TURRET) {
1516 &aShipPositionsArray[firedObject],
1517 &aShipPositionsArray[target], &direction);
1518 launch_object(obj, firedObject, direction,
1519 real_velocity(firedObject));
1520 }
1521 }
1522 break;
1523 case OBJECT_CLASS_MINE:
1524 /* The first angle test deliberately preserves the original
1525 * stack-local ordering recovered at 0x42056a. */
1526 if (!minePresent && weaponType == OBJECT_TYPE_SPACE_MINE &&
1527 anShipSpeed[obj] >= 0x500 &&
1528 velocityAngle >= 75 && range <= 2000 &&
1529 nFacingToTargetValue >= -50 &&
1530 nTargetFacingValue <= 90) {
1531 velocityAngle = vector_angle(
1532 aShipVelocity[obj],
1533 aShipVelocity[target]);
1534 predictionTime = (short)(900 /
1535 (short)((anShipSpeed[obj] >> 8) + 20));
1536 predictedSeparation = (short)(predictionTime *
1537 (short)(-20 - closingSpeed) + range);
1538 if (closingSpeed == -20)
1539 mineTime = range;
1540 else
1541 mineTime = (short)(range / (closingSpeed + 20));
1542 shouldFire = range < 2000 && nFacingToTargetValue < -50 &&
1543 nTargetFacingValue > 90 && predictedSeparation > 50;
1544 }
1545 if (shouldFire) {
1546 firedObject = (short)drop_mine(
1547 obj, (signed char)weapon, weaponType,
1548 (short)(mineTime + 15));
1549 if (firedObject != -1) {
1551 (int)mineTime, &direction);
1552 interceptPoint = &aShipPositionsArray[
1553 SPACE_OBJECT_COUNT - 1];
1555 &direction, interceptPoint);
1557 &aShipPositionsArray[firedObject],
1558 interceptPoint, &direction);
1559 launch_object(obj, firedObject, direction, 20);
1560 }
1561 minePresent = 1;
1562 }
1563 break;
1565 if (fireMissile && targetInRange) {
1566 switch (weaponType) {
1568 shouldFire = nFacingToTargetValue > 97;
1569 break;
1571 shouldFire = nFacingToTargetValue > 40 &&
1572 nTargetFacingValue < -60;
1573 break;
1575 shouldFire = 1;
1576 break;
1578 shouldFire = nFacingToTargetValue > 40;
1579 break;
1580 }
1581 }
1582 if (shouldFire) {
1583 fire_weapon(obj, weapon);
1584 fireMissile = 0;
1585 }
1586 break;
1587 }
1588 }
1589}
1590
1591/* Function start: 0x4207E0 */
1592short hemisphere(FixedVector *target, FixedVector *parent,
1593 FixedVector *hardpoint)
1594{
1595 FixedVector parentFromHardpoint;
1596 FixedVector parentFromTarget;
1597
1598 ComputeVectorDelta(hardpoint, parent, &parentFromHardpoint);
1599 ComputeVectorDelta(target, parent, &parentFromTarget);
1600 return vector_angle(parentFromHardpoint, parentFromTarget);
1601}
1602
1603/* Function start: 0x420840 */
1604int fire_flack(short owner, short explosion, short range,
1605 FixedVector *aim)
1606{
1607 short projectileVelocity;
1608 short lifetime;
1609
1610 projectileVelocity =
1612 set_objects_data(explosion, OBJECT_TYPE_TURRET, owner);
1613 lifetime = (short)(range / projectileVelocity -
1614 RandomBelowOrEqual(8) - 5);
1615 lifetime = MaxShort(5, lifetime);
1616 lifetime = MinShort(27, lifetime);
1617 asObjectCounterArray[explosion] = lifetime;
1618 send_at_point(explosion, aim, projectileVelocity);
1619 return 0;
1620}
1621
1622/* Function start: 0x4208C0 */
1623short rnd_sign(short v)
1624{
1625 if (RandomBelowOrEqual(1) != 0)
1626 return v;
1627 return -v;
1628}
1629
1630/* Function start: 0x4208E0 */
1631int rnd_aim(short radius, short speed, short maximum)
1632{
1633 short aim;
1634
1635 aim = MinShort(maximum,
1636 (short)(RandomBelowOrEqual(radius) + speed));
1637 return rnd_sign(aim) << 8;
1638}
1639
1640/* Function start: 0x420920 */
1641short pop_flack(short obj, short range, FixedVector *hardpoint)
1642{
1643 FixedVector randomAim;
1644 FixedVector aimPoint;
1645 short target;
1646 short explosion;
1647 short aimRadius;
1648 short targetSpeed;
1649 short chance;
1650
1651 target = acShipTargetTable[obj];
1652 explosion = new_object(OBJECT_TYPE_EXPLOSION0, obj);
1653 if (explosion != -1) {
1654 aimRadius = MaxShort(400, (short)(range >> 2));
1655 targetSpeed = (short)(real_velocity(target) << 4);
1656 randomAim.x = rnd_aim(aimRadius, targetSpeed, 1500);
1657 randomAim.y = rnd_aim(aimRadius, targetSpeed, 1500);
1658 randomAim.z = rnd_aim(aimRadius, targetSpeed, 1500);
1659 AddFixedVectors(&aShipPositionsArray[target], &randomAim,
1660 &aimPoint);
1661 chance = RandomBelowOrEqual(100);
1662 if ((asObjectCounterArray[obj] != -1 || chance >= 40) &&
1663 chance >= 8) {
1664 aShipPositionsArray[explosion] = aimPoint;
1666 explosion,
1668 OBJECT_TYPE_TURRET].explosionDamage);
1669 return explosion;
1670 }
1671 aShipPositionsArray[explosion] = *hardpoint;
1672 fire_flack(obj, explosion, range, &aimPoint);
1673 asObjectCounterArray[obj] = (short)(RandomBelow(10) + 7);
1674 }
1675 return explosion;
1676}
1677
1678/* Turret target-list callee. */
1679short build_target_list(short obj, short range);
1680
1681/* Function start: 0x420AA0 */
1682int fire_turrets(short obj)
1683{
1684 ShipWeaponSlot *slot;
1685 FixedVector hardpoint;
1686 short lastTarget;
1687 short weapon;
1688 short startTarget;
1689 short targetIndex;
1690 short target;
1691 short targetHemisphere;
1692
1693 lastTarget = build_target_list(obj, 5000);
1694 if (lastTarget-- == 0)
1695 return 0;
1696
1697 slot = (ShipWeaponSlot *)&aShipWeaponsTable[obj][1];
1698 for (weapon = 0;
1699 weapon < aShipWeaponsTable[obj][0];
1700 weapon++, slot++) {
1701 if (RandomBelowOrEqual(2) == 0) {
1702 position_child(obj, slot->hardpoint, &hardpoint);
1703 startTarget = RandomBelowOrEqual(lastTarget);
1704 targetIndex = startTarget;
1705 do {
1706 target = (short)acFormationMemberLists[
1707 targetIndex];
1708 targetHemisphere = hemisphere(
1709 &aShipPositionsArray[target],
1710 &aShipPositionsArray[obj], &hardpoint);
1711 if (slot->type != OBJECT_TYPE_TURRET) {
1712 if (targetHemisphere > 50 &&
1713 RandomBelowOrEqual(14) == 0) {
1714 acShipTargetTable[obj] =
1715 (signed char)target;
1716 fire_weapon(obj, weapon);
1717 }
1718 break;
1719 }
1720 if (targetHemisphere >= 25) {
1721 acShipTargetTable[obj] = target;
1722 pop_flack(obj,
1723 asTargetListRangesArray[targetIndex],
1724 &hardpoint);
1725 break;
1726 }
1727 targetIndex++;
1728 if (targetIndex > lastTarget)
1729 targetIndex = 0;
1730 } while (targetIndex != startTarget);
1731 }
1732 }
1733 return 1;
1734}
1735
1736/* Function start: 0x420C20 */
1737int fire_weapon(short obj, short weapon)
1738{
1739 ObjectTypeData *weaponData;
1740 enum ObjectType weaponType;
1741 enum ObjectClass weaponClass;
1742 FixedVector vector;
1743 FixedVector cockpitOffset;
1744 int weaponOffset;
1745 int range;
1746 int sound;
1747 short projectileSpeed;
1748 short projectile;
1749
1750 projectileSpeed = 10;
1751 weaponOffset = (int)obj * sizeof(aShipWeaponsTable[0]) +
1752 (int)weapon * sizeof(ShipWeaponSlot);
1753 weaponType = ((ShipWeaponSlot *)((unsigned char *)
1754 aShipWeaponsTable + weaponOffset + 1))->type;
1755 weaponClass = aObjectTypeData[weaponType].objectClass;
1756 if (weaponType == OBJECT_TYPE_TURRET) {
1757 weaponClass = OBJECT_CLASS_PROJECTILE;
1758 weaponType = OBJECT_TYPE_LASER_CANNON;
1759 }
1760 if (weaponClass == OBJECT_CLASS_MINE)
1761 return drop_mine(obj, (signed char)weapon, weaponType, -1);
1762 if (weaponClass == OBJECT_CLASS_MISSILE)
1763 projectile = initialize_ship(weaponType, obj);
1764 else
1765 projectile = new_object(weaponType, obj);
1766 if (projectile != -1) {
1767 weaponData = &aObjectTypeData[weaponType];
1768 copy_frame(obj, projectile);
1769 if (weaponClass == OBJECT_CLASS_PROJECTILE) {
1770 asShipAccumulatedDmg[projectile] =
1771 weaponData->damageCapacity;
1772 projectileSpeed = aObjectTypeData[
1773 aeObjectTypeList[projectile]].maximumVelocity;
1774 asShipWpnEnergyList[obj] =
1775 (short)(asShipWpnEnergyList[obj] -
1776 weaponData->animationDelay);
1777 }
1779 ((ShipWeaponSlot *)((unsigned char *)aShipWeaponsTable +
1780 weaponOffset + 1))->hardpoint,
1781 projectile, obj);
1782 asObjectCounterArray[projectile] =
1783 aObjectTypeData[weaponType].lifetime;
1785 &aShipFwdVec[projectile],
1786 &aShipVelocity[projectile]);
1787 if (weaponClass == OBJECT_CLASS_PROJECTILE) {
1788 range = (short)((weaponData->lifetime + 5) *
1789 weaponData->maximumVelocity);
1791 range << 8, &vector);
1792 AddFixedVectors(&aShipPositionsArray[obj], &vector,
1793 &vector);
1794 point_at(projectile, vector);
1795 if (bCockpitlessView != 0 && cCurrentCockpitView == 3) {
1796 ScaleFixedVector(&aShipUpVector[obj], 0x12200,
1797 &cockpitOffset);
1798 AddFixedVectors(&cockpitOffset, &vector, &vector);
1799 point_at(projectile, vector);
1800 }
1801 }
1802 ScaleFixedVector(&aShipFwdVec[projectile],
1803 (int)projectileSpeed << 8, &vector);
1804 AddFixedVectors(&vector, &aShipVelocity[projectile],
1805 &aShipVelocity[projectile]);
1806 if (weaponClass == OBJECT_CLASS_MISSILE) {
1807 ScaleFixedVector(&aShipUpVector[obj], 0xa00,
1808 &vector);
1809 AddFixedVectors(&vector, &aShipVelocity[projectile],
1810 &aShipVelocity[projectile]);
1811 if (obj == 0)
1812 RemovePlayerReleaseWeapon((signed char)weapon);
1813 else
1814 remove_weapon(obj, weapon);
1815 acObjCollisionGraceTicks[projectile] = 20;
1816 aeSpecialManeuvers[projectile] =
1818 aeShipManeuversTable[projectile] = MANEUVER_NONE;
1819 aeShipTacticArray[projectile] = TACTIC_SIT_STILL;
1820 asObjectCounterArray[projectile] = 5;
1821 switch (weaponType) {
1823 steady_object(projectile);
1824 asObjectCounterArray[projectile] = 1;
1825 acShipTargetTable[projectile] =
1826 acShipTargetTable[obj];
1827 anShipSpeed[projectile] =
1828 get_ship_max_velocity(projectile) << 8;
1829 if (acShipTargetTable[projectile] != -1) {
1832 acShipTargetTable[projectile]], &vector);
1833 range = Vector_magnitude(&vector);
1834 range /= get_ship_max_velocity(projectile);
1836 acShipTargetTable[projectile]],
1837 range, &vector);
1839 acShipTargetTable[projectile]], &vector,
1840 &vector);
1841 point_at(projectile, vector);
1842 }
1843 break;
1846 acShipTargetTable[projectile] =
1847 acShipTargetTable[obj];
1848 break;
1850 acShipTargetTable[projectile] = -1;
1851 asObjectCounterArray[projectile] = 15;
1852 break;
1853 }
1854 }
1855 if (obj == 0) {
1856 if (weaponClass == OBJECT_CLASS_PROJECTILE) {
1859 weaponType - OBJECT_TYPE_LASER_CANNON];
1860 }
1861 } else {
1862 asObjectCounterArray[obj] = 12;
1863 }
1864 switch (weaponType) {
1867 sound = 8;
1868 PlaySfxWaveFileByNumber(sound, projectile, 0);
1869 break;
1871 case OBJECT_TYPE_TURRET:
1872 sound = 5;
1873 PlaySfxWaveFileByNumber(sound, projectile, 0);
1874 break;
1879 sound = 1;
1880 PlaySfxWaveFileByNumber(sound, projectile, 0);
1881 break;
1882 }
1883 }
1884 return projectile;
1885}
1886
1887/* Function start: 0x421100 */
1888short find_weapon(short obj, enum ObjectType weaponType)
1889{
1890 short weapon;
1891
1892 for (weapon = 0;
1893 weapon < aShipWeaponsTable[obj][0];
1894 weapon++) {
1895 ShipWeaponSlot *weaponSlot =
1896 &((ShipWeaponSlot *)&aShipWeaponsTable[obj][1])[weapon];
1897
1898 if (weaponSlot->type == weaponType)
1899 return weapon;
1900 }
1901 return -1;
1902}
1903
1904/* Function start: 0x421150 */
1905int fire_missile(short ship)
1906{
1907 short weapon;
1908 ShipWeaponSlot *slot;
1909
1910 slot = (ShipWeaponSlot *)&aShipWeaponsTable[ship][1];
1911 for (weapon = 0; weapon < aShipWeaponsTable[ship][0];
1912 weapon++, slot++) {
1913 if (aObjectTypeData[slot->type].objectClass ==
1915 if (ship != 0)
1916 return fire_weapon(ship, weapon);
1917 if (slot->disabled == 0) {
1918 if ((slot->type == OBJECT_TYPE_HEAT_SEEKING_MISSILE ||
1920 nTargetLockCountdown != 0) {
1921 if (get_mode(0) == 1)
1923 "Need Lock",
1924 cYellowColour, 3);
1925 return -1;
1926 }
1927 return fire_weapon(ship, weapon);
1928 }
1929 }
1930 }
1931 return -1;
1932}
1933
1934/* Function start: 0x421220 */
1936{
1937 short weapon;
1938 ShipWeaponSlot *slot;
1939
1940 slot = (ShipWeaponSlot *)&aShipWeaponsTable[obj][1];
1941 for (weapon = 0; weapon < aShipWeaponsTable[obj][0]; weapon++, slot++)
1942 if (aObjectTypeData[slot->type].objectClass ==
1944 slot->disabled == 0)
1945 if (fire_weapon(obj, weapon) == -1)
1946 return -1;
1947 /* The original leaves EAX incidental on successful and empty paths. */
1948}
1949
1950/* Function start: 0x4212A0 */
1951int drop_mine(short obj, signed char weapon, enum ObjectType type,
1952 short lifetime)
1953{
1954 ShipWeaponSlot *weaponSlot;
1955 short mine;
1956
1957 mine = new_object(type, obj);
1958 if (mine == -1)
1959 return -1;
1960 copy_frame(obj, mine);
1961 weaponSlot =
1962 &((ShipWeaponSlot *)&aShipWeaponsTable[obj][1])[weapon];
1963 child_object(weaponSlot->hardpoint, mine, obj);
1964 if (lifetime == -1)
1965 lifetime = 20;
1966 acObjCollisionGraceTicks[mine] = (signed char)lifetime;
1967 asObjectCounterArray[mine] = (short)(signed char)lifetime;
1968 if (obj == 0)
1970 else
1971 remove_weapon(obj, weapon);
1972 return mine;
1973}
1974
1975/* Function start: 0x421350 */
1976void fire_afterburner(short obj, short time)
1977{
1978 short timer;
1979
1980 if (Vector_magnitude(&aShipVelocity[obj]) <
1981 get_ship_max_velocity(obj) * 0x500L) {
1984 timer = 0;
1985 else
1986 timer = time;
1987 asShipAfterburnerTimer[obj] = timer;
1988 }
1989}
1990
1991/* Function start: 0x4213B0 */
1992unsigned int fire_super_brake(short ship)
1993{
1994 asShipAfterburnerTimer[ship] = 10;
1996 return 0;
1997}
1998
1999/* Function start: 0x4213D0 */
2000short flip_angle(short ship, short angle)
2001{
2002 short flip;
2003
2004 flip = asObjectFlipArray[ship];
2005 if ((flip & 0x10) != 0)
2006 angle = (short)(180 - angle);
2007 if ((flip & 0x20) != 0)
2008 angle = (short)-angle;
2009 angle += asObjScreenAngles[ship];
2010 angle %= 360;
2011 if (angle < 0)
2012 angle += 360;
2013 return angle;
2014}
2015
2016/* Function start: 0x421430 */
2017unsigned int place_exhaust_on_ships(void)
2018{
2019 short *animation;
2020 short frame;
2021 short scale;
2022 short object;
2023 short ship;
2024
2025 for (ship = 0; ship < 10; ship++) {
2026 if (aeObjectClass[ship] >= OBJECT_CLASS_MISSILE &&
2027 anShipSpeed[ship] != 0 &&
2028 aeSpecialManeuvers[ship] !=
2030 asObjectScreenXList[ship] != (short)0x8001) {
2031 animation = (short *)aObjectTypeData[
2032 aeObjectTypeList[ship]].animation;
2033 if (animation != 0) {
2034 object = animation[asObjectViewFrames[ship]];
2035 if (object != -1) {
2036 animation = (short *)((unsigned char *)animation + object);
2037 while (*animation != -1) {
2038 object = find_vacant_3d_object();
2039 if (object == -1)
2040 return 0;
2042 ship);
2043 frame = *animation++;
2044 scale = *animation++;
2045 scale -= RandomInRange(0, 32);
2046 if (abShipExhaustHeatList[ship] == 0)
2047 scale = (short)(scale - 32);
2048 awObjectScales[object] = scale;
2049 asObjDistancesTable[object] = *animation++;
2050 asObjScreenAngles[object] =
2051 flip_angle(ship, *animation++);
2052 asObjectFlipArray[object] = 0;
2053 asObjectScreenXList[object] = *animation++;
2054 asObjectScreenYArray[object] = *animation++;
2055 if (aeSpecialManeuvers[ship] ==
2057 asObjectViewFrames[object] =
2058 (short)(frame * 3 +
2059 RandomInRange(0, 2));
2060 } else {
2061 asObjectViewFrames[object] =
2062 (short)(frame * 2 + 12 +
2063 RandomInRange(0, 1));
2064 }
2065 }
2066 }
2067 }
2068 }
2069 }
2070 /* The original leaves EAX incidental after scanning every ship. */
2071}
2072
2073/* Function start: 0x4215E0 */
2075{
2076 int right;
2077 int up;
2078 long sine;
2079 long cosine;
2080 short angle;
2081 short parent;
2082 short object;
2083
2084 for (object = 10; object <= SPACE_LAST_MOVING_OBJECT; object++) {
2085 if (aeObjectClass[object] ==
2087 parent = (short)acObjOwnersTable[object];
2088 if (aeObjectTypeList[object] ==
2090 aeObjectTypeList[object] ==
2092 angle = asObjScreenAngles[parent];
2093 sine = SinFixed(angle);
2094 cosine = CosFixed(angle);
2095 right = (int)asObjectScreenXList[object] *
2096 (unsigned short)asObjScreenScalesArray[parent];
2097 asObjDistancesTable[object] +=
2098 asObjDistancesTable[parent];
2099 if ((asObjectFlipArray[parent] & 0x10) != 0)
2100 right = -right;
2101 up = (int)asObjectScreenYArray[object] *
2102 (unsigned short)asObjScreenScalesArray[parent];
2103 if ((asObjectFlipArray[parent] & 0x20) != 0)
2104 up = -up;
2105 asObjectScreenXList[object] = (short)(
2106 (MultiplyFixed(right, (int)cosine) -
2107 MultiplyFixed(up, (int)sine)) >> 8);
2108 asObjectScreenYArray[object] = (short)(
2109 (MultiplyFixed(up, (int)cosine) +
2110 MultiplyFixed(right, (int)sine)) >> 8);
2111 asObjectScreenXList[object] +=
2112 asObjectScreenXList[parent];
2113 asObjectScreenYArray[object] +=
2114 asObjectScreenYArray[parent];
2115 }
2116 asObjScreenScalesArray[object] = (short)(
2117 (unsigned short)
2118 asObjScreenScalesArray[parent] *
2119 (unsigned short)
2120 awObjectScales[object] >> 8);
2121 }
2122 }
2123 return 0;
2124}
2125
2126/* Function start: 0x421760 */
2127unsigned int housekeep_power_plant_and_fuel(short ship)
2128{
2129 if (0 < anShipSpeed[ship])
2130 drain_fuel(ship, 5);
2131 return 0;
2132}
2133
2134/* Function start: 0x421780 */
2135unsigned int replenish_shields(short ship)
2136{
2137 signed char shield;
2138
2139 if (ship == 0 && acPlayerComponentDamageList[1] > 0 &&
2141 (acPlayerComponentDamageList[1] + 1) != 0)
2142 return 0;
2143 for (shield = 0; shield <= 1; shield++) {
2144 if (aasShipShield[ship][shield] >
2145 aasShipMaximumShieldTable[ship][shield])
2146 aasShipShield[ship][shield] =
2147 aasShipMaximumShieldTable[ship][shield];
2148 if (aasShipShield[ship][shield] <
2149 aasShipMaximumShieldTable[ship][shield] &&
2151 aObjectTypeData[aeObjectTypeList[ship]].animationDelay == 0)
2152 aasShipShield[ship][shield]++;
2153 }
2154 return 0;
2155}
2156
2157/* Function start: 0x421830 */
2158unsigned int replenish_weapon_energy_bank(short ship)
2159{
2160 short energy;
2161 short shieldEnergy;
2162 short maximumShield;
2163
2164 if (ship == 0 && acPlayerComponentDamageList[1] != 0 &&
2165 (int)(unsigned short)RandomInRange(0, 4) <
2167 return 0;
2168 energy = asShipWpnEnergyList[ship];
2169 if (energy < 100) {
2170 shieldEnergy = aasShipShield[ship][0];
2171 maximumShield = aasShipMaximumShieldTable[ship][0];
2172 shieldEnergy =
2173 (short)(shieldEnergy + aasShipShield[ship][1]);
2174 maximumShield =
2175 (short)(maximumShield +
2176 aasShipMaximumShieldTable[ship][1]);
2177 if (shieldEnergy < maximumShield) {
2178 asShipWpnEnergyList[ship] =
2179 MinShort((short)(energy + 1), 100);
2180 } else {
2181 asShipWpnEnergyList[ship] =
2182 MinShort((short)(energy + 2), 100);
2183 }
2184 }
2185 return 0;
2186}
2187
2188/* Function start: 0x4218D0 */
2189void accelerate(short amount)
2190{
2191 if (malf(0) != 0) {
2192 amount = (short)(amount - 2);
2193 if (nCurrentSpaceFrameValue % 3 == 0)
2194 PlaySfxWaveFileByNumber(3, -1, 0);
2195 }
2196 celerate(0, (int)amount << 8);
2197}
2198
2199/* Function start: 0x421920 */
2201{
2202 short time;
2203
2204 if (anShipFuelsTable[0] <= 0)
2205 return;
2206 if (malf(0) != 0) {
2207 PlaySfxWaveFileByNumber(3, -1, 0);
2208 return;
2209 }
2210 if (aeSpecialManeuvers[0] !=
2212 time = 8;
2213 } else if (asShipAfterburnerTimer[0] == 0) {
2214 time = 8;
2215 } else {
2216 if (asShipAfterburnerTimer[0] > 2)
2217 return;
2218 time = 2;
2219 }
2220 fire_afterburner(0, time);
2225 PlaySfxWaveFileByNumber(12, -1, 0);
2226 }
2227}
unsigned char cYellowColour
Definition init.c:15
signed char acShipRating[16]
Definition joycal.c:25
signed char acShipDestroyedWeaponCountArray[16]
Definition screen.c:31
short asViableTgtDistList[16]
Definition game.c:555
enum ShipTactic aeShipTacticArray[12]
Definition input.c:20
short asObjScreenScalesArray[SPACE_OBJECT_COUNT]
Definition dib.c:105
short anShipMissionShips[16]
Definition comm.c:57
unsigned char cRedColour
Definition init.c:16
signed char abShipExhaustHeatList[10]
Definition input.c:21
short nCurrentWave
Definition game.c:34
signed char acViableTargetList[16]
Definition dib.c:102
short nMissionMedalScoreValue
Definition gameflow.c:29
enum Side aeShipSide[12]
Definition ending.c:22
short anRollGoal[16]
Definition ending.c:21
int bAfterburnerSfxEnabled
Definition ship.c:64
signed char acShipStressList[16]
Definition ending.c:20
signed char aShipWeaponsTable[10][0x47]
Definition dib.c:108
int nMemoryConfig
Definition ship.c:58
signed char acPlayerComponentDamageList[9]
Definition smart.c:19
short asObjScreenAngles[SPACE_OBJECT_COUNT]
Definition joycal.c:26
enum ShipManeuver aeShipManeuversTable[12]
Definition screen.c:25
ObjectTypeData aObjectTypeData[OBJECT_TYPE_COUNT]
Definition objdata.c:86
short aasShipMaximumShieldTable[10][2]
Definition ending.c:26
short anPitchGoal[16]
Definition screen.c:13
short anObjectRollRotationList[SPACE_OBJECT_COUNT]
Definition screen.c:16
signed char cViableTargetCount
Definition game.c:107
short anObjectYawRotation[SPACE_OBJECT_COUNT]
Definition joycal.c:33
short anObjPitchRot[SPACE_OBJECT_COUNT]
Definition data.c:247
short asShipAccumulatedDmg[SPACE_OBJECT_COUNT]
Definition music.c:89
signed char acShipIonDriveDmg[16]
Definition comm.c:56
short nTgtRange
Definition joycal.c:27
int anShipFuelsTable[12]
Definition data.c:252
short asShipMaximumSpeedArray[16]
Definition game.c:552
signed char acShipDmg[10]
Definition game.c:553
int bCockpitlessView
Definition main.c:39
short nFacingToTargetValue
Definition screen.c:19
short asShipWpnEnergyList[10]
Definition comm.c:54
short nTargetLockCountdown
Definition game.c:79
int nAvailableGameMemory
Definition ship.c:61
FixedVector aShipRightVector[64]
Definition smart.c:15
short asObjAfterburnerVelocities[SPACE_OBJECT_COUNT]
Definition dib.c:106
short asTargetListRangesArray[16]
Definition video.c:17
int bCurrentPlayerDestroyed
Definition logic.c:111
enum ObjectClass aeObjectClass[SPACE_OBJECT_COUNT]
Definition video.c:21
short nYourWingman
Definition game.c:61
short aasShipArmor[10][4]
Definition comm.c:53
signed char acFormationMemberLists[16]
Definition comm.c:55
const char * apszComponentNames[9]
Definition damage.c:18
short asObjectScreenYArray[SPACE_OBJECT_COUNT]
Definition screen.c:20
FixedVector aShipVelocity[SPACE_OBJECT_COUNT]
Definition smart.c:21
short asObjectCollisionRadius[64]
Definition ending.c:27
short nExternalViewShip
Definition game.c:52
short asShipAfterburnerTimer[16]
Definition game.c:558
short aasShipShield[10][2]
Definition input.c:19
signed char cCurrentCockpitView
Definition screen.c:23
short asCapitalShipViewFramesTable[16]
Definition screen.c:28
int nArcadeState
Definition main.c:22
int anShipSpeed[64]
Definition data.c:248
struct Shape * pMouseCursorResource
Definition ship.c:60
short nWingmanKillCount
Definition init.c:57
int nSceneResourceBudgetValue
Definition ship.c:62
unsigned short asObjDistancesTable[SPACE_OBJECT_COUNT]
Definition data.c:253
enum ObjectType eSelectedGunType
Definition game.c:67
short nTargetFacingValue
Definition input.c:17
short asObjectCounterArray[SPACE_OBJECT_COUNT]
Definition game.c:547
FixedVector aShipUpVector[64]
Definition smart.c:16
CampaignState stCampaignState
Definition dib.c:107
short asObjectScreenXList[SPACE_OBJECT_COUNT]
Definition screen.c:21
signed char acObjOwnersTable[64]
Definition joycal.c:29
short nCurrentSpaceFrameValue
Definition data.c:249
unsigned short awObjectScales[SPACE_OBJECT_COUNT]
Definition music.c:86
struct Shape * apObjShapeArray[SPACE_OBJECT_COUNT]
Definition comm.c:48
signed char acObjCollisionGraceTicks[SPACE_OBJECT_COUNT]
Definition screen.c:29
int nSelectedReleaseWeaponIndex
Definition game.c:70
enum ObjectType aeObjectTypeList[SPACE_OBJECT_COUNT]
Definition data.c:255
signed char acLastCollisionObjects[SPACE_OBJECT_COUNT]
Definition ending.c:25
short asObjectViewFrames[SPACE_OBJECT_COUNT]
Definition video.c:23
short asObjectFlipArray[SPACE_OBJECT_COUNT]
Definition dib.c:97
short nPlayerKillTotal
Definition logic.c:112
unsigned short awObjMassArray[SPACE_OBJECT_COUNT]
Definition game.c:557
MissionShipRecord aMissionShips[MISSION_SHIP_STORAGE_COUNT]
Definition game.c:230
signed char acPreviousAttackers[16]
Definition dib.c:101
short asObjectAnimationDelay[SPACE_OBJECT_COUNT]
Definition data.c:256
int dwOriginalFreeMem
Definition ship.c:59
short nShipMissionIndices[10]
Definition game.c:559
FixedVector aShipPositionsArray[SPACE_OBJECT_COUNT]
Definition game.c:556
FixedVector aShipFwdVec[64]
Definition smart.c:17
signed char acShipTargetTable[16]
Definition joycal.c:30
signed char acShipCommunicatorArray[16]
Definition game.c:560
short anYawTarget[16]
Definition smart.c:22
int nCurrentArcadeScore
Definition trainsim.c:36
signed char acPilotHitPointsArray[16]
Definition joycal.c:34
int nAfterburnerSoundDeadline
Definition ship.c:63
int nCurrentWingmanKilledThisMission
Definition init.c:56
enum SpecialManeuver aeSpecialManeuvers[12]
Definition game.c:549
short asObjectAnimIndexes[SPACE_OBJECT_COUNT]
Definition screen.c:22
int bPlayerVulnerable
Definition main.c:36
enum ObjectType aeShipHitDebrisTypes[3]
Definition ship.c:49
signed char acGunRefireDelay[4]
Definition ship.c:55
short asPlayerDamageSystemTable[50]
Definition ship.c:13
static enum ObjectType aaeExplosionDebris[4][7]
Definition ship.c:21
short missionScore
Definition wcdata.h:723
signed char state
Definition wcdata.h:896
short armorRight
Definition wcdata.h:392
short yawRate
Definition wcdata.h:383
short shieldFore
Definition wcdata.h:387
short rollRate
Definition wcdata.h:384
enum ObjectClass objectClass
Definition wcdata.h:370
short maximumVelocity
Definition wcdata.h:378
unsigned char * animation
Definition wcdata.h:380
short collisionRadius
Definition wcdata.h:371
short armorRear
Definition wcdata.h:390
short pitchRate
Definition wcdata.h:382
short scale
Definition wcdata.h:373
short animationDelay
Definition wcdata.h:374
short shieldAft
Definition wcdata.h:388
struct Shape * shapeSet
Definition wcdata.h:393
unsigned short mass
Definition wcdata.h:372
short damageCapacity
Definition wcdata.h:376
short afterburnerVelocity
Definition wcdata.h:385
unsigned char weaponLoadout[0x47]
Definition wcdata.h:386
short armorLeft
Definition wcdata.h:391
short armorFront
Definition wcdata.h:389
short hardpoint
Definition wcdata.h:409
enum ObjectType type
Definition wcdata.h:408
signed char disabled
Definition wcdata.h:410
Umbrella header for the game core.
short get_mode(short i)
Definition cockpt.c:690
int fire_flack(short owner, short explosion, short range, FixedVector *aim)
Definition ship.c:1604
void damage_ion_drive(short ship, short amount, short maximum)
Definition geom.c:132
short the_creator(short obj)
Definition ship.c:1276
short pilot_hit(short obj)
Definition ship.c:600
short ShipExplosion(short obj)
Definition ship.c:1170
short find_child_ship(short parent, enum ObjectClass objectClass, short target)
Definition ship.c:1415
long MultiplyFixed(int left, int right)
Definition mathfp.c:67
int send_at_point(short obj, FixedVector *point, short speed)
Definition ship.c:1389
unsigned int fire_super_brake(short ship)
Definition ship.c:1992
short pop_flack(short obj, short range, FixedVector *hardpoint)
Definition ship.c:1641
void place_damage_on_cockpit(short damage)
Definition cockpt.c:2660
void FillFixedVectorWithRandomComponents(short limit, FixedVector *vector)
Definition geom.c:357
unsigned int steady_object(short ship)
Definition ship.c:422
int dot_product(const FixedVector *left, const FixedVector *right)
Definition geom.c:441
void Create_ship_hit_debris(short obj, short count)
Definition ship.c:968
int drop_mine(short obj, signed char weapon, enum ObjectType type, short lifetime)
Definition ship.c:1951
unsigned int score_for_kill(short pilot, short victim)
Definition ship.c:1111
void remove_object(short obj)
Definition geom.c:1002
void fire_afterburner(short obj, short time)
Definition ship.c:1976
int explosion_shock_wave(short obj, short blastDamage)
Definition ship.c:1292
short recalc_max_velocity(short ship)
Definition geom.c:106
unsigned int analyze_kill(short attacker, short victim)
Definition ship.c:1151
int rnd_aim(short radius, short speed, short maximum)
Definition ship.c:1631
long Vector_magnitude(const FixedVector *vector)
Definition mathfp.c:132
unsigned int animate_shape(short obj)
Definition spc.c:1165
void AddFixedVectors(const FixedVector *left, const FixedVector *right, FixedVector *sum)
Definition geom.c:296
unsigned int match_rotation_goal(short *rotation, short *goal, short totalError, short rate)
Definition ship.c:287
void check_next_wave(void)
Definition ship.c:995
void set_objects_data(short obj, enum ObjectType type, short owner)
Definition ship.c:173
void set_up_next_wave(void)
Definition mission.c:687
void your_afterburner(void)
Definition ship.c:2200
void repair_internal_damage(void)
Definition ship.c:940
int inflict_damage(short attacker, short victim, short damage, const FixedVector *impactDirection)
Definition ship.c:503
int fire_turrets(short obj)
Definition ship.c:1682
void init_ijk(short obj)
Definition geom.c:568
int fire_missile(short ship)
Definition ship.c:1905
int launch_object(short parent, short child, FixedVector direction, short speed)
Definition ship.c:1431
short FixedToShortSaturating(int value)
Definition geom.c:193
unsigned int housekeep_power_plant_and_fuel(short ship)
Definition ship.c:2127
short get_ship_slot(void)
Definition geom.c:976
int rotate_object_to_goal(short obj)
Definition ship.c:328
long SinFixed(short degrees)
Definition mathfp.c:89
short MinShort(short a, short b)
Definition mathutil.c:20
unsigned int personality_killed(short personality)
Definition targ.c:124
unsigned int TriggerPlayerHitPaletteFlash(void)
Definition main.c:488
short find_ratio(short inputMinimum, short inputMaximum, short input, short outputMinimum, short outputMaximum)
Definition logic.c:1352
short rnd_sign(short v)
Definition ship.c:1623
short get_ship_max_velocity(short obj)
Definition geom.c:95
void InvalidateVduMode(short i)
Definition cockpt.c:764
int onboard_explosion(short obj)
Definition ship.c:620
int fire_fixed_projectile_weapon(short obj)
Definition ship.c:1935
unsigned int select_new_release_weapon(enum ObjectType preferredType)
Definition select.c:93
unsigned int replenish_weapon_energy_bank(short ship)
Definition ship.c:2158
short borrow_dust(void)
Definition ship.c:78
int explode(short attacker, short victim)
Definition ship.c:1340
short vector_angle(FixedVector left, FixedVector right)
Definition geom.c:451
unsigned int approach_speed(short ship, int targetSpeed)
Definition ship.c:405
void copy_frame(short source, short destination)
Definition geom.c:585
unsigned int check_computer_damage(void)
Definition ship.c:916
int damage_your_component(char component, char amount, char maximum)
Definition cockpt.c:864
void apply_force_to_objects_center(FixedVector *force, short obj)
Definition geom.c:1035
short initialize_ship(enum ObjectType type, short owner)
Definition ship.c:102
long CosFixed(short degrees)
Definition mathfp.c:95
unsigned int set_special(short ship, enum SpecialManeuver special)
Definition logic.c:729
void RemovePlayerReleaseWeapon(signed char weapon)
Definition cockpt.c:885
void ScaleFixedVector(const FixedVector *vector, int scale, FixedVector *result)
Definition geom.c:322
void ShowComponentHitHudMessage(const char *text, unsigned short colour, short flashCount)
Definition cockpt.c:847
unsigned int sort_viable_target_list(void)
Definition ship.c:447
void SetVectorFixedPoint(FixedVector *p, short v)
Definition geom.c:907
short build_target_list(short obj, short range)
Definition logic.c:1044
void send_message(short obj, short message)
Definition cockpt.c:2489
void position_child(short parent, short hardpoint, FixedVector *position)
Definition geom.c:950
short new_object(enum ObjectType type, short owner)
Definition ship.c:91
void zero_vector(FixedVector *vector)
Definition geom.c:280
void child_object(short hardpoint, short child, short parent)
Definition geom.c:969
short real_velocity(short obj)
Definition ship.c:431
void revise_shields(short obj)
Definition ship.c:781
unsigned int fix_velocity(short obj)
Definition ship.c:438
unsigned int place_exhaust_on_ships(void)
Definition ship.c:2017
short RandomBelow(short n)
Definition mathfp.c:29
void MakeRandomVectorFixed(short minimum, short maximum, FixedVector *vector)
Definition geom.c:349
int any_enemy(short obj, short range)
Definition logic.c:887
short hemisphere(FixedVector *target, FixedVector *parent, FixedVector *hardpoint)
Definition ship.c:1592
short find_child_object(short parent, enum ObjectClass objectClass)
Definition ship.c:1399
short malf(char component)
Definition cockpt.c:829
void new_space_music_changes(short attacker, short victim)
Definition music.c:480
short ReportComponentRepaired(short component, short minimumDamage)
Definition ship.c:923
short find_vacant_3d_object(void)
Definition geom.c:987
short initialize_object(short obj, enum ObjectType type, short owner)
Definition ship.c:67
void get_facing_range_from_object(short obj, short other)
Definition geom.c:691
unsigned int reposition_fixed_child_objects(void)
Definition ship.c:2074
short flip_angle(short ship, short angle)
Definition ship.c:2000
int your_internal_damage(short attacker, short damage, short quadrant)
Definition ship.c:794
void unflag_ace(short ace, unsigned char bits)
Definition logic.c:121
short Explosion(short obj)
Definition ship.c:1200
void PlaySfxWaveFileByNumber()
unsigned int Create_explosion_debris(short obj)
Definition ship.c:1010
void point_at(short obj, FixedVector point)
Definition geom.c:152
void fire(short obj, short target)
Definition ship.c:1445
void call_enemy(short obj)
Definition ship.c:642
unsigned int check_for_lost_control(short obj)
Definition ship.c:364
void divide_vector(FixedVector *vector, int divisor, FixedVector *result)
Definition geom.c:330
int internal_damage(short attacker, short victim, short damage, short quadrant)
Definition ship.c:660
void ComputeVectorDelta(const FixedVector *from, const FixedVector *to, FixedVector *delta)
Definition geom.c:314
int skill_check(short obj, short difficulty)
Definition logic.c:1158
unsigned int select_new_gun(void)
Definition select.c:83
unsigned int affect_mission_score(short pilot, int event, short amount)
Definition ship.c:1060
short MaxShort(short a, short b,...)
Definition mathutil.c:29
void vector_component_in_dir(const FixedVector *vector, const FixedVector *direction, FixedVector *component)
Definition geom.c:497
void accelerate(short amount)
Definition ship.c:2189
void send_appropriate_message(short attacker, short victim)
Definition ship.c:480
short any_selected(signed char *loadout, enum ObjectClass objectClass)
Definition ship.c:114
void FreePacketAndClear(void *slot, unsigned short releaseFlags)
Definition mathutil.c:37
short find_ship_index(short missionShip)
Definition logic.c:439
unsigned int SignFixed(int v)
Definition geom.c:246
short __stdcall RandomInRange(short lo, short hi)
Definition mathfp.c:49
int fire_weapon(short obj, short weapon)
Definition ship.c:1737
unsigned int remove_weapon(short obj, short weapon)
Definition ship.c:132
int alert_flag(short ship, unsigned int bits)
Definition logic.c:166
unsigned int replenish_shields(short ship)
Definition ship.c:2135
unsigned int celerate(short ship, int delta)
Definition ship.c:390
void reset_maneuver(short ship, short maneuver)
Definition logic.c:712
short ace_status(short ace, unsigned char bits)
Definition logic.c:115
short RandomBelowOrEqual(short n)
Definition mathfp.c:59
short NormalizeFixedVector(FixedVector *vector)
Definition geom.c:471
void drain_fuel(short ship, short amount)
Definition geom.c:124
short find_weapon(short obj, enum ObjectType weaponType)
Definition ship.c:1888
int GetShipAccelerationRate(short ship)
Definition geom.c:140
@ RATING_ACE_ICEMAN
Definition wcdata.h:191
@ RATING_ACE_ANGEL
Definition wcdata.h:192
#define SPACE_LAST_MOVING_OBJECT
Definition wcdata.h:1005
ObjectType
Definition wcdata.h:54
@ OBJECT_TYPE_EXPLOSION0
Definition wcdata.h:103
@ OBJECT_TYPE_KILRATHI_BASE
Definition wcdata.h:76
@ OBJECT_TYPE_FRALTHI
Definition wcdata.h:73
@ OBJECT_TYPE_NEUTRON_PARTICLE_GUN
Definition wcdata.h:80
@ OBJECT_TYPE_HEAT_SEEKING_MISSILE
Definition wcdata.h:84
@ OBJECT_TYPE_DEBRIS_METAL_SHEET
Definition wcdata.h:98
@ OBJECT_TYPE_FF_MISSILE
Definition wcdata.h:85
@ OBJECT_TYPE_MASS_DRIVER_CANNON
Definition wcdata.h:81
@ OBJECT_TYPE_LUMBARI
Definition wcdata.h:71
@ OBJECT_TYPE_DEBRIS_WING
Definition wcdata.h:99
@ OBJECT_TYPE_SNAKEIR
Definition wcdata.h:74
@ OBJECT_TYPE_RALARI
Definition wcdata.h:72
@ OBJECT_TYPE_DEBRIS_GLASS
Definition wcdata.h:100
@ OBJECT_TYPE_KRANT
Definition wcdata.h:66
@ OBJECT_TYPE_ROCK_CHUNK
Definition wcdata.h:95
@ OBJECT_TYPE_SALTHI
Definition wcdata.h:64
@ OBJECT_TYPE_DEBRIS_DUST
Definition wcdata.h:116
@ OBJECT_TYPE_EXPLOSION2
Definition wcdata.h:105
@ OBJECT_TYPE_GRATHA
Definition wcdata.h:67
@ OBJECT_TYPE_IMAGE_RECOGNITION_MISSILE
Definition wcdata.h:86
@ OBJECT_TYPE_DEBRIS_O_RING
Definition wcdata.h:101
@ OBJECT_TYPE_EXPLOSION1
Definition wcdata.h:104
@ OBJECT_TYPE_ASTEROID5
Definition wcdata.h:93
@ OBJECT_TYPE_SPIKERI
Definition wcdata.h:69
@ OBJECT_TYPE_ASTEROID3
Definition wcdata.h:91
@ OBJECT_TYPE_DORKIR
Definition wcdata.h:70
@ OBJECT_TYPE_SIVAR
Definition wcdata.h:75
@ OBJECT_TYPE_ASTEROID4
Definition wcdata.h:92
@ OBJECT_TYPE_LASER_CANNON
Definition wcdata.h:79
@ OBJECT_TYPE_DEBRIS_PIPE
Definition wcdata.h:102
@ OBJECT_TYPE_JALTHI
Definition wcdata.h:68
@ OBJECT_TYPE_THRUSTERS
Definition wcdata.h:110
@ OBJECT_TYPE_SPACE_DUST
Definition wcdata.h:115
@ OBJECT_TYPE_ASTEROID6
Definition wcdata.h:94
@ OBJECT_TYPE_DUMB_FIRE_MISSILE
Definition wcdata.h:83
@ OBJECT_TYPE_ASTEROID1
Definition wcdata.h:89
@ OBJECT_TYPE_ASTEROID2
Definition wcdata.h:90
@ OBJECT_TYPE_DEBRIS_SHIP_GIRDER_CHUNK
Definition wcdata.h:96
@ OBJECT_TYPE_TURRET
Definition wcdata.h:82
@ OBJECT_TYPE_DEBRIS_SHIP_TUBING
Definition wcdata.h:97
@ OBJECT_TYPE_DRALTHI
Definition wcdata.h:65
@ OBJECT_TYPE_SPACE_MINE
Definition wcdata.h:88
@ SIDE_KILRATHI
Definition wcdata.h:175
@ SIDE_NEUTRAL
Definition wcdata.h:176
#define SPACE_OBJECT_COUNT
Definition wcdata.h:1004
@ SPECIAL_MANEUVER_BLOWING_UP
Definition wcdata.h:267
@ SPECIAL_MANEUVER_SUPER_BRAKE
Definition wcdata.h:262
@ SPECIAL_MANEUVER_UNKNOWN_9
Definition wcdata.h:268
@ SPECIAL_MANEUVER_KILL_ENGINES
Definition wcdata.h:264
@ SPECIAL_MANEUVER_AFTERBURNER
Definition wcdata.h:260
@ SPECIAL_MANEUVER_NONE
Definition wcdata.h:258
@ MANEUVER_OUTA_HERE
Definition wcdata.h:229
@ MANEUVER_NONE
Definition wcdata.h:207
ObjectClass
Definition wcdata.h:37
@ OBJECT_CLASS_FIXED_OBJECT
Definition wcdata.h:45
@ OBJECT_CLASS_MISSILE
Definition wcdata.h:49
@ OBJECT_CLASS_SHIP
Definition wcdata.h:50
@ OBJECT_CLASS_DUST
Definition wcdata.h:42
@ OBJECT_CLASS_CAPITAL_SHIP
Definition wcdata.h:51
@ OBJECT_CLASS_ASTEROID
Definition wcdata.h:47
@ OBJECT_CLASS_PROJECTILE
Definition wcdata.h:46
@ OBJECT_CLASS_MINE
Definition wcdata.h:48
@ TACTIC_SIT_STILL
Definition wcdata.h:153