95% match CMetaree

Former-commit-id: 280fe91feb
This commit is contained in:
Luke Street 2022-10-29 00:22:07 -04:00
parent f463d79f5d
commit 3b8eb2ed04
12 changed files with 350 additions and 25 deletions

View File

@ -3,8 +3,8 @@
.section .data
.balign 8
.global lbl_803E2878
lbl_803E2878:
.global __vt__8CMetaree
__vt__8CMetaree:
# ROM: 0x3DF878
.4byte 0
.4byte 0
@ -218,9 +218,9 @@ __dt__8CMetareeFv:
/* 8014E118 0014B078 93 C1 00 08 */ stw r30, 8(r1)
/* 8014E11C 0014B07C 7C 7E 1B 79 */ or. r30, r3, r3
/* 8014E120 0014B080 41 82 00 28 */ beq lbl_8014E148
/* 8014E124 0014B084 3C A0 80 3E */ lis r5, lbl_803E2878@ha
/* 8014E124 0014B084 3C A0 80 3E */ lis r5, __vt__8CMetaree@ha
/* 8014E128 0014B088 38 80 00 00 */ li r4, 0
/* 8014E12C 0014B08C 38 05 28 78 */ addi r0, r5, lbl_803E2878@l
/* 8014E12C 0014B08C 38 05 28 78 */ addi r0, r5, __vt__8CMetaree@l
/* 8014E130 0014B090 90 1E 00 00 */ stw r0, 0(r30)
/* 8014E134 0014B094 4B F2 94 3D */ bl __dt__10CPatternedFv
/* 8014E138 0014B098 7F E0 07 35 */ extsh. r0, r31
@ -1140,9 +1140,9 @@ Accept__8CMetareeFR8IVisitor:
/* 8014EE24 0014BD84 38 A1 00 20 */ addi r5, r1, 0x20
/* 8014EE28 0014BD88 38 80 00 12 */ li r4, 0x12
/* 8014EE2C 0014BD8C 4B F2 E6 25 */ bl "__ct__10CPatternedFQ210CPatterned10ECharacter9TUniqueIdRCQ24rstl66basic_string<c,Q24rstl14char_traits<c>,Q24rstl17rmemory_allocator>Q210CPatterned11EFlavorTypeRC11CEntityInfoRC12CTransform4fRC10CModelDataRC14CPatternedInfoQ210CPatterned13EMovementTypeQ210CPatterned13EColliderType9EBodyTypeRC16CActorParameters17EKnockBackVariant"
/* 8014EE30 0014BD90 3C 80 80 3E */ lis r4, lbl_803E2878@ha
/* 8014EE30 0014BD90 3C 80 80 3E */ lis r4, __vt__8CMetaree@ha
/* 8014EE34 0014BD94 3C 60 80 5A */ lis r3, sZeroVector__9CVector3f@ha
/* 8014EE38 0014BD98 38 04 28 78 */ addi r0, r4, lbl_803E2878@l
/* 8014EE38 0014BD98 38 04 28 78 */ addi r0, r4, __vt__8CMetaree@l
/* 8014EE3C 0014BD9C C0 02 9D 8C */ lfs f0, lbl_805ABAAC@sda21(r2)
/* 8014EE40 0014BDA0 90 1F 00 00 */ stw r0, 0(r31)
/* 8014EE44 0014BDA4 38 A3 66 A0 */ addi r5, r3, sZeroVector__9CVector3f@l

View File

@ -215,7 +215,7 @@ LIBS = [
["MetroidPrime/ScriptObjects/CScriptDistanceFog", False],
"MetroidPrime/BodyState/CBSProjectileAttack",
"MetroidPrime/Weapons/CPowerBomb",
"MetroidPrime/Enemies/CMetaree",
["MetroidPrime/Enemies/CMetaree", False],
["MetroidPrime/ScriptObjects/CScriptDockAreaChange", False],
["MetroidPrime/ScriptObjects/CScriptSpecialFunction", False],
"MetroidPrime/ScriptObjects/CScriptActorRotate",
@ -354,7 +354,7 @@ LIBS = [
"MetroidPrime/Enemies/CAtomicBeta",
"MetroidPrime/Weapons/CElectricBeamProjectile",
"MetroidPrime/Enemies/CRidley",
"MetroidPrime/Enemies/CPuffer",
["MetroidPrime/Enemies/CPuffer", False],
["MetroidPrime/ScriptObjects/CFire", False],
"MetroidPrime/CPauseScreenBlur",
"MetroidPrime/Enemies/CTryclops",

View File

@ -20,6 +20,7 @@ public:
else
x0_list.push_back(info.GetSwapped());
}
int GetCount() const { return x0_list.size(); }
iterator End() { return x0_list.end(); }
const_iterator End() const { return x0_list.end(); }

View File

@ -28,9 +28,12 @@ public:
void PlayBestAnimation(const CPASAnimParmData& parms, CRandom16& r);
bool HasIceBreakoutState();
void Activate(CStateManager& mgr);
void SetLocomotionType(pas::ELocomotionType type);
float GetPercentageFrozen() const;
void SetFallState(pas::EFallState state); // { x2f0_fallState = state; }
pas::EFallState GetFallState() const; // { return x2f0_fallState; }
const CBodyStateInfo& GetBodyStateInfo() const { return x2a4_bodyStateInfo; }
int GetCurrentAnimId() const { return x2f8_curAnim; }
pas::ELocomotionType GetLocomotionType() const { return x2ec_locomotionType; }
bool IsAnimationOver() const { return x300_24_animationOver; }

View File

@ -49,21 +49,22 @@ public:
: CBodyStateCmd(kBSC_Generate)
, x8_type(type)
, xc_targetPos(vec)
, x18_animId(-1)
, x1c_24_targetTransform(targetTransform)
, x1c_25_overrideAnim(overrideAnim) {}
pas::EGenerateType GetGenerateType() const { return x8_type; }
const CVector3f& GetExitTargetPos() const { return xc_targetPos; }
bool HasExitTargetPos() const { return x1c_24_targetTransform; }
int GetSpecialAnimId() const { return x18_animId; }
bool HasExitTargetPos() const { return x1c_24_targetTransform; }
bool UseSpecialAnimId() const { return x1c_25_overrideAnim; }
private:
pas::EGenerateType x8_type;
CVector3f xc_targetPos;
int x18_animId;
bool x1c_24_targetTransform : 1;
bool x1c_25_overrideAnim : 1;
uint x1c_24_targetTransform : 1;
uint x1c_25_overrideAnim : 1;
};
//
@ -390,8 +391,20 @@ class CBodyStateCmdMgr {
public:
void ClearLocomotionCmds();
void DeliverCmd(const CBCLocomotionCmd& cmd);
CBodyStateCmd* GetCmd(EBodyStateCmd cmd);
void DeliverCmd(EBodyStateCmd cmd);
void DeliverCmd(const CBCGenerateCmd& cmd) {
DeliverCmd(kBSC_Generate);
x18c_generate = cmd;
}
void DeliverCmd(const CBCKnockDownCmd& cmd) {
DeliverCmd(kBSC_KnockDown);
xdc_knockDown = cmd;
}
void DeliverTargetVector(const CVector3f& t) { x18_target = t; }
CBodyStateCmd* GetCmd(EBodyStateCmd cmd);
const CVector3f& GetMoveVector() const { return x0_move; }
const CVector3f& GetTargetVector() const { return x18_target; }

View File

@ -0,0 +1,64 @@
#ifndef _CMETAREE
#define _CMETAREE
#include "types.h"
#include "MetroidPrime/CDamageInfo.hpp"
#include "MetroidPrime/Enemies/CPatterned.hpp"
class CPatternedInfo;
class CGenDescription;
class CMetaree : public CPatterned {
public:
CMetaree(TUniqueId uid, const rstl::string& name, EFlavorType flavor, const CEntityInfo& info,
const CTransform4f& xf, const CModelData& mData, const CPatternedInfo& pInfo,
const CDamageInfo& dInfo, float f1, const CVector3f& v1, float f2, EBodyType bodyType,
float f3, float f4, const CActorParameters& aParms);
// CEntity
void Accept(IVisitor& visitor) override;
void Think(float dt, CStateManager& mgr) override;
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override;
// CActor
void Touch(CActor&, CStateManager&) override;
// CPhysicsActor
void CollidedWith(const TUniqueId& id, const CCollisionInfoList& list,
CStateManager& mgr) override;
// CAi
void Dead(CStateManager&, EStateMsg, float) override;
void Halt(CStateManager&, EStateMsg, float) override;
void Attack(CStateManager&, EStateMsg, float) override;
void Active(CStateManager&, EStateMsg, float) override;
void InActive(CStateManager&, EStateMsg, float) override;
void Flee(CStateManager&, EStateMsg, float) override;
void Explode(CStateManager&, EStateMsg, float) override;
bool InRange(CStateManager&, float) override;
bool Delay(CStateManager&, float) override;
bool ShouldAttack(CStateManager&, float) override;
// CPatterned
void ThinkAboutMove(float) override;
private:
float x568_delay;
float x56c_haltDelay;
float x570_dropHeight;
CVector3f x574_offset;
float x580_attackSpeed;
CVector3f x584_lookPos;
CVector3f x590_projectileDelta;
CVector3f x59c_velocity;
int x5a8_;
CDamageInfo x5ac_damageInfo;
ushort x5c8_attackSfx;
bool x5ca_24_ : 1;
bool x5ca_25_started : 1;
bool x5ca_26_deactivated : 1;
uint x5cc_;
};
#endif // _CMETAREE

View File

@ -240,7 +240,15 @@ public:
return x520_deathExplosionParticle;
}
void DeathDelete(CStateManager& mgr);
TUniqueId GetDestObj() const { return x2dc_destObj; } // TODO: name?
CStateMachineState& StateMachineState() { return x330_stateMachineState; }
const CStateMachineState& GetStateMachineState() const { return x330_stateMachineState; }
ECharacter GetCharacterType() const { return x34c_characterType; }
bool IsAlive() const { return x400_25_alive; }
void SetWasHit(bool v) { x400_24_hitByPlayerProjectile = v; }
void SetPendingDeath(bool v) { x401_30_pendingDeath = v; }
CBodyController* GetBodyCtrl() { return x450_bodyController.get(); }
const CBodyController* GetBodyCtrl() const { return x450_bodyController.get(); }
CKnockBackController& GetKnockBackCtrl() { return x460_knockBackController; }
@ -249,7 +257,7 @@ public:
template < class T >
static T* CastTo(const TPatternedCast< T >& ent);
public:
private:
EPatrolState x2d8_patrolState;
TUniqueId x2dc_destObj;
CVector3f x2e0_destPos;

View File

@ -32,6 +32,7 @@ public:
virtual void ResolveCollisionWithActor(const CRayCastResult& res, CActor& act,
CStateManager& mgr);
const CVector3f& GetPreviousPos() const { return x298_previousPos; }
TUniqueId GetHomingTargetId() const { return x2c0_homingTargetId; }
private:

View File

@ -25,8 +25,11 @@ public:
int /*EProjectileAttrib?*/) const override;
void FluidFXThink(EFluidState, CScriptWater&, CStateManager&) override;
EProjectileAttrib GetAttribField() const { return xe8_projectileAttribs; }
void SetDamageFalloffSpeed(float d);
EProjectileAttrib GetAttribField() const { return xe8_projectileAttribs; }
TUniqueId GetOwnerId() const { return xec_ownerId; }
private:
EProjectileAttrib xe8_projectileAttribs;
TUniqueId xec_ownerId;

View File

@ -2,7 +2,7 @@
#include "Kyoto/Math/CloseEnough.hpp"
const float CPhysicsActor::skGravityConstant = 9.81f * 2.5f;
const float CPhysicsActor::kGravityAccel = 9.81f * 2.5f;
CPhysicsActor::CPhysicsActor(TUniqueId uid, bool active, const rstl::string& name,
const CEntityInfo& info, const CTransform4f& xf,

View File

@ -0,0 +1,232 @@
#include "MetroidPrime/Enemies/CMetaree.hpp"
#include "MetroidPrime/BodyState/CBodyController.hpp"
#include "MetroidPrime/Player/CPlayer.hpp"
#include "MetroidPrime/SFX/Metaree.h"
#include "MetroidPrime/Weapons/CGameProjectile.hpp"
#include "Kyoto/Audio/CSfxManager.hpp"
#include "Collision/CCollisionInfoList.hpp"
CMetaree::CMetaree(TUniqueId uid, const rstl::string& name, EFlavorType flavor,
const CEntityInfo& info, const CTransform4f& xf, const CModelData& mData,
const CPatternedInfo& pInfo, const CDamageInfo& dInfo, float f1,
const CVector3f& v1, float f2, EBodyType bodyType, float f3, float f4,
const CActorParameters& aParms)
: CPatterned(kC_Metaree, uid, name, flavor, info, xf, mData, pInfo, kMT_Flyer, kCT_Zero, bodyType,
aParms, kKBV_Small)
, x568_delay(f3)
, x56c_haltDelay(f4)
, x570_dropHeight(f1)
, x574_offset(v1)
, x580_attackSpeed(f2)
, x584_lookPos(CVector3f::Zero())
, x590_projectileDelta(0.f, 0.f, 0.f)
, x59c_velocity(CVector3f::Zero())
, x5a8_(0)
, x5ac_damageInfo(dInfo)
, x5c8_attackSfx(SFXsfx0225)
, x5ca_24_(true)
, x5ca_25_started(false)
, x5ca_26_deactivated(false) {}
void CMetaree::Accept(IVisitor& visitor) { visitor.Visit(*this); }
void CMetaree::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
CPatterned::AcceptScriptMsg(msg, uid, mgr);
switch (msg) {
break;
case kSM_Registered:
GetBodyCtrl()->Activate(mgr);
break;
case kSM_Start:
x5ca_25_started = true;
break;
case kSM_Activate:
default:
break;
}
}
void CMetaree::ThinkAboutMove(float) {}
void CMetaree::CollidedWith(const TUniqueId& id, const CCollisionInfoList& colList,
CStateManager& mgr) {
if (IsAlive() && colList.GetCount() > 0) {
mgr.ApplyDamageToWorld(GetUniqueId(), *this, GetTranslation(), x5ac_damageInfo,
CMaterialFilter::MakeInclude(kMT_Player));
SendScriptMsgs(kSS_Arrived, mgr, kSM_None);
MassiveDeath(mgr);
}
}
void CMetaree::Touch(CActor& act, CStateManager& mgr) {
if (!IsAlive()) {
return;
}
if (CGameProjectile* projectile = TCastToPtr< CGameProjectile >(act)) {
if (projectile->GetOwnerId() != mgr.GetPlayer()->GetUniqueId()) {
return;
}
SetWasHit(true);
x590_projectileDelta = projectile->GetTranslation() - projectile->GetPreviousPos();
}
}
bool CMetaree::ShouldAttack(CStateManager&, float) {
return GetTranslation().GetZ() < x584_lookPos.GetZ();
}
bool CMetaree::InRange(CStateManager& mgr, float arg) {
return x5ca_25_started || CPatterned::InRange(mgr, arg);
}
void CMetaree::InActive(CStateManager&, EStateMsg msg, float) {
switch (msg) {
case kStateMsg_Activate:
if (!x5ca_26_deactivated) {
GetBodyCtrl()->SetLocomotionType(pas::kLT_Relaxed);
} else {
GetBodyCtrl()->SetLocomotionType(pas::kLT_Crouch);
}
break;
case kStateMsg_Update:
break;
case kStateMsg_Deactivate:
x5ca_26_deactivated = true;
break;
}
}
void CMetaree::Active(CStateManager& mgr, EStateMsg msg, float) {
switch (msg) {
case kStateMsg_Activate:
SetWasHit(false);
x584_lookPos = GetTranslation() - CVector3f(0.f, 0.f, x570_dropHeight);
GetBodyCtrl()->CommandMgr().DeliverCmd(CBCGenerateCmd(pas::kGType_Zero, x584_lookPos));
SetMomentumWR(CVector3f(0.f, 0.f, -GetGravityConstant() * GetMass()));
break;
case kStateMsg_Update:
GetBodyCtrl()->CommandMgr().DeliverTargetVector(
(mgr.GetPlayer()->GetTranslation() - GetTranslation()).AsNormalized());
break;
case kStateMsg_Deactivate:
SetMomentumWR(CVector3f::Zero());
break;
}
}
void CMetaree::Halt(CStateManager& mgr, EStateMsg msg, float) {
switch (msg) {
case kStateMsg_Activate: {
Stop();
SetVelocityWR(CVector3f::Zero());
SetMomentumWR(CVector3f::Zero());
GetBodyCtrl()->SetLocomotionType(pas::kLT_Lurk);
x584_lookPos = mgr.GetPlayer()->GetTranslation() + x574_offset;
SetTransform(CTransform4f::LookAt(GetTranslation(), x584_lookPos));
StateMachineState().SetDelay(x56c_haltDelay);
break;
}
case kStateMsg_Update:
case kStateMsg_Deactivate:
break;
}
}
void CMetaree::Attack(CStateManager&, EStateMsg msg, float) {
switch (msg) {
case kStateMsg_Activate: {
x5a8_ = 0;
CVector3f dir = (x584_lookPos - GetTranslation()).AsNormalized();
SetVelocityWR(x580_attackSpeed * dir);
CSfxManager::AddEmitter(x5c8_attackSfx, GetTranslation(), CVector3f::Zero(), true, false);
GetBodyCtrl()->SetLocomotionType(pas::kLT_Combat);
x59c_velocity = x580_attackSpeed * dir;
break;
}
case kStateMsg_Update:
if (GetBodyCtrl()->GetPercentageFrozen() == 0.f) {
SetVelocityWR(x59c_velocity);
} else {
Stop();
SetVelocityWR(CVector3f::Zero());
}
break;
case kStateMsg_Deactivate:
break;
}
}
void CMetaree::Dead(CStateManager& mgr, EStateMsg msg, float) {
switch (msg) {
case kStateMsg_Activate:
mgr.ApplyDamageToWorld(
GetUniqueId(), *this, GetTranslation(), x5ac_damageInfo,
CMaterialFilter::MakeIncludeExclude(CMaterialList(kMT_Player), CMaterialList()));
DeathDelete(mgr);
break;
default:
break;
}
}
void CMetaree::Flee(CStateManager& mgr, EStateMsg msg, float) {
switch (msg) {
case kStateMsg_Activate: {
CVector3f ang =
GetMass() * CVector3f(x590_projectileDelta.GetX(), x590_projectileDelta.GetY(), 0.f) * 5.f;
ApplyImpulseWR(ang, CAxisAngle::Identity());
SetMomentumWR(CVector3f(0.f, 0.f, -GetGravityConstant() * GetMass()));
SetTransform(CTransform4f::Translate(GetTranslation()));
x5a8_ = 0;
break;
}
case kStateMsg_Update: {
if (x5a8_ == 0) {
if (GetBodyCtrl()->GetBodyStateInfo().GetCurrentStateId() == pas::kAS_LieOnGround) {
x5a8_ = 1;
} else {
GetBodyCtrl()->CommandMgr().DeliverCmd(
CBCKnockDownCmd(CVector3f(0.f, 1.f, 0.f), pas::kS_Zero));
}
}
break;
}
case kStateMsg_Deactivate:
break;
}
}
void CMetaree::Explode(CStateManager& mgr, EStateMsg msg, float) {
switch (msg) {
case kStateMsg_Activate:
mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer()->GetUniqueId(), GetUniqueId(), x5ac_damageInfo,
CMaterialFilter::MakeIncludeExclude(CMaterialList(kMT_Solid), CMaterialList()),
CVector3f::Zero());
MassiveDeath(mgr);
break;
default:
break;
}
}
void CMetaree::Think(float dt, CStateManager& mgr) {
bool target = true;
CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetCurrentVisor();
bool b = visor != CPlayerState::kPV_Thermal && visor != CPlayerState::kPV_Scan;
if (!b && !x5ca_26_deactivated) {
target = false;
}
xe7_31_targetable = target;
CPatterned::Think(dt, mgr);
}
bool CMetaree::Delay(CStateManager&, float) override {
return GetStateMachineState().GetTime() > x568_delay;
}

View File

@ -58,7 +58,7 @@ void CPuffer::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMan
break;
case kSM_Action:
if (GetActive()) {
x401_30_pendingDeath = true;
SetPendingDeath(true);
}
break;
default:
@ -69,8 +69,8 @@ void CPuffer::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMan
void CPuffer::Touch(CActor& act, CStateManager& mgr) {
CPatterned::Touch(act, mgr);
if (x400_25_alive && mgr.GetPlayer()->GetUniqueId() == act.GetUniqueId()) {
x401_30_pendingDeath = true;
if (IsAlive() && mgr.GetPlayer()->GetUniqueId() == act.GetUniqueId()) {
SetPendingDeath(true);
}
}
@ -105,24 +105,24 @@ void CPuffer::Think(float dt, CStateManager& mgr) {
CPatterned::Think(dt, mgr);
sub8025bfa4(mgr);
CVector3f moveVector = x450_bodyController->GetCommandMgr().GetMoveVector();
CVector3f moveVector = GetBodyCtrl()->GetCommandMgr().GetMoveVector();
if (x5cc_ != x2dc_destObj) {
x5cc_ = x2dc_destObj;
if (x5cc_ != GetDestObj()) {
x5cc_ = GetDestObj();
CSfxManager::AddEmitter(x59a_, GetTranslation(), CVector3f::Zero(), true, false);
}
x450_bodyController->CommandMgr().ClearLocomotionCmds();
GetBodyCtrl()->CommandMgr().ClearLocomotionCmds();
if (moveVector.CanBeNormalized()) {
x5c0_move = CVector3f::Lerp(x5c0_move, moveVector, dt / 0.5f).AsNormalized();
x450_bodyController->CommandMgr().DeliverCmd(CBCLocomotionCmd(x5c0_move, x568_face, 1.f));
GetBodyCtrl()->CommandMgr().DeliverCmd(CBCLocomotionCmd(x5c0_move, x568_face, 1.f));
}
}
#define ARRAY_SIZE(arr) int(sizeof(arr) / sizeof(arr[0]))
#define ARRAY_SIZE(arr) static_cast< int >(sizeof(arr) / sizeof(arr[0]))
void CPuffer::sub8025bfa4(CStateManager& mgr) {
CVector3f moveVector = x450_bodyController->GetCommandMgr().GetMoveVector();
CVector3f moveVector = GetBodyCtrl()->GetCommandMgr().GetMoveVector();
if (x5d4_gasLocators.empty()) {
for (int i = 0; i < ARRAY_SIZE(skGasLocators); ++i) {