prime/src/MetroidPrime/Enemies/CMetaree.cpp

238 lines
6.9 KiB
C++

#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(CMaterialList(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: {
switch(x5a8_) {
case 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;
default:
break;
}
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;
}
SetTargetable(target);
CPatterned::Think(dt, mgr);
}
bool CMetaree::Delay(CStateManager&, float) {
return GetStateMachineState().GetTime() > x568_delay;
}