diff --git a/asm/MetroidPrime/ScriptLoader.s b/asm/MetroidPrime/ScriptLoader.s index 7e125f4c..72505366 100644 --- a/asm/MetroidPrime/ScriptLoader.s +++ b/asm/MetroidPrime/ScriptLoader.s @@ -11344,7 +11344,7 @@ lbl_800CF530: /* 800CF608 000CC568 38 81 00 0C */ addi r4, r1, 0xc /* 800CF60C 000CC56C 38 A1 00 10 */ addi r5, r1, 0x10 /* 800CF610 000CC570 38 E1 00 20 */ addi r7, r1, 0x20 -/* 800CF614 000CC574 48 0B FB 99 */ bl "__ct__14CScriptEMPulseF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfoRC12CTransform4fbfffffUi" +/* 800CF614 000CC574 48 0B FB 99 */ bl "__ct__14CScriptEMPulseF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfoRC12CTransform4fbfffffffUi" /* 800CF618 000CC578 7C 7D 1B 78 */ mr r29, r3 lbl_800CF61C: /* 800CF61C 000CC57C 38 61 00 10 */ addi r3, r1, 0x10 diff --git a/asm/MetroidPrime/ScriptObjects/CScriptEMPulse.s b/asm/MetroidPrime/ScriptObjects/CScriptEMPulse.s index 32c00716..cc0c916d 100644 --- a/asm/MetroidPrime/ScriptObjects/CScriptEMPulse.s +++ b/asm/MetroidPrime/ScriptObjects/CScriptEMPulse.s @@ -3,8 +3,8 @@ .section .data .balign 8 -.global lbl_803E4400 -lbl_803E4400: +.global __vt__14CScriptEMPulse +__vt__14CScriptEMPulse: # ROM: 0x3E1400 .4byte 0 .4byte 0 @@ -56,9 +56,9 @@ __dt__14CScriptEMPulseFv: /* 8018EBC8 0018BB28 93 C1 00 08 */ stw r30, 8(r1) /* 8018EBCC 0018BB2C 7C 7E 1B 79 */ or. r30, r3, r3 /* 8018EBD0 0018BB30 41 82 00 70 */ beq lbl_8018EC40 -/* 8018EBD4 0018BB34 3C 60 80 3E */ lis r3, lbl_803E4400@ha +/* 8018EBD4 0018BB34 3C 60 80 3E */ lis r3, __vt__14CScriptEMPulse@ha /* 8018EBD8 0018BB38 34 1E 01 14 */ addic. r0, r30, 0x114 -/* 8018EBDC 0018BB3C 38 03 44 00 */ addi r0, r3, lbl_803E4400@l +/* 8018EBDC 0018BB3C 38 03 44 00 */ addi r0, r3, __vt__14CScriptEMPulse@l /* 8018EBE0 0018BB40 90 1E 00 00 */ stw r0, 0(r30) /* 8018EBE4 0018BB44 41 82 00 24 */ beq lbl_8018EC08 /* 8018EBE8 0018BB48 80 7E 01 14 */ lwz r3, 0x114(r30) @@ -469,8 +469,8 @@ lbl_8018F18C: /* 8018F1A4 0018C104 38 21 00 70 */ addi r1, r1, 0x70 /* 8018F1A8 0018C108 4E 80 00 20 */ blr -.global "__ct__14CScriptEMPulseF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfoRC12CTransform4fbfffffUi" -"__ct__14CScriptEMPulseF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfoRC12CTransform4fbfffffUi": +.global "__ct__14CScriptEMPulseF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfoRC12CTransform4fbfffffffUi" +"__ct__14CScriptEMPulseF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfoRC12CTransform4fbfffffffUi": /* 8018F1AC 0018C10C 94 21 FE 50 */ stwu r1, -0x1b0(r1) /* 8018F1B0 0018C110 7C 08 02 A6 */ mflr r0 /* 8018F1B4 0018C114 90 01 01 B4 */ stw r0, 0x1b4(r1) @@ -538,9 +538,9 @@ lbl_8018F18C: /* 8018F2AC 0018C20C 38 61 01 00 */ addi r3, r1, 0x100 /* 8018F2B0 0018C210 38 80 FF FF */ li r4, -1 /* 8018F2B4 0018C214 4B F8 77 99 */ bl __dt__10CModelDataFv -/* 8018F2B8 0018C218 3C 60 80 3E */ lis r3, lbl_803E4400@ha +/* 8018F2B8 0018C218 3C 60 80 3E */ lis r3, __vt__14CScriptEMPulse@ha /* 8018F2BC 0018C21C 3C 80 50 41 */ lis r4, 0x50415254@ha -/* 8018F2C0 0018C220 38 03 44 00 */ addi r0, r3, lbl_803E4400@l +/* 8018F2C0 0018C220 38 03 44 00 */ addi r0, r3, __vt__14CScriptEMPulse@l /* 8018F2C4 0018C224 38 61 00 18 */ addi r3, r1, 0x18 /* 8018F2C8 0018C228 90 1F 00 00 */ stw r0, 0(r31) /* 8018F2CC 0018C22C 38 04 52 54 */ addi r0, r4, 0x50415254@l diff --git a/configure.py b/configure.py index e6b902c8..a3a0773c 100755 --- a/configure.py +++ b/configure.py @@ -249,7 +249,7 @@ LIBS = [ "MetroidPrime/Weapons/CPhazonBeam", ["MetroidPrime/ScriptObjects/CScriptTargetingPoint", True], "MetroidPrime/BodyState/CBSWallHang", - "MetroidPrime/ScriptObjects/CScriptEMPulse", + ["MetroidPrime/ScriptObjects/CScriptEMPulse", False], "MetroidPrime/HUD/CHudDecoInterface", "MetroidPrime/Weapons/CFlameThrower", "MetroidPrime/Weapons/CBeamProjectile", diff --git a/include/MetroidPrime/Player/CPlayer.hpp b/include/MetroidPrime/Player/CPlayer.hpp index ec3f213b..0966a3df 100644 --- a/include/MetroidPrime/Player/CPlayer.hpp +++ b/include/MetroidPrime/Player/CPlayer.hpp @@ -28,6 +28,22 @@ enum EPlayerMovementState { }; }; +enum EPlayerOrbitRequest { + kOR_StopOrbit, + kOR_Respawn, + kOR_EnterMorphBall, + kOR_Default, + kOR_Four, + kOR_Five, + kOR_InvalidateTarget, + kOR_BadVerticalAngle, + kOR_ActivateOrbitSource, + kOR_ProjectileCollide, + kOR_Freeze, + kOR_DamageOnGrapple, + kOR_LostGrappleLineOfSight, +}; + class CPlayer : public CPhysicsActor { struct CVisorSteam { float x0_curTargetAlpha; @@ -93,21 +109,6 @@ public: kOT_Far, kOT_Default, }; - enum EPlayerOrbitRequest { - kOR_StopOrbit, - kOR_Respawn, - kOR_EnterMorphBall, - kOR_Default, - kOR_Four, - kOR_Five, - kOR_InvalidateTarget, - kOR_BadVerticalAngle, - kOR_ActivateOrbitSource, - kOR_ProjectileCollide, - kOR_Freeze, - kOR_DamageOnGrapple, - kOR_LostGrappleLineOfSight, - }; enum EPlayerZoneInfo { kZI_Targeting, kZI_Scan, @@ -175,7 +176,7 @@ public: // CPlayer virtual bool IsTransparent(); - + CVector3f GetBallPosition() const; CVector3f GetEyePosition() const; float GetEyeHeight() const; @@ -193,6 +194,7 @@ public: void DecrementPhazon(); // GetMovementDirection2D__7CPlayerCFv ?? void SetOrbitTargetId(TUniqueId id, CStateManager& mgr); + void SetOrbitRequestForTarget(TUniqueId id, EPlayerOrbitRequest req, CStateManager& mgr); void AddOrbitDisableSource(CStateManager& mgr, TUniqueId addId); void RemoveOrbitDisableSource(TUniqueId uid); void ResetAimTargetPrediction(TUniqueId target); @@ -205,6 +207,8 @@ public: CMorphBall* MorphBall() { return x768_morphball.get(); } const CMorphBall* GetMorphBall() const { return x768_morphball.get(); } + float GetStaticTimer() const { return x740_staticTimer; } + ESurfaceRestraints GetCurrentSurfaceRestraint() const { return x2ac_surfaceRestraint; } ESurfaceRestraints GetSurfaceRestraint() const { return x2b0_outOfWaterTicks == 2 ? GetCurrentSurfaceRestraint() : kSR_Water; diff --git a/include/MetroidPrime/ScriptObjects/CScriptEMPulse.hpp b/include/MetroidPrime/ScriptObjects/CScriptEMPulse.hpp new file mode 100644 index 00000000..1cf17733 --- /dev/null +++ b/include/MetroidPrime/ScriptObjects/CScriptEMPulse.hpp @@ -0,0 +1,37 @@ +#ifndef _CSCRIPTEMPULSE +#define _CSCRIPTEMPULSE + +#include "MetroidPrime/CActor.hpp" + +class CGenDescription; +class CElementGen; + +class CScriptEMPulse : public CActor { +public: + CScriptEMPulse(TUniqueId, const rstl::string&, const CEntityInfo&, const CTransform4f&, bool, + float, float, float, float, float, float, float, CAssetId); + + void Accept(IVisitor&) override; + void Think(float, CStateManager&) override; + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&) override; + void AddToRenderer(const CFrustumPlanes&, const CStateManager&) const override; + void CalculateRenderBounds() override; + rstl::optional_object< CAABox > GetTouchBounds() const override; + void Touch(CActor&, CStateManager&) override; + +private: + float xe8_duration; + float xec_finalRadius; + float xf0_currentRadius; + float xf4_initialRadius; + float xf8_interferenceDur; + float xfc_; + float x100_interferenceMag; + float x104_; + TLockedToken< CGenDescription > x108_particleDesc; + rstl::single_ptr< CElementGen > x114_particleGen; + + CAABox CalculateBoundingBox() const; +}; + +#endif // _CSCRIPTEMPULSE diff --git a/src/MetroidPrime/ScriptObjects/CScriptEMPulse.cpp b/src/MetroidPrime/ScriptObjects/CScriptEMPulse.cpp new file mode 100644 index 00000000..feaba972 --- /dev/null +++ b/src/MetroidPrime/ScriptObjects/CScriptEMPulse.cpp @@ -0,0 +1,108 @@ +#include "MetroidPrime/ScriptObjects/CScriptEMPulse.hpp" + +#include "MetroidPrime/CActorParameters.hpp" +#include "MetroidPrime/CStateManager.hpp" +#include "MetroidPrime/Player/CPlayer.hpp" +#include "MetroidPrime/Player/CPlayerState.hpp" + +#include "MetaRender/CCubeRenderer.hpp" + +#include "Kyoto/Particles/CElementGen.hpp" +#include "Kyoto/Particles/CGenDescription.hpp" + +CScriptEMPulse::CScriptEMPulse(TUniqueId uid, const rstl::string& name, const CEntityInfo& info, + const CTransform4f& xf, bool active, float initialRadius, + float finalRadius, float duration, float interferenceDur, float f5, + float interferenceMag, float f7, CAssetId partId) +: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(kMT_Projectile), + CActorParameters::None().HotInThermal(true), kInvalidUniqueId) +, xe8_duration(duration) +, xec_finalRadius(finalRadius) +, xf0_currentRadius(initialRadius) +, xf4_initialRadius(initialRadius) +, xf8_interferenceDur(interferenceDur) +, xfc_(f5) +, x100_interferenceMag(interferenceMag) +, x104_(f7) +, x108_particleDesc(gpSimplePool->GetObj(SObjectTag('PART', partId))) {} + +void CScriptEMPulse::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, uid, mgr); + + switch (msg) { + case kSM_Activate: + + x114_particleGen = + new CElementGen(x108_particleDesc, CElementGen::kMOT_Normal, CElementGen::kOSF_One); + + x114_particleGen->SetOrientation(GetTransform().GetRotation()); + x114_particleGen->SetGlobalTranslation(GetTranslation()); + x114_particleGen->SetParticleEmission(true); + mgr.PlayerState()->StaticInterference().AddSource(GetUniqueId(), x100_interferenceMag, + xf8_interferenceDur); + break; + default: + break; + } +} + +void CScriptEMPulse::Accept(IVisitor& visitor) { visitor.Visit(*this); } + +void CScriptEMPulse::Think(float dt, CStateManager& mgr) { + if (!GetActive()) { + return; + } + xf0_currentRadius += ((xec_finalRadius - xf4_initialRadius) / xe8_duration) * dt; + + if (xf0_currentRadius <= xec_finalRadius) { + mgr.FreeScriptObject(GetUniqueId()); + } + + x114_particleGen->Update(dt); +} + +CAABox CScriptEMPulse::CalculateBoundingBox() const { + float radius = xf0_currentRadius; + CVector3f position(GetTranslation()); + return CAABox( + CVector3f(position.GetX() - radius, position.GetY() - radius, position.GetZ() - radius), + CVector3f(position.GetX() + radius, position.GetY() + radius, position.GetZ() + radius)); +} + +rstl::optional_object< CAABox > CScriptEMPulse::GetTouchBounds() const { + return CalculateBoundingBox(); +} + +void CScriptEMPulse::CalculateRenderBounds() { SetRenderBounds(CalculateBoundingBox()); } + +void CScriptEMPulse::Touch(CActor& act, CStateManager& mgr) { + if (!GetActive()) { + return; + } + + if (CPlayer* pl = TCastToPtr< CPlayer >(act)) { + // CVector3f thisPos(GetTranslation()); + // CVector3f posDiff(thisPos - pl->GetTranslation()); + // float diffMagnitude = posDiff.Magnitude(); + float diffMagnitude = (GetTranslation() - pl->GetTranslation()).Magnitude(); + if (diffMagnitude < xec_finalRadius) { + const float diffMagOp = 1.f - (diffMagnitude / xec_finalRadius); + const float dur = (diffMagOp * (xfc_ - xf8_interferenceDur)) + xf8_interferenceDur; + const float mag = (diffMagOp * (x104_ - x100_interferenceMag)) + x100_interferenceMag; + + if (dur > pl->GetStaticTimer()) { + pl->SetHudDisable(dur); + pl->SetOrbitRequestForTarget(mgr.GetPlayer()->GetOrbitTargetId(), kOR_ActivateOrbitSource, + mgr); + } + mgr.PlayerState()->StaticInterference().AddSource(GetUniqueId(), mag, dur); + } + } +} + +void CScriptEMPulse::AddToRenderer(const CFrustumPlanes& frustum, const CStateManager& mgr) const { + CActor::AddToRenderer(frustum, mgr); + if (GetActive()) { + gpRender->AddParticleGen(*x114_particleGen); + } +}