Add CWaveBeam

This commit is contained in:
Henrique Gemignani Passos Lima 2022-12-08 00:48:51 +02:00
parent 2cbd08bb66
commit c1d11e5701
No known key found for this signature in database
GPG Key ID: E224F951761145F8
8 changed files with 277 additions and 28 deletions

View File

@ -2230,7 +2230,7 @@ lbl_801BBB34:
/* 801BBB40 001B8AA0 57 25 10 3A */ slwi r5, r25, 2
/* 801BBB44 001B8AA4 88 03 02 20 */ lbz r0, 0x220(r3)
/* 801BBB48 001B8AA8 51 20 36 72 */ rlwimi r0, r9, 6, 0x19, 0x19
/* 801BBB4C 001B8AAC 38 82 A9 D0 */ addi r4, r2, lbl_805AC6F0@sda21
/* 801BBB4C 001B8AAC 38 82 A9 D0 */ addi r4, r2, skShootAnim__10CGunWeapon@sda21
/* 801BBB50 001B8AB0 C0 02 A9 D8 */ lfs f0, lbl_805AC6F8@sda21(r2)
/* 801BBB54 001B8AB4 98 03 02 20 */ stb r0, 0x220(r3)
/* 801BBB58 001B8AB8 38 00 FF FF */ li r0, -1
@ -4017,8 +4017,8 @@ lbl_805AC6EC:
# ROM: 0x3F8F8C
.4byte lbl_803D19D7
.global lbl_805AC6F0
lbl_805AC6F0:
.global skShootAnim__10CGunWeapon
skShootAnim__10CGunWeapon:
# ROM: 0x3F8F90
.4byte 0x00000004
.4byte 0x00000003

View File

@ -7,8 +7,8 @@ lbl_ctor:
.section .data
.balign 8
.global lbl_803DF7A0
lbl_803DF7A0:
.global __vt__9CWaveBeam
__vt__9CWaveBeam:
# ROM: 0x3DC7A0
.4byte 0
.4byte 0
@ -18,13 +18,13 @@ lbl_803DF7A0:
.4byte PreRenderGunFx__10CGunWeaponFRC13CStateManagerRC12CTransform4f
.4byte PostRenderGunFx__9CWaveBeamFRC13CStateManagerRC12CTransform4f
.4byte UpdateGunFx__9CWaveBeamFbfRC13CStateManagerRC12CTransform4f
.4byte Fire__9CWaveBeamFbfQ212CPlayerState12EChargeStageRC12CTransform4fR13CStateManager9TUniqueId
.4byte Fire__9CWaveBeamFbfQ212CPlayerState12EChargeStageRC12CTransform4fR13CStateManager9TUniqueIdff
.4byte EnableFx__10CGunWeaponFb
.4byte EnableSecondaryFx__9CWaveBeamFQ210CGunWeapon16ESecondaryFxType
.4byte Draw__10CGunWeaponCFbRC13CStateManagerRC12CTransform4fRC11CModelFlagsPC12CActorLights
.4byte DrawMuzzleFx__10CGunWeaponCFRC13CStateManager
.4byte Update__9CWaveBeamFfR13CStateManager
.4byte Load__9CWaveBeamFb
.4byte Load__9CWaveBeamFR13CStateManagerb
.4byte Unload__9CWaveBeamFR13CStateManager
.4byte IsLoaded__9CWaveBeamCFv
.4byte 0
@ -33,8 +33,8 @@ lbl_803DF7A0:
.balign 8
# CWaveBeam
.global lbl_805A8EB8
lbl_805A8EB8:
.global skShotAnglePitch
skShotAnglePitch:
.skip 0x8
.section .sdata2, "a"
@ -75,8 +75,8 @@ lbl_805AACB0:
# ROM: 0x3F7550
.double 4.503601774854144E15
.global lbl_805AACB8
lbl_805AACB8:
.global skShotAnglePitchSource
skShotAnglePitchSource:
# ROM: 0x3F7558
.4byte 0x42F00000
.4byte 0
@ -318,8 +318,8 @@ Unload__9CWaveBeamFR13CStateManager:
/* 800E03E0 000DD340 38 21 00 10 */ addi r1, r1, 0x10
/* 800E03E4 000DD344 4E 80 00 20 */ blr
.global Load__9CWaveBeamFb
Load__9CWaveBeamFb:
.global Load__9CWaveBeamFR13CStateManagerb
Load__9CWaveBeamFR13CStateManagerb:
/* 800E03E8 000DD348 94 21 FF F0 */ stwu r1, -0x10(r1)
/* 800E03EC 000DD34C 7C 08 02 A6 */ mflr r0
/* 800E03F0 000DD350 90 01 00 14 */ stw r0, 0x14(r1)
@ -340,8 +340,8 @@ Load__9CWaveBeamFb:
/* 800E042C 000DD38C 38 21 00 10 */ addi r1, r1, 0x10
/* 800E0430 000DD390 4E 80 00 20 */ blr
.global Fire__9CWaveBeamFbfQ212CPlayerState12EChargeStageRC12CTransform4fR13CStateManager9TUniqueId
Fire__9CWaveBeamFbfQ212CPlayerState12EChargeStageRC12CTransform4fR13CStateManager9TUniqueId:
.global Fire__9CWaveBeamFbfQ212CPlayerState12EChargeStageRC12CTransform4fR13CStateManager9TUniqueIdff
Fire__9CWaveBeamFbfQ212CPlayerState12EChargeStageRC12CTransform4fR13CStateManager9TUniqueIdff:
/* 800E0434 000DD394 94 21 FE 10 */ stwu r1, -0x1f0(r1)
/* 800E0438 000DD398 7C 08 02 A6 */ mflr r0
/* 800E043C 000DD39C 90 01 01 F4 */ stw r0, 0x1f4(r1)
@ -380,7 +380,7 @@ lbl_800E04AC:
/* 800E04BC 000DD41C 3C 60 80 3D */ lis r3, lbl_803CE568@ha
/* 800E04C0 000DD420 C3 A2 8F 88 */ lfs f29, lbl_805AACA8@sda21(r2)
/* 800E04C4 000DD424 EF 80 00 72 */ fmuls f28, f0, f1
/* 800E04C8 000DD428 C3 CD A2 F8 */ lfs f30, lbl_805A8EB8@sda21(r13)
/* 800E04C8 000DD428 C3 CD A2 F8 */ lfs f30, skShotAnglePitch@sda21(r13)
/* 800E04CC 000DD42C 7F 53 02 14 */ add r26, r19, r0
/* 800E04D0 000DD430 CB E2 8F 90 */ lfd f31, lbl_805AACB0@sda21(r2)
/* 800E04D4 000DD434 3B E3 E5 68 */ addi r31, r3, lbl_803CE568@l
@ -519,7 +519,7 @@ lbl_800E06A4:
/* 800E06D0 000DD630 56 A5 10 3A */ slwi r5, r21, 2
/* 800E06D4 000DD634 88 03 02 20 */ lbz r0, 0x220(r3)
/* 800E06D8 000DD638 51 20 36 72 */ rlwimi r0, r9, 6, 0x19, 0x19
/* 800E06DC 000DD63C 38 82 A9 D0 */ addi r4, r2, lbl_805AC6F0@sda21
/* 800E06DC 000DD63C 38 82 A9 D0 */ addi r4, r2, skShootAnim__10CGunWeapon@sda21
/* 800E06E0 000DD640 C0 02 8F 8C */ lfs f0, lbl_805AACAC@sda21(r2)
/* 800E06E4 000DD644 98 03 02 20 */ stb r0, 0x220(r3)
/* 800E06E8 000DD648 38 00 FF FF */ li r0, -1
@ -897,9 +897,9 @@ __dt__9CWaveBeamFv:
/* 800E0C28 000DDB88 93 C1 00 08 */ stw r30, 8(r1)
/* 800E0C2C 000DDB8C 7C 7E 1B 79 */ or. r30, r3, r3
/* 800E0C30 000DDB90 41 82 00 EC */ beq lbl_800E0D1C
/* 800E0C34 000DDB94 3C 60 80 3E */ lis r3, lbl_803DF7A0@ha
/* 800E0C34 000DDB94 3C 60 80 3E */ lis r3, __vt__9CWaveBeam@ha
/* 800E0C38 000DDB98 34 1E 02 54 */ addic. r0, r30, 0x254
/* 800E0C3C 000DDB9C 38 03 F7 A0 */ addi r0, r3, lbl_803DF7A0@l
/* 800E0C3C 000DDB9C 38 03 F7 A0 */ addi r0, r3, __vt__9CWaveBeam@l
/* 800E0C40 000DDBA0 90 1E 00 00 */ stw r0, 0(r30)
/* 800E0C44 000DDBA4 41 82 00 24 */ beq lbl_800E0C68
/* 800E0C48 000DDBA8 80 7E 02 54 */ lwz r3, 0x254(r30)
@ -982,9 +982,9 @@ __ct__9CWaveBeamFUi11EWeaponType9TUniqueId14EMaterialTypesRC9CVector3f:
/* 800E0D54 000DDCB4 38 C1 00 08 */ addi r6, r1, 8
/* 800E0D58 000DDCB8 B0 01 00 08 */ sth r0, 8(r1)
/* 800E0D5C 000DDCBC 48 0D C4 55 */ bl __ct__10CGunWeaponFUi11EWeaponType9TUniqueId14EMaterialTypesRC9CVector3f
/* 800E0D60 000DDCC0 3C 60 80 3E */ lis r3, lbl_803DF7A0@ha
/* 800E0D60 000DDCC0 3C 60 80 3E */ lis r3, __vt__9CWaveBeam@ha
/* 800E0D64 000DDCC4 3C 80 80 3D */ lis r4, lbl_803CE568@ha
/* 800E0D68 000DDCC8 38 03 F7 A0 */ addi r0, r3, lbl_803DF7A0@l
/* 800E0D68 000DDCC8 38 03 F7 A0 */ addi r0, r3, __vt__9CWaveBeam@l
/* 800E0D6C 000DDCCC 38 61 00 24 */ addi r3, r1, 0x24
/* 800E0D70 000DDCD0 90 1F 00 00 */ stw r0, 0(r31)
/* 800E0D74 000DDCD4 38 84 E5 68 */ addi r4, r4, lbl_803CE568@l
@ -1078,8 +1078,8 @@ __ct__9CWaveBeamFUi11EWeaponType9TUniqueId14EMaterialTypesRC9CVector3f:
.global __sinit_CWaveBeam_cpp
__sinit_CWaveBeam_cpp:
/* 800E0ED4 000DDE34 C0 02 8F 98 */ lfs f0, lbl_805AACB8@sda21(r2)
/* 800E0ED8 000DDE38 D0 0D A2 F8 */ stfs f0, lbl_805A8EB8@sda21(r13)
/* 800E0ED4 000DDE34 C0 02 8F 98 */ lfs f0, skShotAnglePitchSource@sda21(r2)
/* 800E0ED8 000DDE38 D0 0D A2 F8 */ stfs f0, skShotAnglePitch@sda21(r13)
/* 800E0EDC 000DDE3C 4E 80 00 20 */ blr
.section .rodata

View File

@ -109,7 +109,7 @@ LIBS = [
"MetroidPrime/Factories/CStateMachineFactory",
["MetroidPrime/Weapons/CPlasmaBeam", False],
["MetroidPrime/Weapons/CPowerBeam", False],
"MetroidPrime/Weapons/CWaveBeam",
["MetroidPrime/Weapons/CWaveBeam", False],
["MetroidPrime/Weapons/CIceBeam", False],
["MetroidPrime/CScriptMailbox", False],
["MetroidPrime/ScriptObjects/CScriptRelay", True],

View File

@ -0,0 +1,40 @@
#ifndef _CELECTRICDESCRIPTION
#define _CELECTRICDESCRIPTION
#include "Kyoto/Particles/CParticleDataFactory.hpp"
class CColorElement;
class CEmitterElement;
class CIntElement;
class CRealElement;
// using SParticleModel = STokenDesc<CModel>;
// using SChildGeneratorDesc = STokenDesc<CGenDescription>;
// using SSwooshGeneratorDesc = STokenDesc<CSwooshDescription>;
// using SElectricGeneratorDesc = STokenDesc<CElectricDescription>;
class CElectricDescription {
public:
CIntElement* x0_LIFE;
CIntElement* x4_SLIF;
CRealElement* x8_GRAT;
CIntElement* xc_SCNT;
CIntElement* x10_SSEG;
CColorElement* x14_COLR;
CEmitterElement* x18_IEMT;
CEmitterElement* x1c_FEMT;
CRealElement* x20_AMPL;
CRealElement* x24_AMPD;
CRealElement* x28_LWD1;
CRealElement* x2c_LWD2;
CRealElement* x30_LWD3;
CColorElement* x34_LCL1;
CColorElement* x38_LCL2;
CColorElement* x3c_LCL3;
// SSwooshGeneratorDesc x40_SSWH;
// SChildGeneratorDesc x50_GPSM;
// SChildGeneratorDesc x60_EPSM;
// bool x70_ZERY = false;
};
#endif // _CELECTRICDESCRIPTION

View File

@ -96,7 +96,9 @@ public:
rstl::optional_object< CModelData >& SolidModelData() { return x10_solidModelData; }
const CModelData& GetSolidModelData() const { return x10_solidModelData.data(); }
EWeaponType GetWeaponType() const { return x1c0_weaponType; }
TUniqueId GetPlayerId() const { return x1c4_playerId; }
EMaterialTypes GetPlayerMaterial() const { return x1c8_playerMaterial; }
CAABox GetBounds() const;
CAABox GetBounds(const CTransform4f& xf) const;
@ -162,7 +164,7 @@ protected:
bool x218_28_suitArmLocked : 1;
bool x218_29_drawHologram : 1;
static int skShootAnim[2];
static const int skShootAnim[2];
void AllocResPools(CPlayerState::EBeamId beam);
void FreeResPools();

View File

@ -5,14 +5,41 @@
#include "MetroidPrime/Weapons/CGunWeapon.hpp"
#include "rstl/single_ptr.hpp"
class CElectricDescription;
class CParticleElectric;
class CWaveBeam : public CGunWeapon {
public:
CWaveBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId,
EMaterialTypes playerMaterial, const CVector3f& scale);
~CWaveBeam();
~CWaveBeam() override;
void PostRenderGunFx(const CStateManager& mgr, const CTransform4f& xf) override;
void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr,
const CTransform4f& xf) override;
void Fire(bool underwater, float dt, CPlayerState::EChargeStage chargeState,
const CTransform4f& xf, CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1,
float chargeFactor2) override;
void EnableSecondaryFx(ESecondaryFxType type) override;
void Update(float dt, CStateManager& mgr) override;
void Load(CStateManager& mgr, bool subtypeBasePose) override;
void Unload(CStateManager& mgr) override;
bool IsLoaded() const override;
private:
uchar x21c_pad[0x40];
TCachedToken< CWeaponDescription > x21c_waveBeam;
TCachedToken< CElectricDescription > x228_wave2nd1;
TCachedToken< CElectricDescription > x234_wave2nd2;
TCachedToken< CGenDescription > x240_wave2nd3;
float x24c_effectTimer;
rstl::single_ptr< CParticleElectric > x250_chargeElec;
rstl::single_ptr< CElementGen > x254_chargeFx;
bool x258_24_loaded : 1;
bool x258_25_effectTimerActive : 1;
void ReInitVariables();
};
CHECK_SIZEOF(CWaveBeam, 0x25c)

View File

@ -375,7 +375,7 @@ void CGunWeapon::DrawHologram(const CStateManager& mgr, const CTransform4f& xf,
}
}
int CGunWeapon::skShootAnim[2] = {4, 3};
const int CGunWeapon::skShootAnim[2] = {4, 3};
static float kChargeScaleFactor = 1.0f;

View File

@ -0,0 +1,180 @@
#include "MetroidPrime/Weapons/CWaveBeam.hpp"
#include "MetroidPrime/CAnimData.hpp"
#include "MetroidPrime/CAnimPlaybackParms.hpp"
#include "MetroidPrime/CStateManager.hpp"
#include "MetroidPrime/SFX/Weapons.h"
#include "MetroidPrime/Weapons/CEnergyProjectile.hpp"
#include "Kyoto/Audio/CSfxHandle.hpp"
#include "Kyoto/Audio/CSfxManager.hpp"
#include "Kyoto/Math/CMath.hpp"
#include "Kyoto/Math/CRelAngle.hpp"
#include "Kyoto/Particles/CElectricDescription.hpp"
#include "Kyoto/Particles/CElementGen.hpp"
#include "Kyoto/Particles/CParticleElectric.hpp"
static float skShotAnglePitchSource = 120.f;
static const float skShotAnglePitch = skShotAnglePitchSource;
static const ushort kSoundId[2] = {
SFXwpn_fire_wave_normal,
SFXwpn_fire_wave_charged,
};
CWaveBeam::CWaveBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId,
EMaterialTypes playerMaterial, const CVector3f& scale)
: CGunWeapon(characterId, type, playerId, playerMaterial, scale)
, x21c_waveBeam(gpSimplePool->GetObj("WaveBeam"))
, x228_wave2nd1(gpSimplePool->GetObj("Wave2nd_1"))
, x234_wave2nd2(gpSimplePool->GetObj("Wave2nd_2"))
, x240_wave2nd3(gpSimplePool->GetObj("Wave2nd_3"))
, x24c_effectTimer(0.f)
, x258_24_loaded(false)
, x258_25_effectTimerActive(false) {}
CWaveBeam::~CWaveBeam() {}
void CWaveBeam::ReInitVariables() {
x24c_effectTimer = 0.f;
x250_chargeElec = nullptr;
x254_chargeFx = nullptr;
x258_24_loaded = false;
x258_25_effectTimerActive = false;
x1cc_enabledSecondaryEffect = kSFT_None;
}
void CWaveBeam::PostRenderGunFx(const CStateManager& mgr, const CTransform4f& xf) {
if (x1cc_enabledSecondaryEffect != kSFT_None) {
if (x254_chargeFx.get())
x254_chargeFx->Render();
if (x250_chargeElec.get())
x250_chargeElec->Render();
}
CGunWeapon::PostRenderGunFx(mgr, xf);
}
void CWaveBeam::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr,
const CTransform4f& xf) {
if (x1cc_enabledSecondaryEffect != kSFT_None) {
if (x258_25_effectTimerActive && x24c_effectTimer < 0.f) {
x1cc_enabledSecondaryEffect = kSFT_None;
x24c_effectTimer = 0.f;
x258_25_effectTimerActive = false;
} else {
if (x254_chargeFx.get()) {
x254_chargeFx->SetGlobalTranslation(xf.GetTranslation());
x254_chargeFx->SetGlobalOrientation(xf.GetRotation());
x254_chargeFx->Update(dt);
}
if (x250_chargeElec.get()) {
x250_chargeElec->SetGlobalTranslation(xf.GetTranslation());
x250_chargeElec->SetGlobalOrientation(xf.GetRotation());
x250_chargeElec->Update(dt);
}
}
if (x258_25_effectTimerActive && x24c_effectTimer > 0.f)
x24c_effectTimer -= dt;
}
CGunWeapon::UpdateGunFx(shotSmoke, dt, mgr, xf);
}
void CWaveBeam::Update(float dt, CStateManager& mgr) {
CGunWeapon::Update(dt, mgr);
if (IsLoaded())
return;
if (CGunWeapon::IsLoaded() && !x258_24_loaded) {
x258_24_loaded = x228_wave2nd1.IsLoaded() && x234_wave2nd2.IsLoaded() &&
x240_wave2nd3.IsLoaded() && x21c_waveBeam.IsLoaded();
}
}
void CWaveBeam::Fire(bool underwater, float dt, CPlayerState::EChargeStage chargeState,
const CTransform4f& xf, CStateManager& mgr, TUniqueId homingTarget,
float chargeFactor1, float chargeFactor2) {
if (chargeState != CPlayerState::kCS_Normal) {
CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1,
chargeFactor2);
} else {
float randAng = mgr.Random()->Float() * 360.f;
for (int i = 0; i < 3; ++i) {
CTransform4f shotXf =
xf * CTransform4f::RotateY(CRelAngle::FromDegrees((randAng + i) * skShotAnglePitch));
CEnergyProjectile* proj = new CEnergyProjectile(
true, x144_weapons[chargeState], GetWeaponType(), shotXf, GetPlayerMaterial(),
GetDamageInfo(mgr, chargeState, chargeFactor1), mgr.AllocateUniqueId(), kInvalidAreaId,
GetPlayerId(), homingTarget, kPA_ArmCannon, underwater, CVector3f(1.f, 1.f, 1.f),
rstl::optional_object_null(), CSfxManager::kInternalInvalidSfxId, false);
mgr.AddObject(proj);
proj->Think(dt, mgr);
}
}
if (chargeState != CPlayerState::kCS_Normal)
x218_25_enableCharge = true;
NWeaponTypes::play_sfx(kSoundId[size_t(chargeState)], underwater, false, 0x4a);
x10_solidModelData->AnimationData()->EnableLooping(false);
const CAnimPlaybackParms parms(skShootAnim[chargeState], -1, 1.f, true);
x10_solidModelData->AnimationData()->SetAnimation(parms, false);
}
void CWaveBeam::Load(CStateManager& mgr, bool subtypeBasePose) {
CGunWeapon::Load(mgr, subtypeBasePose);
x228_wave2nd1.Lock();
x234_wave2nd2.Lock();
x240_wave2nd3.Lock();
x21c_waveBeam.Lock();
}
void CWaveBeam::Unload(CStateManager& mgr) {
CGunWeapon::Unload(mgr);
x21c_waveBeam.Unlock();
x240_wave2nd3.Unlock();
x234_wave2nd2.Unlock();
x228_wave2nd1.Unlock();
ReInitVariables();
}
bool CWaveBeam::IsLoaded() const { return CGunWeapon::IsLoaded() && x258_24_loaded; }
void CWaveBeam::EnableSecondaryFx(ESecondaryFxType type) {
switch (type) {
case kSFT_None:
x1cc_enabledSecondaryEffect = kSFT_None;
break;
case kSFT_CancelCharge:
if (x1cc_enabledSecondaryEffect == kSFT_None)
break;
// [[fallthrough]];
default:
if (x1cc_enabledSecondaryEffect != kSFT_ToCombo) {
CToken fx = type == kSFT_Charge ? x228_wave2nd1 : x234_wave2nd2;
x250_chargeElec = new CParticleElectric(fx);
x250_chargeElec->SetGlobalScale(x4_scale);
}
switch (type) {
case kSFT_Charge:
x254_chargeFx = nullptr;
break;
case kSFT_CancelCharge:
if (x1cc_enabledSecondaryEffect != kSFT_CancelCharge) {
x258_25_effectTimerActive = true;
x24c_effectTimer = 3.f;
if (x254_chargeFx.get())
x254_chargeFx->SetParticleEmission(false);
}
break;
case kSFT_ToCombo:
x254_chargeFx = new CElementGen(x240_wave2nd3);
x254_chargeFx->SetGlobalScale(x4_scale);
x24c_effectTimer = 0.f;
x258_25_effectTimerActive = true;
break;
default:
break;
}
x1cc_enabledSecondaryEffect = type;
}
}