Initial CMetroidPrimeEssence behavior

This commit is contained in:
Phillip Stephens 2020-09-19 15:08:07 -07:00
parent 130c60ccc8
commit 543a24ea9e
Signed by: Antidote
GPG Key ID: F8BEE4C83DACA60D
7 changed files with 750 additions and 8 deletions

View File

@ -192,7 +192,7 @@ CStateManager::CStateManager(const std::weak_ptr<CRelayTracker>& relayTracker,
x90c_loaderFuncs[size_t(EScriptObjectType::Burrower)] = ScriptLoader::LoadBurrower;
x90c_loaderFuncs[size_t(EScriptObjectType::ScriptBeam)] = ScriptLoader::LoadBeam;
x90c_loaderFuncs[size_t(EScriptObjectType::WorldLightFader)] = ScriptLoader::LoadWorldLightFader;
x90c_loaderFuncs[size_t(EScriptObjectType::MetroidPrimeStage2)] = ScriptLoader::LoadMetroidPrimeStage2;
x90c_loaderFuncs[size_t(EScriptObjectType::MetroidPrimeStage2)] = ScriptLoader::LoadMetroidPrimeEssence;
x90c_loaderFuncs[size_t(EScriptObjectType::MetroidPrimeStage1)] = ScriptLoader::LoadMetroidPrimeStage1;
x90c_loaderFuncs[size_t(EScriptObjectType::MazeNode)] = ScriptLoader::LoadMazeNode;
x90c_loaderFuncs[size_t(EScriptObjectType::OmegaPirate)] = ScriptLoader::LoadOmegaPirate;

View File

@ -32,6 +32,7 @@ set(MP1_WORLD_SOURCES
CMetroidPrimeExo.hpp CMetroidPrimeExo.cpp
CMetroidPrimeProjectile.hpp CMetroidPrimeProjectile.cpp
CMetroidPrimeRelay.hpp CMetroidPrimeRelay.cpp
CMetroidPrimeEssence.hpp CMetroidPrimeEssence.cpp
CNewIntroBoss.hpp CNewIntroBoss.cpp
COmegaPirate.hpp COmegaPirate.cpp
CParasite.hpp CParasite.cpp

View File

@ -0,0 +1,607 @@
#include "Runtime/MP1/World/CMetroidPrimeEssence.hpp"
#include "Runtime/CSimplePool.hpp"
#include "Runtime/CStateManager.hpp"
#include "Runtime/Collision/CCollisionActor.hpp"
#include "Runtime/Collision/CCollisionActorManager.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Weapon/CGameProjectile.hpp"
#include "Runtime/World/CGameArea.hpp"
#include "Runtime/World/CPatternedInfo.hpp"
#include "Runtime/World/CPlayer.hpp"
#include "Runtime/World/CWorld.hpp"
#include "Runtime/Graphics/CBooRenderer.hpp"
#include "DataSpec/DNAMP1/SFX/MetroidPrime.h"
#include "TCastTo.hpp" // Generated file, do not modify include path
namespace urde::MP1 {
namespace {
std::array<SSphereJointInfo, 1> skJointInfo{{
{"lockon_target_LCTR", 1.5f},
}};
std::array<u32, 4> skUnkInts1{{0, 1, 0, 2}};
std::array<u32, 3> skUnkInts2{{1, 2, 3}};
} // namespace
CMetroidPrimeEssence::CMetroidPrimeEssence(urde::TUniqueId uid, std::string_view name, const urde::CEntityInfo& info,
const zeus::CTransform& xf, urde::CModelData&& mData,
const urde::CPatternedInfo& pInfo, const urde::CActorParameters& actParms,
urde::CAssetId particle1, const urde::CDamageInfo& dInfo, float f1,
urde::CAssetId electric, u32 w1, urde::CAssetId particle2)
: CPatterned(ECharacter::MetroidPrimeEssence, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, actParms, EKnockBackVariant::Medium)
, x568_(g_SimplePool->GetObj({FOURCC('PART'), particle2}))
, x574_searchPath(nullptr, 3, pInfo.GetPathfindingIndex(), 1.f, 1.f)
, x660_(particle1)
, x664_(electric)
, x698_(dInfo)
, x6b4_(xf.origin)
, x70c_(CSfxManager::TranslateSFXID(w1)) {}
void CMetroidPrimeEssence::Think(float dt, CStateManager& mgr) {
if (!GetActive()) {
return;
}
CPatterned::Think(dt, mgr);
if (IsAlive()) {
UpdatePhase(dt, mgr);
}
x450_bodyController->FaceDirection((mgr.GetPlayer().GetTranslation() - GetTranslation()).normalized(), dt);
x658_collisionManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
UpdateHealth(mgr);
CountListeningAi(mgr);
if (x70e_30_) {
x6d4_ = 2.f * dt + x6d4_;
if (x6d4_ >= 1.f) {
x6d4_ = 0.f;
}
sub8027ce5c(-4.f * x6d4_ * (x6d4_ - 1.f));
}
}
void CMetroidPrimeEssence::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId other, CStateManager& mgr) {
CPatterned::AcceptScriptMsg(msg, other, mgr);
switch (msg) {
case EScriptObjectMessage::Activate:
x658_collisionManager->SetActive(mgr, true);
break;
case EScriptObjectMessage::Deactivate:
x658_collisionManager->SetActive(mgr, false);
break;
case EScriptObjectMessage::Start:
x70e_25_ = true;
break;
case EScriptObjectMessage::Stop:
x70e_25_ = false;
break;
case EScriptObjectMessage::Touched: {
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(other)) {
if (colAct->GetLastTouchedObject() == mgr.GetPlayer().GetUniqueId()) {
mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), GetContactDamage(),
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), zeus::skZero3f);
x420_curDamageRemTime = x424_damageWaitTime;
}
}
break;
}
case EScriptObjectMessage::Registered: {
SetupCollisionActorManager(mgr);
x658_collisionManager->SetActive(mgr, true);
x6cc_ = GetModelData()->GetScale().x();
x6d0_ = 0.9f * x6cc_ + x6cc_;
x55c_moveScale.splat(1.f / (0.625f * x6cc_));
const float hp = GetHealthInfo(mgr)->GetHP();
x6c0_ = 0.3f * hp;
if (hp > 0.f) {
x6c4_ = 1.f / hp;
}
x450_bodyController->Activate(mgr);
break;
}
case EScriptObjectMessage::Deleted: {
x658_collisionManager->Destroy(mgr);
mgr.SetBossParams(kInvalidUniqueId, 0.f, 0);
break;
}
case EScriptObjectMessage::InitializedInArea: {
x574_searchPath.SetArea(mgr.GetWorld()->GetArea(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea);
x704_ = GetWaypointForState(mgr, EScriptObjectState::Play, EScriptObjectMessage::Activate);
break;
}
case EScriptObjectMessage::Damage: {
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(other)) {
if (TCastToConstPtr<CGameProjectile> proj = mgr.GetObjectById(colAct->GetLastTouchedObject())) {
if (proj->GetOwnerId() == mgr.GetPlayer().GetUniqueId()) {
if (colAct->GetDamageVulnerability()->WeaponHits(proj->GetDamageInfo().GetWeaponMode(), false) &&
proj->GetDamageInfo().GetWeaponMode().GetType() == EWeaponType::Phazon) {
sub8027cee0(mgr);
TakeDamage(zeus::skForward, 1.f);
if (!x70e_24_ && !x70e_26_) {
GetBodyController()->GetCommandMgr().DeliverCmd(
CBCKnockBackCmd{GetTransform().frontVector(), pas::ESeverity::One});
sub8027cce0(mgr);
}
}
}
}
} else if (TCastToConstPtr<CGameProjectile> proj = mgr.GetObjectById(other)) {
mgr.ApplyDamage(other, x706_lockOnTargetCollider, proj->GetOwnerId(), proj->GetDamageInfo(),
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), zeus::skZero3f);
}
break;
}
default:
break;
}
}
void CMetroidPrimeEssence::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) {
CPatterned::PreRender(mgr, frustum);
}
void CMetroidPrimeEssence::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) {
if (GetActive() && x65c_) {
g_Renderer->AddParticleGen(*x65c_);
}
CPatterned::AddToRenderer(frustum, mgr);
}
void CMetroidPrimeEssence::Render(CStateManager& mgr) {
if (x70e_27_) {
mgr.DrawSpaceWarp(x6b4_, 1.f);
}
CPatterned::Render(mgr);
}
zeus::CVector3f CMetroidPrimeEssence::GetAimPosition(const CStateManager& mgr, float dt) const {
if (TCastToConstPtr<CCollisionActor> colAct = mgr.GetObjectById(x706_lockOnTargetCollider)) {
return colAct->GetTranslation();
}
return CPatterned::GetAimPosition(mgr, dt);
}
void CMetroidPrimeEssence::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type,
float dt) {
CPatterned::DoUserAnimEvent(mgr, node, type, dt);
}
void CMetroidPrimeEssence::Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) {
if (!IsAlive()) {
return;
}
sub8027ee88(mgr);
sub8027d790(mgr, false);
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(x706_lockOnTargetCollider)) {
colAct->AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr);
}
CPatterned::Death(mgr, direction, state);
}
void CMetroidPrimeEssence::Dead(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg != EStateMsg::Update || GetModelData()->GetAnimationData()->IsAnimTimeRemaining(dt, "Whole Body"sv)) {
return;
}
DeathDelete(mgr);
}
void CMetroidPrimeEssence::PathFind(CStateManager& mgr, EStateMsg msg, float dt) {
CPatterned::PathFind(mgr, msg, dt);
if (msg == EStateMsg::Update) {
sub8027cb40(GetTranslation());
}
}
void CMetroidPrimeEssence::Halt(CStateManager& mgr, EStateMsg msg, float dt) {
// Intentionally empty
}
void CMetroidPrimeEssence::Generate(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
zeus::CTransform xf = zeus::lookAt(GetTranslation(), mgr.GetPlayer().GetTranslation());
xf.origin = GetTranslation();
SetTransform(xf);
} else if (msg == EStateMsg::Deactivate) {
mgr.SetBossParams(GetUniqueId(), GetHealthInfo(mgr)->GetHP(), 91);
sub8027d790(mgr, true);
}
}
void CMetroidPrimeEssence::JumpBack(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
x32c_animState = EAnimState::Ready;
x700_ = sub8027cfd4(mgr, 1);
} else if (msg == EStateMsg::Update) {
TryCommand(mgr, pas::EAnimationState::Step, &CPatterned::TryStep, x700_);
} else if (msg == EStateMsg::Deactivate) {
x32c_animState = EAnimState::NotReady;
}
}
void CMetroidPrimeEssence::Skid(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
x32c_animState = EAnimState::Ready;
} else if (msg == EStateMsg::Update) {
TryCommand(mgr, pas::EAnimationState::Step, &CPatterned::TryStep, 5);
} else if (msg == EStateMsg::Deactivate) {
x32c_animState = EAnimState::NotReady;
}
}
void CMetroidPrimeEssence::FadeIn(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
x6f8_ = sub8027d428();
x32c_animState = EAnimState::Ready;
x70e_24_ = true;
} else if (msg == EStateMsg::Update) {
TryCommand(mgr, pas::EAnimationState::ProjectileAttack, &CPatterned::TryProjectileAttack, 0);
} else if (msg == EStateMsg::Deactivate) {
x70e_24_ = false;
x70e_27_ = false;
x70e_29_ = false;
x70e_30_ = false;
x32c_animState = EAnimState::NotReady;
}
}
void CMetroidPrimeEssence::FadeOut(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg != EStateMsg::Activate) {
return;
}
DoPhaseTransition(mgr);
}
void CMetroidPrimeEssence::Taunt(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
x32c_animState = EAnimState::Ready;
} else if (msg == EStateMsg::Update) {
TryCommand(mgr, pas::EAnimationState::Taunt, &CPatterned::TryTaunt, 2);
} else if (msg == EStateMsg::Deactivate) {
x32c_animState = EAnimState::NotReady;
}
}
void CMetroidPrimeEssence::TelegraphAttack(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
x32c_animState = EAnimState::Ready;
x70e_30_ = true;
} else if (msg == EStateMsg::Update) {
if (!x70e_30_) {
TryCommand(mgr, pas::EAnimationState::MeleeAttack, &CPatterned::TryMeleeAttack, 2);
} else {
TryCommand(mgr, pas::EAnimationState::ProjectileAttack, &CPatterned::TryProjectileAttack, 5);
}
} else if (msg == EStateMsg::Deactivate) {
x32c_animState = EAnimState::NotReady;
x70e_30_ = false;
sub8027ce5c(dt);
}
}
void CMetroidPrimeEssence::Dodge(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
x32c_animState = EAnimState::Ready;
x700_ = sub8027cfd4(mgr, 0);
} else if (msg == EStateMsg::Update) {
TryCommand(mgr, pas::EAnimationState::Step, &CPatterned::TryStep, x700_);
} else if (msg == EStateMsg::Deactivate) {
x32c_animState = EAnimState::NotReady;
}
}
void CMetroidPrimeEssence::PathFindEx(CStateManager& mgr, EStateMsg msg, float dt) {
CPatterned::PathFind(mgr, msg, dt);
if (msg == EStateMsg::Activate) {
x70e_24_ = true;
} else if (msg == EStateMsg::Update) {
sub8027cb40(x2e0_destPos);
} else if (msg == EStateMsg::Deactivate) {
x70e_24_ = false;
}
}
bool CMetroidPrimeEssence::HasPatrolPath(CStateManager& mgr, float dt) {
return !x70e_30_ && CPatterned::HasPatrolPath(mgr, dt);
}
bool CMetroidPrimeEssence::ShouldAttack(CStateManager& mgr, float dt) { return x70e_30_ && x70e_25_; }
bool CMetroidPrimeEssence::InPosition(CStateManager& mgr, float dt) {
return (GetTranslation().z() - mgr.GetPlayer().GetTranslation().z()) > 0.25f;
}
bool CMetroidPrimeEssence::CoverFind(CStateManager& mgr, float dt) {
return (x2e0_destPos - GetTranslation()).magSquared() < 90.f;
}
bool CMetroidPrimeEssence::ShouldTaunt(CStateManager& mgr, float dt) {
const CHealthInfo* info = GetHealthInfo(mgr);
if (!info || info->GetHP() <= x6c0_) {
return false;
}
return mgr.GetActiveRandom()->Next() % 100 < 50;
}
bool CMetroidPrimeEssence::ShouldCrouch(CStateManager& mgr, float dt) {
if (x6f0_ < x6f4_) {
++x6f0_;
return false;
}
x6f4_ = std::min(static_cast<u32>(3.f * (1.f - x6c4_ * GetHealthInfo(mgr)->GetHP())), x6ec_);
x6f0_ = 0;
return true;
}
bool CMetroidPrimeEssence::ShouldMove(CStateManager& mgr, float dt) { return x70e_30_; }
CPathFindSearch* CMetroidPrimeEssence::GetSearchPath() { return &x574_searchPath; }
void CMetroidPrimeEssence::sub8027cb40(const zeus::CVector3f& vec) {
pas::EStepDirection stepDir = GetStepDirection(GetBodyController()->GetCommandMgr().GetMoveVector());
if (stepDir == pas::EStepDirection::Forward &&
(x2e0_destPos - GetTranslation()).normalized().dot(GetTransform().frontVector().normalized()) <
zeus::degToRad(-15.f)) {
stepDir = pas::EStepDirection::Backward;
}
GetBodyController()->GetCommandMgr().DeliverCmd(CBCStepCmd(stepDir, pas::EStepType::Normal));
GetBodyController()->GetCommandMgr().DeliverTargetVector(vec - GetTranslation());
}
void CMetroidPrimeEssence::sub8027cce0(CStateManager& mgr) {
if (CSfxManager::IsPlaying(x708_)) {
return;
}
CAudioSys::C3DEmitterParmData emitterData{zeus::skZero3f, zeus::skZero3f, 1000.f, 0.1f, 1, SFXsfx0B67, 1.f,
0.16f, false, 127};
emitterData.x0_pos = GetTargetTransform(mgr).origin;
x708_ = CSfxManager::AddEmitter(emitterData, true, 127, false, GetAreaIdAlways());
}
zeus::CTransform CMetroidPrimeEssence::GetTargetTransform(CStateManager& mgr) {
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(x706_lockOnTargetCollider)) {
return colAct->GetTransform();
}
return GetTransform();
}
void CMetroidPrimeEssence::sub8027ce5c(float dt) {
const auto matCount = static_cast<float>(GetModelData()->GetNumMaterialSets() - 2);
u32 iVar1 = matCount - (matCount * dt);
if (x6fc_ != iVar1) {
x6fc_ = iVar1;
}
}
void CMetroidPrimeEssence::sub8027cee0(CStateManager& mgr) {
const float hp = x6c4_ * GetHealthInfo(mgr)->GetHP();
if (hp < 0.f) {
return;
}
bool sendMsg = false;
if (x6d8_ == 0 && hp < 0.75f) {
x6d8_ = 1;
} else if (x6d8_ == 1 && hp < 0.5f) {
sendMsg = true;
x6d8_ = 2;
} else if (x6d8_ == 2 && hp < 0.25f) {
sendMsg = true;
x6d8_ = 3;
}
if (sendMsg) {
SendScriptMsgs(EScriptObjectState::DeactivateState, mgr, EScriptObjectMessage::None);
}
}
u32 CMetroidPrimeEssence::sub8027cfd4(CStateManager& mgr, u32 w1) {
zeus::CTransform xf = GetTargetTransform(mgr);
u32 uVar1 = zeus::countLeadingZeros(w1);
uVar1 >>= 5;
std::array<zeus::CVector3f, 2> vec;
const zeus::CVector3f* dir = &vec[uVar1];
vec[0] = -xf.frontVector();
vec[1] = -xf.rightVector();
u32 uVar5 = 1 << uVar1;
for (size_t i = uVar1; i < 3; ++i) {
CRayCastResult res = mgr.RayStaticIntersection(xf.origin, *dir, 20.f, CMaterialFilter::skPassEverything);
if (res.IsInvalid()) {
uVar5 |= 1 << i;
}
++dir;
}
u32 uVar3 = 0;
if (uVar5 < 8) {
u32 numBits = zeus::PopCount(uVar5);
if (numBits == 2) {
u32 uVar1_ = mgr.GetActiveRandom()->Next();
if ((uVar1_ & 1) == false) {
uVar3 = (uVar5 & 1) ^ 1;
} else {
uVar3 = ((uVar5 >> 2) & 1) + 1;
}
} else if (numBits < 2) {
uVar3 = uVar5 >> 1;
} else if (numBits == 3) {
uVar3 = mgr.GetActiveRandom()->Range(uVar1, 2);
}
}
return skUnkInts2[uVar3];
}
void CMetroidPrimeEssence::DoPhaseTransition(CStateManager& mgr) {
x330_stateMachineState.SetDelay(2.f);
x70e_26_ = true;
x70e_27_ = true;
x6c8_ = 1.f;
x70e_29_ = false;
bool uVar3 = x6dc_ == skUnkInts1[size_t(mgr.GetPlayerState()->GetCurrentVisor())];
if (skUnkInts1[size_t(mgr.GetPlayerState()->GetCurrentVisor())] == x6dc_) {
x65c_ = std::make_unique<CElementGen>(x568_, CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One);
if (x65c_) {
zeus::CTransform xf = GetTargetTransform(mgr);
x65c_->SetGlobalScale(GetModelData()->GetScale());
x65c_->SetGlobalOrientation(xf.getRotation());
x65c_->SetGlobalTranslation(xf.origin);
}
}
CSfxManager::AddEmitter(SFXsfx0B7D + uVar3, GetTranslation(), zeus::skZero3f, true, false, 127, kInvalidAreaId);
x6e0_ = x6dc_;
++x6dc_;
if (x6dc_ > 2) {
x6dc_ = 0;
}
}
void CMetroidPrimeEssence::ShakeCamera(CStateManager& mgr, float f1) {
float mag = 0.5f - (0.01f * (GetTranslation() - mgr.GetPlayer().GetTranslation()).magnitude());
if (mag < 0.f || mgr.GetPlayer().GetSurfaceRestraint() == CPlayer::ESurfaceRestraints::Air) {
return;
}
mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData(0.5f, mag), true);
}
void CMetroidPrimeEssence::sub8027d52c(CStateManager& mgr, const SShockWaveData& shockWaveData) {}
CRayCastResult CMetroidPrimeEssence::sub8027d704(CStateManager& mgr) { return CRayCastResult(); }
void CMetroidPrimeEssence::sub8027d790(CStateManager& mgr, bool active) {}
void CMetroidPrimeEssence::sub8027d824(CStateManager& mgr) {}
bool CMetroidPrimeEssence::sub8027e870(const zeus::CTransform& xf, CStateManager& mgr) { return false; }
void CMetroidPrimeEssence::sub8027ee88(CStateManager& mgr) {}
void CMetroidPrimeEssence::CountListeningAi(CStateManager& mgr) {
x6e0_ = 0;
for (auto* ent : mgr.GetListeningAiObjectList()) {
if (TCastToPtr<CAi> ai = ent) {
if (ai != this && ai->GetActive() && ai->GetAreaIdAlways() == GetAreaIdAlways()) {
++x6e4_;
}
}
}
}
void CMetroidPrimeEssence::UpdatePhase(float dt, CStateManager& mgr) {
if (skUnkInts1[size_t(mgr.GetPlayerState()->GetCurrentVisor())] == x6dc_) {
x42c_color.a() = 1.f - x6c8_;
GetModelData()->SetScale(zeus::CVector3f((x6cc_ - x6d0_) + x6d0_));
if (!x70e_28_) {
AddMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr);
sub8027d790(mgr, true);
x70e_28_ = true;
}
} else {
x42c_color.a() = skUnkInts1[size_t(mgr.GetPlayerState()->GetCurrentVisor())] == x6e0_ ? x6c8_ : 0.f;
GetModelData()->SetScale(zeus::CVector3f((x6cc_ - x6d0_) + x6d0_));
if (x70e_28_) {
RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr);
sub8027d790(mgr, false);
x70e_28_ = false;
}
}
zeus::CTransform xf = GetTargetTransform(mgr);
if (x70e_26_) {
x6c8_ -= 0.5f * dt;
x6b4_ = xf.origin;
if (x6c8_ < 0.f) {
x6c8_ = 0.f;
x70e_26_ = false;
x70e_27_ = false;
}
}
if (!x65c_) {
return;
}
if (!x65c_->IsSystemDeletable()) {
x65c_->SetGlobalOrientation(xf.getRotation());
x65c_->SetGlobalTranslation(xf.origin);
x65c_->Update(dt);
} else {
x65c_.reset();
}
}
void CMetroidPrimeEssence::UpdateHealth(CStateManager& mgr) {
if (!IsAlive()) {
return;
}
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(x706_lockOnTargetCollider)) {
colAct->SetDamageVulnerability(*GetDamageVulnerability());
HealthInfo(mgr)->SetHP(colAct->GetHealthInfo(mgr)->GetHP());
}
if (GetHealthInfo(mgr)->GetHP() <= 0.f) {
Death(mgr, zeus::skZero3f, EScriptObjectState::DeathRattle);
RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr);
}
}
void CMetroidPrimeEssence::SetLockOnTargetHealthAndDamageVulns(CStateManager& mgr) {
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(x706_lockOnTargetCollider)) {
*colAct->HealthInfo(mgr) = *HealthInfo(mgr);
colAct->SetDamageVulnerability(*GetDamageVulnerability());
}
}
void CMetroidPrimeEssence::AddSphereCollisions(SSphereJointInfo* info, size_t count,
std::vector<CJointCollisionDescription>& vecOut) {
const CAnimData* animData = GetModelData()->GetAnimationData();
for (size_t i = 0; i < count; ++i) {
CSegId segId = animData->GetLocatorSegId(info[i].name);
if (segId.IsInvalid()) {
continue;
}
vecOut.push_back(CJointCollisionDescription::SphereCollision(segId, info[i].radius, info[i].name, 1000.f));
}
}
void CMetroidPrimeEssence::SetupCollisionActorManager(CStateManager& mgr) {
std::vector<CJointCollisionDescription> joints;
AddSphereCollisions(skJointInfo.data(), skJointInfo.size(), joints);
x658_collisionManager =
std::make_unique<CCollisionActorManager>(mgr, GetUniqueId(), GetAreaIdAlways(), joints, false);
for (size_t i = 0; i < x658_collisionManager->GetNumCollisionActors(); ++i) {
const auto& info = x658_collisionManager->GetCollisionDescFromIndex(i);
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(info.GetCollisionActorId())) {
if (info.GetName() == "lockon_target_LCTR"sv) {
x706_lockOnTargetCollider = info.GetCollisionActorId();
}
}
}
SetLockOnTargetHealthAndDamageVulns(mgr);
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(
{EMaterialTypes::Solid}, {EMaterialTypes::CollisionActor, EMaterialTypes::Player, EMaterialTypes::Character}));
AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr);
}
} // namespace urde::MP1

View File

@ -0,0 +1,111 @@
#pragma once
#include "Runtime/Collision/CJointCollisionDescription.hpp"
#include "Runtime/MP1/World/CShockWave.hpp"
#include "Runtime/World/CPathFindSearch.hpp"
#include "Runtime/World/CPatterned.hpp"
namespace urde {
class CCollisionActorManager;
namespace MP1 {
class CMetroidPrimeEssence : public CPatterned {
TCachedToken<CGenDescription> x568_;
CPathFindSearch x574_searchPath;
std::unique_ptr<CCollisionActorManager> x658_collisionManager;
std::unique_ptr<CElementGen> x65c_;
CAssetId x660_;
CAssetId x664_;
zeus::CTransform x668_;
CDamageInfo x698_;
zeus::CVector3f x6b4_;
float x6c0_ = 0.f;
float x6c4_ = 0.f;
float x6c8_ = 0.f;
float x6cc_ = 4.f;
float x6d0_ = 0.9f * x6cc_ + x6cc_;
float x6d4_ = 0.f;
u32 x6d8_ = 0;
u32 x6dc_ = 0;
u32 x6e0_ = x6dc_;
u32 x6e4_ = 0;
u32 x6e8_ = 2;
u32 x6ec_ = 4;
u32 x6f0_ = 0;
u32 x6f4_ = x6e8_ - 1;
u32 x6f8_ = 2;
u32 x6fc_ = 0;
u32 x700_ = 1;
TUniqueId x704_ = kInvalidUniqueId;
TUniqueId x706_lockOnTargetCollider = kInvalidUniqueId;
CSfxHandle x708_;
s16 x70c_;
bool x70e_24_ : 1 = false;
bool x70e_25_ : 1 = true;
bool x70e_26_ : 1 = false;
bool x70e_27_ : 1 = false;
bool x70e_28_ : 1 = true;
bool x70e_29_ : 1 = false;
bool x70e_30_ : 1 = false;
bool x70e_31_ : 1 = false;
void sub8027cb40(const zeus::CVector3f& vec);
void sub8027cce0(CStateManager& mgr);
zeus::CTransform GetTargetTransform(CStateManager& mgr);
void sub8027ce5c(float f1);
void sub8027cee0(CStateManager& mgr);
u32 sub8027cfd4(CStateManager& mgr, u32 w1);
void DoPhaseTransition(CStateManager& mgr);
u32 sub8027d428() { return 2; }
void ShakeCamera(CStateManager& mgr, float f1);
void sub8027d52c(CStateManager& mgr, const SShockWaveData& shockWaveData);
CRayCastResult sub8027d704(CStateManager& mgr);
void sub8027d790(CStateManager& mgr, bool active);
void sub8027d824(CStateManager& mgr);
bool sub8027e870(const zeus::CTransform& xf, CStateManager& mgr);
void sub8027ee88(CStateManager& mgr);
void CountListeningAi(CStateManager& mgr);
void UpdatePhase(float dt, CStateManager& mgr);
void UpdateHealth(CStateManager& mgr);
void SetLockOnTargetHealthAndDamageVulns(CStateManager& mgr);
void AddSphereCollisions(SSphereJointInfo* info, size_t count, std::vector<CJointCollisionDescription>& vecOut);
void SetupCollisionActorManager(CStateManager& mgr);
public:
DEFINE_PATTERNED(MetroidPrimeEssence);
CMetroidPrimeEssence(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms,
CAssetId particle1, const CDamageInfo& dInfo, float f1, CAssetId electric, u32 w1,
CAssetId particle2);
void Think(float dt, CStateManager& mgr) override;
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId other, CStateManager& mgr) override;
void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) override;
void AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) override;
void Render(CStateManager& mgr) override;
zeus::CVector3f GetAimPosition(const CStateManager& mgr, float dt) const override;
void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override;
void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) override;
void Dead(CStateManager& mgr, EStateMsg msg, float dt) override;
void PathFind(CStateManager& mgr, EStateMsg msg, float dt) override;
void Halt(CStateManager& mgr, EStateMsg msg, float dt) override;
void Generate(CStateManager& mgr, EStateMsg msg, float dt) override;
void JumpBack(CStateManager& mgr, EStateMsg msg, float dt) override;
void Skid(CStateManager& mgr, EStateMsg msg, float dt) override;
void FadeIn(CStateManager& mgr, EStateMsg msg, float dt) override;
void FadeOut(CStateManager& mgr, EStateMsg msg, float dt) override;
void Taunt(CStateManager& mgr, EStateMsg msg, float dt) override;
void TelegraphAttack(CStateManager& mgr, EStateMsg msg, float dt) override;
void Dodge(CStateManager& mgr, EStateMsg msg, float dt) override;
void PathFindEx(CStateManager& mgr, EStateMsg msg, float dt) override;
bool HasPatrolPath(CStateManager& mgr, float dt) override;
bool ShouldAttack(CStateManager& mgr, float dt) override;
bool InPosition(CStateManager& mgr, float dt) override;
bool CoverFind(CStateManager& mgr, float dt) override;
bool ShouldTaunt(CStateManager& mgr, float dt) override;
bool ShouldCrouch(CStateManager& mgr, float dt) override;
bool ShouldMove(CStateManager& mgr, float dt) override;
CPathFindSearch* GetSearchPath() override;
};
} // namespace MP1
} // namespace urde

View File

@ -428,8 +428,8 @@ void CScriptPlayerActor::Render(CStateManager& mgr) {
const float radius = zeus::clamp(0.25f, (6.f - vecFromCam.magnitude()) / 6.f, 2.f);
const float offsetX = std::sin(x34c_phazonOffsetAngle);
const float offsetY = std::sin(x34c_phazonOffsetAngle) * 0.5f;
g_Renderer->DrawPhazonSuitIndirectEffect(zeus::CColor(0.1f, 1.f), x338_phazonIndirectTexture, zeus::skWhite,
radius, 0.05f, offsetX, offsetY);
//g_Renderer->DrawPhazonSuitIndirectEffect(zeus::CColor(0.1f, 1.f), x338_phazonIndirectTexture, zeus::skWhite,
// radius, 0.05f, offsetX, offsetY);
}
}

View File

@ -31,6 +31,7 @@
#include "Runtime/MP1/World/CDrone.hpp"
#include "Runtime/MP1/World/CMetroid.hpp"
#include "Runtime/MP1/World/CMetroidBeta.hpp"
#include "Runtime/MP1/World/CMetroidPrimeEssence.hpp"
#include "Runtime/MP1/World/CMetroidPrimeRelay.hpp"
#include "Runtime/MP1/World/CNewIntroBoss.hpp"
#include "Runtime/MP1/World/COmegaPirate.hpp"
@ -3693,10 +3694,32 @@ CEntity* ScriptLoader::LoadWorldLightFader(CStateManager& mgr, CInputStream& in,
0.f, zeus::skZero2f, false, active, 0.f, 0.f, f1, f2);
}
CEntity* ScriptLoader::LoadMetroidPrimeStage2(CStateManager& mgr, CInputStream& in, int propCount,
const CEntityInfo& info) {
return nullptr;
}
CEntity* ScriptLoader::LoadMetroidPrimeEssence(CStateManager& mgr, CInputStream& in, int propCount,
const CEntityInfo& info) {
if (!EnsurePropertyCount(propCount, 11, "MetroidPrimeEssence")) {
return nullptr;
}
SScaledActorHead aHead = LoadScaledActorHead(in, mgr);
auto [valid, pInfoPropCount] = CPatternedInfo::HasCorrectParameterCount(in);
if (!valid) {
return nullptr;
}
CPatternedInfo pInfo{in, pInfoPropCount};
CActorParameters actParms = LoadActorParameters(in);
CAssetId particle1{in};
CDamageInfo dInfo{in};
CAssetId electric{in};
u32 w3 = in.readUint32Big();
CAssetId particle2{in};
const CAnimationParameters& animParms = pInfo.GetAnimationParameters();
CModelData mData{CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), aHead.x40_scale,
animParms.GetInitialAnimation(), true)};
return new MP1::CMetroidPrimeEssence(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform,
std::move(mData), pInfo, actParms, particle1, dInfo, aHead.x40_scale.y(),
electric, w3, particle2);
};
CEntity* ScriptLoader::LoadMetroidPrimeStage1(CStateManager& mgr, CInputStream& in, int propCount,
const CEntityInfo& info) {

View File

@ -154,7 +154,7 @@ public:
static CEntity* LoadBurrower(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info);
static CEntity* LoadBeam(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info);
static CEntity* LoadWorldLightFader(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info);
static CEntity* LoadMetroidPrimeStage2(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info);
static CEntity* LoadMetroidPrimeEssence(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info);
static CEntity* LoadMetroidPrimeStage1(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info);
static CEntity* LoadMazeNode(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info);
static CEntity* LoadOmegaPirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info);