mirror of
https://github.com/PrimeDecomp/prime.git
synced 2025-08-19 08:11:31 +00:00
160 lines
5.7 KiB
C++
160 lines
5.7 KiB
C++
#include "MetroidPrime/Enemies/CPuffer.hpp"
|
|
|
|
#include "Kyoto/Audio/CSfxManager.hpp"
|
|
#include "MetroidPrime/BodyState/CBodyController.hpp"
|
|
#include "MetroidPrime/CAnimData.hpp"
|
|
#include "MetroidPrime/Player/CPlayer.hpp"
|
|
#include "MetroidPrime/ScriptObjects/CFire.hpp"
|
|
|
|
static const char* skGasJetLocators[] = {
|
|
"GasJet01", "GasJet02", "GasJet03", "GasJet04", "GasJet05", "GasJet06", "GasJet07",
|
|
"GasJet08", "GasJet09", "GasJet10", "GasJet11", "GasJet12", "GasJet13", "GasJet14",
|
|
};
|
|
|
|
static const char* skGasLocators[] = {
|
|
"Gas_01_LCTR", "Gas_02_LCTR", "Gas_03_LCTR", "Gas_04_LCTR", "Gas_05_LCTR",
|
|
"Gas_06_LCTR", "Gas_07_LCTR", "Gas_08_LCTR", "Gas_09_LCTR", "Gas_10_LCTR",
|
|
"Gas_11_LCTR", "Gas_12_LCTR", "Gas_13_LCTR", "Gas_14_LCTR",
|
|
};
|
|
|
|
CPuffer::CPuffer(TUniqueId uid, const rstl::string& name, const CEntityInfo& info,
|
|
const CTransform4f& xf, const CModelData& modelData,
|
|
const CActorParameters& actorParameters, const CPatternedInfo& patternedInfo,
|
|
float hoverSpeed, CAssetId cloudEffect, const CDamageInfo& cloudDamage,
|
|
CAssetId cloudSteam, float f2, bool b1, bool b2, bool b3,
|
|
const CDamageInfo& explosionDamage, ushort sfxId)
|
|
: CPatterned(kC_Puffer, uid, name, kFT_Zero, info, xf, modelData, patternedInfo, kMT_Flyer, kCT_One,
|
|
kBT_RestrictedFlyer, actorParameters, kKBV_Small)
|
|
, x568_face(xf.GetColumn(kDY))
|
|
, x574_cloudEffect(gpSimplePool->GetObj(SObjectTag('PART', cloudEffect)))
|
|
, x57c_cloudDamage(cloudDamage)
|
|
, x598_24_(b1)
|
|
, x598_25_(b3)
|
|
, x598_26_(b2)
|
|
, x59a_(CSfxManager::TranslateSFXID(sfxId))
|
|
, x59c_explosionDamage(explosionDamage)
|
|
, x5b8_(f2)
|
|
, x5bc_cloudSteam(cloudSteam)
|
|
, x5c0_move(CVector3f::Zero())
|
|
, x5cc_(kInvalidUniqueId)
|
|
, x5d0_enabledParticles(0) {
|
|
CreateShadow(false);
|
|
GetKnockBackCtrl().SetImpulseDurationIdx(1);
|
|
x574_cloudEffect.Lock();
|
|
GetBodyCtrl()->SetRestrictedFlyerMoveSpeed(hoverSpeed);
|
|
}
|
|
|
|
CPuffer::~CPuffer() {}
|
|
|
|
void CPuffer::Accept(IVisitor& visitor) { visitor.Visit(*this); }
|
|
|
|
void CPuffer::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
|
|
CPatterned::AcceptScriptMsg(msg, uid, mgr);
|
|
|
|
switch (msg) {
|
|
case kSM_Registered:
|
|
GetBodyCtrl()->Activate(mgr);
|
|
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(kMT_Player, kMT_NoStaticCollision));
|
|
break;
|
|
case kSM_Action:
|
|
if (GetActive()) {
|
|
x401_30_pendingDeath = true;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CPuffer::Touch(CActor& act, CStateManager& mgr) {
|
|
CPatterned::Touch(act, mgr);
|
|
|
|
if (x400_25_alive && mgr.GetPlayer()->GetUniqueId() == act.GetUniqueId()) {
|
|
x401_30_pendingDeath = true;
|
|
}
|
|
}
|
|
|
|
rstl::optional_object< CAABox > CPuffer::GetTouchBounds() const {
|
|
rstl::optional_object< CAABox > touchBounds = CPatterned::GetTouchBounds();
|
|
if (touchBounds.valid()) {
|
|
CAABox box = *touchBounds;
|
|
box.AccumulateBounds(box.GetMinPoint() - CVector3f(0.5f, 0.5f, 0.5f));
|
|
box.AccumulateBounds(box.GetMaxPoint() + CVector3f(0.5f, 0.5f, 0.5f));
|
|
return box;
|
|
}
|
|
return touchBounds;
|
|
}
|
|
|
|
void CPuffer::Death(CStateManager& mgr, const CVector3f& vec, EScriptObjectState state) {
|
|
CPatterned::Death(mgr, vec, state);
|
|
|
|
mgr.ApplyDamageToWorld(
|
|
GetUniqueId(), *this, GetTranslation(), x59c_explosionDamage,
|
|
CMaterialFilter::MakeIncludeExclude(CMaterialList(kMT_Solid), CMaterialList()));
|
|
|
|
TUniqueId uid = mgr.AllocateUniqueId();
|
|
CAABox aabb =
|
|
CAABox(CVector3f(-1.f, -1.f, -1.f), CVector3f(1.f, 1.f, 1.f))
|
|
.GetTransformedAABox(GetTransform() * CTransform4f::Scale(x57c_cloudDamage.GetRadius()));
|
|
mgr.AddObject(new CFire(x574_cloudEffect, uid, GetCurrentAreaId(), true, GetUniqueId(),
|
|
GetTransform(), x57c_cloudDamage, aabb, CVector3f(1.f, 1.f, 1.f), true,
|
|
x5bc_cloudSteam, x598_24_, x598_26_, x598_25_, 1.f, x5b8_, 1.f, 1.f));
|
|
}
|
|
|
|
void CPuffer::Think(float dt, CStateManager& mgr) {
|
|
CPatterned::Think(dt, mgr);
|
|
|
|
sub8025bfa4(mgr);
|
|
CVector3f moveVector = x450_bodyController->GetCommandMgr().GetMoveVector();
|
|
|
|
if (x5cc_ != x2dc_destObj) {
|
|
x5cc_ = x2dc_destObj;
|
|
CSfxManager::AddEmitter(x59a_, GetTranslation(), CVector3f::Zero(), true, false);
|
|
}
|
|
|
|
x450_bodyController->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));
|
|
}
|
|
}
|
|
|
|
#define ARRAY_SIZE(arr) int(sizeof(arr) / sizeof(arr[0]))
|
|
|
|
void CPuffer::sub8025bfa4(CStateManager& mgr) {
|
|
CVector3f moveVector = x450_bodyController->GetCommandMgr().GetMoveVector();
|
|
|
|
if (x5d4_gasLocators.empty()) {
|
|
for (int i = 0; i < ARRAY_SIZE(skGasLocators); ++i) {
|
|
x5d4_gasLocators.push_back(
|
|
GetScaledLocatorTransform(rstl::string_l(skGasLocators[i])).GetColumn(kDY));
|
|
}
|
|
}
|
|
|
|
if (moveVector.CanBeNormalized()) {
|
|
CVector3f moveNorm = -moveVector.AsNormalized();
|
|
for (int i = 0; i < ARRAY_SIZE(skGasJetLocators); ++i) {
|
|
CVector3f tmp = GetTransform().Rotate(x5d4_gasLocators[i]);
|
|
float ang = CMath::FastCosR(CMath::Deg2Rad(45.f));
|
|
bool enable = CVector3f::Dot(moveNorm, tmp) > ang;
|
|
bool enabledCur = bool(x5d0_enabledParticles & (1 << i));
|
|
|
|
if (enabledCur != enable) {
|
|
AnimationData()->SetParticleEffectState(rstl::string_l(skGasJetLocators[i]), enable, mgr);
|
|
}
|
|
if (enable) {
|
|
x5d0_enabledParticles |= (1 << i);
|
|
} else {
|
|
x5d0_enabledParticles &= ~(1 << i);
|
|
}
|
|
}
|
|
} else {
|
|
for (int i = 0; i < ARRAY_SIZE(skGasJetLocators); ++i) {
|
|
if ((x5d0_enabledParticles & (1 << i)) != 0) {
|
|
AnimationData()->SetParticleEffectState(rstl::string_l(skGasJetLocators[i]), false, mgr);
|
|
}
|
|
}
|
|
x5d0_enabledParticles = 0;
|
|
}
|
|
}
|