diff --git a/asm/MetroidPrime/Player/CGrappleArm.s b/asm/MetroidPrime/Player/CGrappleArm.s index 9622feb8..875ae27a 100644 --- a/asm/MetroidPrime/Player/CGrappleArm.s +++ b/asm/MetroidPrime/Player/CGrappleArm.s @@ -864,8 +864,8 @@ lbl_8011DE18: /* 8011DE28 0011AD88 38 21 00 10 */ addi r1, r1, 0x10 /* 8011DE2C 0011AD8C 4E 80 00 20 */ blr -.global EnterStruck__11CGrappleArmFR13CStateManagerf -EnterStruck__11CGrappleArmFR13CStateManagerf: +.global EnterStruck__11CGrappleArmFR13CStateManagerfbb +EnterStruck__11CGrappleArmFR13CStateManagerfbb: /* 8011DE30 0011AD90 94 21 FF E0 */ stwu r1, -0x20(r1) /* 8011DE34 0011AD94 7C 08 02 A6 */ mflr r0 /* 8011DE38 0011AD98 90 01 00 24 */ stw r0, 0x24(r1) @@ -907,7 +907,7 @@ lbl_8011DEB8: /* 8011DEC0 0011AE20 7F A4 EB 78 */ mr r4, r29 /* 8011DEC4 0011AE24 7F C5 F3 78 */ mr r5, r30 /* 8011DEC8 0011AE28 7F E6 FB 78 */ mr r6, r31 -/* 8011DECC 0011AE2C 48 0A E9 81 */ bl EnterStruck__14CGunControllerFR13CStateManagerf +/* 8011DECC 0011AE2C 48 0A E9 81 */ bl EnterStruck__14CGunControllerFR13CStateManagerfbb lbl_8011DED0: /* 8011DED0 0011AE30 80 01 00 24 */ lwz r0, 0x24(r1) /* 8011DED4 0011AE34 CB E1 00 18 */ lfd f31, 0x18(r1) diff --git a/asm/MetroidPrime/Player/CPlayerGun.s b/asm/MetroidPrime/Player/CPlayerGun.s index be3491f0..b90df5bf 100644 --- a/asm/MetroidPrime/Player/CPlayerGun.s +++ b/asm/MetroidPrime/Player/CPlayerGun.s @@ -3127,7 +3127,7 @@ lbl_8003CD38: /* 8003CD4C 00039CAC 7F A5 EB 78 */ mr r5, r29 /* 8003CD50 00039CB0 7C 00 00 34 */ cntlzw r0, r0 /* 8003CD54 00039CB4 54 06 D9 7E */ srwi r6, r0, 5 -/* 8003CD58 00039CB8 48 0E 10 D9 */ bl EnterStruck__11CGrappleArmFR13CStateManagerf +/* 8003CD58 00039CB8 48 0E 10 D9 */ bl EnterStruck__11CGrappleArmFR13CStateManagerfbb lbl_8003CD5C: /* 8003CD5C 00039CBC C0 02 84 6C */ lfs f0, lbl_805AA18C@sda21(r2) /* 8003CD60 00039CC0 3C 60 80 5A */ lis r3, sZeroVector__9CVector3f@ha diff --git a/asm/MetroidPrime/Weapons/GunController/CGunController.s b/asm/MetroidPrime/Weapons/GunController/CGunController.s index c49f4dd8..568b3808 100644 --- a/asm/MetroidPrime/Weapons/GunController/CGunController.s +++ b/asm/MetroidPrime/Weapons/GunController/CGunController.s @@ -521,8 +521,8 @@ LoadFidgetAnimAsync__14CGunControllerFR13CStateManageriii: /* 801CC844 001C97A4 38 21 00 10 */ addi r1, r1, 0x10 /* 801CC848 001C97A8 4E 80 00 20 */ blr -.global EnterStruck__14CGunControllerFR13CStateManagerf -EnterStruck__14CGunControllerFR13CStateManagerf: +.global EnterStruck__14CGunControllerFR13CStateManagerfbb +EnterStruck__14CGunControllerFR13CStateManagerfbb: /* 801CC84C 001C97AC 94 21 FE C0 */ stwu r1, -0x140(r1) /* 801CC850 001C97B0 7C 08 02 A6 */ mflr r0 /* 801CC854 001C97B4 90 01 01 44 */ stw r0, 0x144(r1) diff --git a/include/Kyoto/Math/CRelAngle.hpp b/include/Kyoto/Math/CRelAngle.hpp index 247a716a..9006a6c9 100644 --- a/include/Kyoto/Math/CRelAngle.hpp +++ b/include/Kyoto/Math/CRelAngle.hpp @@ -33,6 +33,17 @@ public: static CRelAngle FromDegrees(float deg) { return CRelAngle(deg * (M_PIF / 180.f)); } static CRelAngle FromRadians(float rad) { return CRelAngle(rad); } + // Relative + + static float MakeRelativeAngle(float angle) { + float ret = angle - ((float)(int)(angle * (1.f / (2.f * M_PIF)))) * (2.f * M_PIF); + if (ret < 0.f) + ret += 2.f * M_PIF; + return ret; + } + + CRelAngle AsRelative() const { return CRelAngle(MakeRelativeAngle(x0_angle)); } + private: CRelAngle(float rad) : x0_angle(rad) {} diff --git a/include/MetroidPrime/Player/CGrappleArm.hpp b/include/MetroidPrime/Player/CGrappleArm.hpp index ce76015c..37145684 100644 --- a/include/MetroidPrime/Player/CGrappleArm.hpp +++ b/include/MetroidPrime/Player/CGrappleArm.hpp @@ -2,16 +2,37 @@ #define _CGRAPPLEARM #include "types.h" +#include "rstl/single_ptr.hpp" +#include "Kyoto/Audio/CSfxHandle.hpp" class CVector3f; +class CStateManager; +class CFrustumPlanes; +class CGunController; class CGrappleArm { public: + enum EArmState { + kAS_IntoGrapple, + kAS_IntoGrappleIdle, + kAS_FireGrapple, + kAS_Three, + kAS_ConnectGrapple, + kAS_Five, + kAS_Connected, + kAS_Seven, + kAS_OutOfGrapple, + kAS_GunControllerAnimation, + kAS_Done + }; + CGrappleArm(const CVector3f& scale); ~CGrappleArm(); void PreRender(CStateManager& mgr, const CFrustumPlanes& frustum, const CVector3f& camPos); void ReturnToDefault(CStateManager& mgr, float dt, bool setState); + void EnterStruck(CStateManager&, float, bool, bool); + void DisconnectGrappleBeam(); // EArmState GetAnimState() const { return x334_animState; } bool GetActive() const { return x3b2_24_active; } @@ -21,7 +42,12 @@ public: bool IsSuitLoading() const { return x3b2_29_suitLoading; } private: - uchar x0_pad[0x3b0]; + uchar x0_pad[0x328]; + rstl::single_ptr x328_gunController; + CSfxHandle x32c_grappleLoopSfx; + CSfxHandle x330_swooshSfx; + EArmState x334_animState; + uchar x338_pad[0x78]; short x3b0_rumbleHandle; bool x3b2_24_active : 1; bool x3b2_25_beamActive : 1; diff --git a/include/MetroidPrime/Weapons/GunController/CGunController.hpp b/include/MetroidPrime/Weapons/GunController/CGunController.hpp index ac021ee7..960a75cf 100644 --- a/include/MetroidPrime/Weapons/GunController/CGunController.hpp +++ b/include/MetroidPrime/Weapons/GunController/CGunController.hpp @@ -38,7 +38,7 @@ public: void EnterFreeLook(CStateManager&, int, int); void EnterComboFire(CStateManager&, int); void EnterFidget(CStateManager&, int, int, int); - void EnterStruck(CStateManager&, float); + void EnterStruck(CStateManager&, float, bool, bool); void LoadFidgetAnimAsync(CStateManager&, int, int, int); int Update(float, CStateManager&); void EnterIdle(CStateManager&); diff --git a/libc/math.h b/libc/math.h index 39468087..885a0815 100644 --- a/libc/math.h +++ b/libc/math.h @@ -71,6 +71,7 @@ double fmod(double x, double m); double sin(double x); double cos(double x); double atan(double x); +double atan2(double y, double x); _MATH_INLINE float sinf(float x) { return (float)sin((double)x); } _MATH_INLINE float cosf(float x) { return (float)cos((double)x); } diff --git a/src/MetroidPrime/Player/CGrappleArm.cpp b/src/MetroidPrime/Player/CGrappleArm.cpp new file mode 100644 index 00000000..6391e1ea --- /dev/null +++ b/src/MetroidPrime/Player/CGrappleArm.cpp @@ -0,0 +1,21 @@ +#include "MetroidPrime/Player/CGrappleArm.hpp" + +#include "MetroidPrime/Weapons/GunController/CGunController.hpp" + +void CGrappleArm::EnterStruck(CStateManager& mgr, float angle, bool bigStrike, bool notInFreeLook) { + if (x3b2_29_suitLoading) + return; + + if (x3b2_28_isGrappling) { + DisconnectGrappleBeam(); + x3b2_28_isGrappling = false; + } + + if (!x3b2_27_armMoving) { + x3b2_24_active = true; + x3b2_27_armMoving = true; + x334_animState = kAS_GunControllerAnimation; + } + + x328_gunController->EnterStruck(mgr, angle, bigStrike, notInFreeLook); +} diff --git a/src/MetroidPrime/Player/CPlayerGun.cpp b/src/MetroidPrime/Player/CPlayerGun.cpp index bc99ac17..e92c3e3d 100644 --- a/src/MetroidPrime/Player/CPlayerGun.cpp +++ b/src/MetroidPrime/Player/CPlayerGun.cpp @@ -993,7 +993,32 @@ void CPlayerGun::CMotionState::Update(bool firing, float dt, CTransform4f& xf, C void CPlayerGun::DamageRumble(const CVector3f&, const CStateManager&) {} -void CPlayerGun::TakeDamage(bool, bool, CStateManager&) {} +void CPlayerGun::TakeDamage(bool bigStrike, bool notFromMetroid, CStateManager& mgr) { + const CPlayer& player = *mgr.GetPlayer(); + bool hasStrikeAngle = false; + float angle = 0.f; + if (x398_damageAmt >= 10.f && !bigStrike && (x2f8_stateFlags & 0x10) != 0x10 && !x832_26_comboFiring && + x384_gunStrikeDelayTimer <= 0.f) { + x384_gunStrikeDelayTimer = 20.f; + x364_gunStrikeCoolTimer = 0.75f; + if (x678_morph.GetGunState() == CGunMorph::kGS_OutWipeDone) { + CVector3f localDamageLoc = player.GetTransform().TransposeRotate(x3dc_damageLocation); + angle = CRelAngle::FromRadians(atan2(localDamageLoc.GetY(), localDamageLoc.GetX())).AsRelative().AsDegrees(); + hasStrikeAngle = true; + } + } + + if (hasStrikeAngle || bigStrike) { + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::kPV_Scan) { + x73c_gunMotion->PlayPasAnim(SamusGun::kAS_Struck, mgr, angle, bigStrike); + if ((bigStrike && notFromMetroid) || x833_31_inFreeLook) + x740_grappleArm->EnterStruck(mgr, angle, bigStrike, !x833_31_inFreeLook); + } + } + + x398_damageAmt = 0.f; + x3dc_damageLocation = CVector3f::Zero(); +} void CPlayerGun::StopChargeSound(CStateManager&) {} diff --git a/src/MetroidPrime/Weapons/GunController/CGunController.cpp b/src/MetroidPrime/Weapons/GunController/CGunController.cpp index 44044f85..aed50bd3 100644 --- a/src/MetroidPrime/Weapons/GunController/CGunController.cpp +++ b/src/MetroidPrime/Weapons/GunController/CGunController.cpp @@ -13,7 +13,7 @@ void CGunController::EnterComboFire(CStateManager&, int) {} void CGunController::EnterFidget(CStateManager&, int, int, int) {} -void CGunController::EnterStruck(CStateManager&, float) {} +void CGunController::EnterStruck(CStateManager&, float, bool, bool) {} void CGunController::LoadFidgetAnimAsync(CStateManager&, int, int, int) {}