#include "Runtime/MP1/World/COmegaPirate.hpp" #include "Runtime/Camera/CGameCamera.hpp" #include "Runtime/Collision/CCollisionActor.hpp" #include "Runtime/Collision/CCollisionActorManager.hpp" #include "Runtime/Collision/CGameCollision.hpp" #include "Runtime/CSimplePool.hpp" #include "Runtime/GameGlobalObjects.hpp" #include "Runtime/Graphics/CCubeRenderer.hpp" #include "Runtime/Weapon/CGameProjectile.hpp" #include "Runtime/World/CPlayer.hpp" #include "Runtime/World/CScriptEffect.hpp" #include "Runtime/World/CScriptPlatform.hpp" #include "Runtime/World/CScriptSound.hpp" #include "Runtime/World/CScriptWaypoint.hpp" #include "Runtime/World/CWorld.hpp" #include "TCastTo.hpp" // Generated file, do not modify include path namespace metaforce::MP1 { namespace { constexpr std::array skSphereJoints{{ {"lockon_target_LCTR", 1.f}, }}; constexpr std::array skObbJoints{{ {"Spine_2", "Collar", zeus::skOne3f}, {"R_toe_1", "R_ankle", zeus::skOne3f}, {"L_toe_1", "L_ankle", zeus::skOne3f}, {"R_knee", "R_ankle", zeus::skOne3f}, {"L_knee", "L_ankle", zeus::skOne3f}, {"R_elbow", "R_wrist", zeus::skOne3f}, {"L_elbow", "L_wrist", zeus::skOne3f}, {"R_wrist", "R_index_1", zeus::skOne3f}, {"L_wrist", "L_index_1", zeus::skOne3f}, {"R_index_1", "R_index_3_SDK", zeus::CVector3f{2.f}}, {"L_index_1", "L_index_3_SDK", zeus::CVector3f{2.f}}, }}; } // namespace COmegaPirate::CFlash::CFlash(TUniqueId uid, const CEntityInfo& info, const zeus::CVector3f& pos, TLockedToken& thermalSpot, float delay) : CActor(uid, true, "Omega Pirate Flash", info, zeus::CTransform::Translate(pos), CModelData::CModelDataNull(), {}, CActorParameters::None(), kInvalidUniqueId) , xf4_delay(delay) , m_thermalSpotAdd(EFilterType::Add, thermalSpot) , m_thermalSpotSubtract(EFilterType::Subtract, thermalSpot) {} void COmegaPirate::CFlash::Accept(IVisitor& visitor) { visitor.Visit(this); } void COmegaPirate::CFlash::Think(float dt, CStateManager& mgr) { CEntity::Think(dt, mgr); xf4_delay -= dt; if (xf4_delay > 0.f) { return; } xf8_time += dt; float intensity = xf8_time; if (intensity <= 0.75f) { intensity /= 0.75f; } else { intensity = 1.f - (intensity - 0.75f) / 0.25f; } const CGameCamera* const camera = mgr.GetCameraManager()->GetCurrentCamera(mgr); const zeus::CVector3f dist = (GetTranslation() - camera->GetTranslation()).normalized(); float dot = dist.dot(camera->GetTransform().frontVector()); float dVar4 = 0.f; if (dot >= 0.f) { dVar4 = dot * dot; } xfc_size = dVar4 * intensity; if (xf8_time > 1.f) { mgr.FreeScriptObject(GetUniqueId()); } } void COmegaPirate::CFlash::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { mgr.RenderLast(GetUniqueId()); // if (xf0_thermalSpot == nullptr && xe8_thermalSpotToken.IsLocked() && xe8_thermalSpotToken.HasReference()) { // xf0_thermalSpot = xe8_thermalSpotToken.GetObj(); // } } void COmegaPirate::CFlash::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) {} void COmegaPirate::CFlash::Render(CStateManager& mgr) { const CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr); if (visor == CPlayerState::EPlayerVisor::Thermal) { return; } float sizeMul = 35.f; CTexturedQuadFilter* filter = nullptr; if (visor == CPlayerState::EPlayerVisor::XRay) { // CGraphics::SetBlendMode(ERglBlendMode::Subtract, ERglBlendFactor::One, ERglBlendFactor::Zero, // ERglLogicOp::Clear); filter = &m_thermalSpotSubtract; sizeMul = 60.f; } else { // CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, // ERglLogicOp::Clear); filter = &m_thermalSpotAdd; } float size = xfc_size * sizeMul; const auto rightVec = size * CGraphics::g_ViewMatrix.rightVector(); const auto upVec = size * CGraphics::g_ViewMatrix.upVector(); const auto rvS = GetTranslation() - rightVec; const auto rvP = GetTranslation() + rightVec; CGraphics::SetModelMatrix(zeus::CTransform()); const std::array verts{{ {rvS + upVec, {0.f, 0.f}}, {rvP + upVec, {0.f, 1.f}}, {rvS - upVec, {1.f, 0.f}}, {rvP - upVec, {1.f, 1.f}}, }}; filter->drawVerts(zeus::CColor{1.f, std::min(1.f, size)}, verts); } COmegaPirate::COmegaPirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, CElitePirateData data, CAssetId skeletonModelId, CAssetId skeletonSkinRulesId, CAssetId skeletonLayoutInfoId) : CElitePirate(uid, name, info, xf, std::move(mData), pInfo, actParms, data) , x9d0_initialScale(GetModelData()->GetScale()) , x9f0_skeletonModel(*g_SimplePool, skeletonModelId, skeletonSkinRulesId, skeletonLayoutInfoId) , xb70_thermalSpot(g_SimplePool->GetObj("Thermal_Spot_2"sv)) { x9a4_scriptWaypointPlatforms.reserve(3); x9b8_scriptEffects.reserve(24); x9dc_scriptPlatforms.reserve(4); xaa0_scriptSounds.reserve(4); xab4_.reserve(3); xb7c_.resize(4, 0); SetMass(100000.f); CMaterialFilter filter = GetMaterialFilter(); filter.ExcludeList().Add( CMaterialList{EMaterialTypes::Character, EMaterialTypes::CollisionActor, EMaterialTypes::Platform}); SetMaterialFilter(filter); GetSearchPath()->SetPadding(20.f); } void COmegaPirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { switch (msg) { default: CElitePirate::AcceptScriptMsg(msg, uid, mgr); break; case EScriptObjectMessage::Activate: CElitePirate::AcceptScriptMsg(msg, uid, mgr); xa38_collisionActorMgr1->SetActive(mgr, true); xa9c_collisionActorMgr2->SetActive(mgr, true); GetKnockBackController().SetAutoResetImpulse(false); if (auto* entity = mgr.ObjectById(x990_launcherId2)) { entity->SetActive(true); } break; case EScriptObjectMessage::Deactivate: CElitePirate::AcceptScriptMsg(msg, uid, mgr); xa38_collisionActorMgr1->SetActive(mgr, false); xa9c_collisionActorMgr2->SetActive(mgr, false); if (auto* entity = mgr.ObjectById(x990_launcherId2)) { entity->SetActive(false); } break; case EScriptObjectMessage::Decrement: x9ec_decrement = true; break; case EScriptObjectMessage::Increment: SetShotAt(true, mgr); break; case EScriptObjectMessage::Open: xb7c_[3] -= xb7c_[3] == 0 ? 0 : 1; break; case EScriptObjectMessage::Reset: xb78_codeTrigger = true; break; case EScriptObjectMessage::SetToMax: xa3c_hearPlayer = true; break; case EScriptObjectMessage::SetToZero: xb7c_[2] -= xb7c_[2] == 0 ? 0 : 1; break; case EScriptObjectMessage::Start: x3b4_speed = 1.f; ++xade_armorPiecesDestroyed; if (xade_armorPiecesDestroyed < 4) { GetBodyController()->GetCommandMgr().DeliverCmd(CBCKnockBackCmd(zeus::skLeft, pas::ESeverity::One)); } break; case EScriptObjectMessage::Stop: DeathDestroy(mgr); break; case EScriptObjectMessage::StopAndReset: xb7c_[1] -= xb7c_[1] == 0 ? 0 : 1; break; case EScriptObjectMessage::UNKM18: xb7c_[0] -= xb7c_[0] == 0 ? 0 : 1; break; case EScriptObjectMessage::Action: x3b4_speed = 1.f; ++xade_armorPiecesDestroyed; if (xade_armorPiecesDestroyed < 4) { GetBodyController()->GetCommandMgr().DeliverCmd(CBCKnockBackCmd(zeus::skRight, pas::ESeverity::One)); } break; case EScriptObjectMessage::Alert: CElitePirate::AcceptScriptMsg(msg, uid, mgr); break; case EScriptObjectMessage::Touched: CElitePirate::AcceptScriptMsg(msg, uid, mgr); if (uid == x990_launcherId2 && x990_launcherId2 != kInvalidUniqueId) { SetShotAt(true, mgr); } if (const TCastToConstPtr actor = mgr.ObjectById(uid)) { if (const TCastToConstPtr player = mgr.ObjectById(actor->GetLastTouchedObject())) { if (x420_curDamageRemTime <= 0.f) { mgr.ApplyDamage(GetUniqueId(), player->GetUniqueId(), GetUniqueId(), GetContactDamage(), CMaterialFilter::MakeInclude({EMaterialTypes::Solid}), zeus::skZero3f); x420_curDamageRemTime = x424_damageWaitTime; } } } break; case EScriptObjectMessage::Registered: CElitePirate::AcceptScriptMsg(msg, uid, mgr); x990_launcherId2 = mgr.AllocateUniqueId(); CreateGrenadeLauncher(mgr, x990_launcherId2); SetupCollisionManager(mgr); GetBodyController()->SetLocomotionType(pas::ELocomotionType::Internal8); x402_27_noXrayModel = false; xa4c_initialXf = x34_transform; xa98_maxEnergy = HealthInfo(mgr)->GetHP(); if (auto* actor = static_cast(mgr.ObjectById(GetLauncherId()))) { actor->RemoveMaterial(EMaterialTypes::Scannable, mgr); } if (auto* actor = static_cast(mgr.ObjectById(x990_launcherId2))) { actor->RemoveMaterial(EMaterialTypes::Scannable, mgr); } GetKnockBackController().SetAutoResetImpulse(false); SetupPathFindSearch(); break; case EScriptObjectMessage::Deleted: CElitePirate::AcceptScriptMsg(msg, uid, mgr); xa38_collisionActorMgr1->Destroy(mgr); xa9c_collisionActorMgr2->Destroy(mgr); mgr.FreeScriptObject(x990_launcherId2); break; case EScriptObjectMessage::InitializedInArea: CElitePirate::AcceptScriptMsg(msg, uid, mgr); for (const SConnection& conn : GetConnectionList()) { TUniqueId connId = mgr.GetIdForScript(conn.x8_objId); if (connId == kInvalidUniqueId || conn.x0_state != EScriptObjectState::Attack) { continue; } if (conn.x4_msg == EScriptObjectMessage::Activate) { if (const TCastToConstPtr effect = mgr.ObjectById(connId)) { x9b8_scriptEffects.emplace_back(connId, effect->GetName()); } else if (TCastToPtr platform = mgr.ObjectById(connId)) { x9dc_scriptPlatforms.emplace_back(connId, platform->GetName()); platform->AddMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, EMaterialTypes::Character, mgr); platform->RemoveMaterial(EMaterialTypes::Scannable, mgr); CMaterialList excludes = platform->GetMaterialFilter().GetExcludeList(); excludes.Add({EMaterialTypes::Player, EMaterialTypes::Character, EMaterialTypes::CollisionActor}); CMaterialList includes = GetMaterialFilter().GetIncludeList(); platform->SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(includes, excludes)); xae4_platformVuln = *platform->GetDamageVulnerability(); xb54_platformColor = platform->GetDrawFlags().x4_color; } else if (const TCastToConstPtr sound = mgr.ObjectById(connId)) { xaa0_scriptSounds.emplace_back(connId, sound->GetName()); } } else if (conn.x4_msg == EScriptObjectMessage::Follow) { if (const TCastToConstPtr waypoint = mgr.ObjectById(connId)) { std::vector waypointPlatformIds; waypointPlatformIds.reserve(3); for (const SConnection& waypointConn : waypoint->GetConnectionList()) { auto waypointConnId = mgr.GetIdForScript(waypointConn.x8_objId); if (TCastToPtr platform = mgr.ObjectById(waypointConnId)) { platform->AddMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); waypointPlatformIds.push_back(waypointConnId); } } x9a4_scriptWaypointPlatforms.emplace_back(connId, waypointPlatformIds); } } } break; case EScriptObjectMessage::Damage: if (uid == x990_launcherId2 && x990_launcherId2 != kInvalidUniqueId) { GetBodyController()->GetCommandMgr().DeliverCmd( CBCKnockBackCmd(GetTransform().frontVector(), pas::ESeverity::Eight)); } CElitePirate::AcceptScriptMsg(msg, uid, mgr); if (uid == xa46_ && xa7c_xrayAlphaState == EXRayFadeState::WaitForTrigger) { xa7c_xrayAlphaState = EXRayFadeState::FadeOut; xa84_xrayAlphaStateTime = 0.f; } break; case EScriptObjectMessage::InvulnDamage: if (const TCastToConstPtr projectile = mgr.GetObjectById(uid)) { if (xa4a_heartVisible) { mgr.ApplyDamage(uid, xa46_, projectile->GetOwnerId(), projectile->GetDamageInfo(), CMaterialFilter::MakeInclude({EMaterialTypes::Solid}), zeus::skZero3f); } } SetShotAt(true, mgr); } } bool COmegaPirate::AggressionCheck(CStateManager& mgr, float arg) { return x990_launcherId2 == kInvalidUniqueId && CElitePirate::AggressionCheck(mgr, arg); } void COmegaPirate::Attack(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { x402_28_isMakingBigStrike = true; x504_damageDur = 1.f; } else if (msg == EStateMsg::Deactivate) { x402_28_isMakingBigStrike = false; x504_damageDur = 0.f; } CElitePirate::Attack(mgr, msg, dt); } bool COmegaPirate::CodeTrigger(CStateManager&, float) { return xb78_codeTrigger; } void COmegaPirate::Cover(CStateManager& mgr, EStateMsg msg, float dt) { CElitePirate::Cover(mgr, msg, dt); if (msg == EStateMsg::Activate) { xad4_cachedSpeed = x3b4_speed; xad8_cover = true; } else if (msg == EStateMsg::Deactivate) { xad8_cover = false; } } bool COmegaPirate::CoverBlown(CStateManager&, float) { if (x9b4_lostAllHp) { x9b4_lostAllHp = false; xb5c_hpLost = 0.f; return true; } return false; } void COmegaPirate::Dizzy(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { xa44_targetable = true; } else if (msg == EStateMsg::Update) { GetBodyController()->GetCommandMgr().DeliverCmd(CBCLoopReactionCmd(pas::EReactionType::Two)); } else if (msg == EStateMsg::Deactivate) { GetBodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState)); } } void COmegaPirate::DoubleSnap(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); SetShotAt(false, mgr); SetState(EState::Zero); xa44_targetable = false; xa4a_heartVisible = false; xa88_xrayFadeInTrigger = false; xa8c_xrayFadeOutTime = 3.f; for (auto& entry : x9dc_scriptPlatforms) { if (auto* platform = static_cast(mgr.ObjectById(entry.first))) { platform->SetActive(true); platform->SetDamageVulnerability(xae4_platformVuln); platform->AddMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr); platform->SetDisableXRayAlpha(false); platform->SetXRayFog(true); } } xb64_stateTime = 17.f; AddMaterial(EMaterialTypes::Scannable, mgr); } else if (msg == EStateMsg::Update) { if (GetState() == EState::Zero) { if (GetBodyController()->GetCurrentStateId() == pas::EAnimationState::Step) { SetState(EState::Two); } else { GetBodyController()->GetCommandMgr().DeliverCmd( CBCStepCmd(pas::EStepDirection::Backward, pas::EStepType::BreakDodge)); } } else if (GetState() == EState::Two && GetBodyController()->GetCurrentStateId() != pas::EAnimationState::Step) { SetState(EState::Over); } } else if (msg == EStateMsg::Deactivate) { if (auto* launcher = static_cast(mgr.ObjectById(GetLauncherId()))) { launcher->SetFollowPlayer(true); } if (auto* launcher = static_cast(mgr.ObjectById(x990_launcherId2))) { launcher->SetFollowPlayer(true); } } } void COmegaPirate::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { switch (type) { case EUserEventType::EggLay: if (x990_launcherId2 != kInvalidUniqueId) { if (auto* entity = mgr.ObjectById(x990_launcherId2)) { mgr.SendScriptMsg(entity, GetUniqueId(), EScriptObjectMessage::Action); } } break; case EUserEventType::FadeIn: x9a1_fadeIn = true; break; case EUserEventType::FadeOut: if (x994_normalFadeState != ENormalFadeState::Two && x9a1_fadeIn) { x994_normalFadeState = ENormalFadeState::One; xa30_skeletonFadeState = ESkeletonFadeState::FadeIn; } break; case EUserEventType::ObjectPickUp: xab4_.clear(); xac8_ = 0; ++xacc_; if (xac4_ == 0) { sub_8028cbec(2, mgr); } else if (xac4_ == 1) { sub_8028cbec(1, mgr); sub_8028cbec(1, mgr); } else if (xac4_ == 2) { sub_8028cbec(2, mgr); sub_8028cbec(1, mgr); } else if (xac4_ == 3) { sub_8028cbec(1, mgr); sub_8028cbec(1, mgr); sub_8028cbec(1, mgr); } SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); break; case EUserEventType::Projectile: case EUserEventType::DamageOn: case EUserEventType::DamageOff: case EUserEventType::ScreenShake: case EUserEventType::BeginAction: case EUserEventType::BecomeShootThrough: default: CElitePirate::DoUserAnimEvent(mgr, node, type, dt); } } void COmegaPirate::Enraged(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { SetState(EState::Zero); } else if (msg == EStateMsg::Update) { if (GetState() == EState::Zero) { if (GetBodyController()->GetCurrentStateId() == pas::EAnimationState::Taunt) { SetState(EState::Two); } else { GetBodyController()->GetCommandMgr().DeliverCmd(CBCTauntCmd(pas::ETauntType::Zero)); } } else if (GetState() == EState::Two && GetBodyController()->GetCurrentStateId() != pas::EAnimationState::Taunt) { SetState(EState::Over); } } else if (msg == EStateMsg::Deactivate) { xadf_launcher1FollowPlayer = true; xae0_launcher2FollowPlayer = true; } } void COmegaPirate::Explode(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { SetState(EState::Zero); xad0_scaleUpTrigger = false; } else if (msg == EStateMsg::Update) { if (GetState() == EState::Zero) { if (GetBodyController()->GetCurrentStateId() == pas::EAnimationState::Step) { SetState(EState::Two); } else { GetBodyController()->GetCommandMgr().DeliverCmd( CBCStepCmd(pas::EStepDirection::Forward, pas::EStepType::Dodge)); } } else if (GetState() == EState::Two && GetBodyController()->GetCurrentStateId() != pas::EAnimationState::Step) { SetState(EState::Over); } } else if (msg == EStateMsg::Deactivate) { GetBodyController()->SetLocomotionType(xa40_locomotionType); } } void COmegaPirate::Faint(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { GetBodyController()->GetCommandMgr().DeliverCmd(CBCLoopReactionCmd(pas::EReactionType::Zero)); xa44_targetable = true; xa4a_heartVisible = true; if (xa7c_xrayAlphaState == EXRayFadeState::WaitForTrigger) { xa8c_xrayFadeOutTime = 0.333f; } for (const auto& entry : x9dc_scriptPlatforms) { if (auto* platform = static_cast(mgr.ObjectById(entry.first))) { platform->SetActive(true); } } } else if (msg == EStateMsg::Update) { if (xb4c_armorPiecesHealed < 4 && x9c8_scaleState == EScaleState::None && xb58_healTime >= 2.5f) { float alpha = std::min(xb50_armorPieceHealTime, 1.f); float invAlpha = 1.f - alpha; size_t idx = 0; for (const auto& entry : x9dc_scriptPlatforms) { if (auto* platform = static_cast(mgr.ObjectById(entry.first))) { if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) { if (xb4c_armorPiecesHealed > idx) { constexpr CModelFlags flags{5, 0, 3, zeus::skBlack}; platform->SetDrawFlags(flags); } else if (xb4c_armorPiecesHealed == idx) { if (!xb6e_armorPieceActivated) { SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::None); xb6e_armorPieceActivated = true; } const CModelFlags flags{5, 0, 3, zeus::CColor{invAlpha, alpha}}; platform->SetDrawFlags(flags); } } else { constexpr CModelFlags flags{5, 0, 3, zeus::CColor{1.f, 0.f}}; platform->SetDrawFlags(flags); } } ++idx; } if (xb50_armorPieceHealTime > 1.f) { ++xb4c_armorPiecesHealed; xb50_armorPieceHealTime = 0.f; xb58_healTime = 0.f; xb6e_armorPieceActivated = false; } xb50_armorPieceHealTime += dt; } xb58_healTime += dt; GetBodyController()->GetCommandMgr().DeliverCmd(CBCLoopReactionCmd(pas::EReactionType::Zero)); } else if (msg == EStateMsg::Deactivate) { GetBodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState)); if (xb58_healTime >= 2.5f) { ++xb4c_armorPiecesHealed; } } } void COmegaPirate::Growth(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { x9c8_scaleState = EScaleState::ScaleDownY; xad0_scaleUpTrigger = false; RemoveMaterial(EMaterialTypes::RadarObject, EMaterialTypes::Scannable, mgr); xb6c_exit1Sent = false; xb6d_exit2Sent = false; ProcessSoundEvent(SFXsfx0B27, 1.f, 0, 0.1f, 1000.f, 0.16f, 1.f, zeus::skZero3f, GetTranslation(), mgr.GetNextAreaId(), mgr, false); } else if (msg == EStateMsg::Update) { if (xb68_ == 0) { if (x330_stateMachineState.GetTime() > 0.3f * xb64_stateTime && !xb6c_exit1Sent) { SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::None); xb6c_exit1Sent = true; } if (x330_stateMachineState.GetTime() > 0.6f * xb64_stateTime && !xb6d_exit2Sent) { SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::None); xb6d_exit2Sent = true; } } else if (x330_stateMachineState.GetTime() > 0.5f * xb64_stateTime && !xb6c_exit1Sent) { SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::None); xb6c_exit1Sent = true; } } else if (msg == EStateMsg::Deactivate) { TeleportToFurthestPlatform(mgr); xad0_scaleUpTrigger = true; AddMaterial(EMaterialTypes::RadarObject, mgr); ProcessSoundEvent(SFXsfx0B28, 1.f, 0, 0.1f, 1000.f, 0.16f, 1.f, zeus::skZero3f, GetTranslation(), mgr.GetNextAreaId(), mgr, false); } } void COmegaPirate::JumpBack(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { SetShotAt(false, mgr); SetState(EState::Two); xade_armorPiecesDestroyed = 0; xadf_launcher1FollowPlayer = false; xae0_launcher2FollowPlayer = false; xb68_ = 0; xa40_locomotionType = GetBodyController()->GetLocomotionType(); GetBodyController()->SetLocomotionType(pas::ELocomotionType::Internal5); GetBodyController()->GetCommandMgr().DeliverCmd( CBCKnockBackCmd(GetTransform().frontVector(), pas::ESeverity::Five)); for (const auto& entry : x9dc_scriptPlatforms) { if (auto* platform = static_cast(mgr.ObjectById(entry.first))) { platform->SetActive(false); } } } else if (msg == EStateMsg::Update) { if (GetState() == EState::Two && GetBodyController()->GetCurrentStateId() != pas::EAnimationState::KnockBack) { SetState(EState::Over); } } } bool COmegaPirate::Landed(CStateManager& mgr, float arg) { return xb4c_armorPiecesHealed == 4; } zeus::CVector3f COmegaPirate::GetOrbitPosition(const CStateManager& mgr) const { if (x990_launcherId2 != kInvalidUniqueId && mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal) { if (const auto* actor = static_cast(mgr.GetObjectById(x990_launcherId2))) { return GetLockOnPosition(actor); } } return CElitePirate::GetOrbitPosition(mgr); } bool COmegaPirate::HearPlayer(CStateManager& mgr, float arg) { return xa3c_hearPlayer; } void COmegaPirate::PathFind(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { xad4_cachedSpeed = x3b4_speed; x3b4_speed = 1.4f * xad4_cachedSpeed; } else if (msg == EStateMsg::Update) { if (GetBodyController()->GetCurrentStateId() == pas::EAnimationState::KnockBack) { x3b4_speed = xad4_cachedSpeed; } else if (xad4_cachedSpeed == x3b4_speed) { x3b4_speed = 1.4f * xad4_cachedSpeed; } } else if (msg == EStateMsg::Deactivate) { x3b4_speed = xad4_cachedSpeed; } CElitePirate::PathFind(mgr, msg, dt); } void COmegaPirate::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { CElitePirate::PreRender(mgr, frustum); if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay) { xb4_drawFlags = CModelFlags{1, 0, 3, zeus::CColor{xa80_xrayAlpha}}; } } void COmegaPirate::Render(CStateManager& mgr) { auto* mData = GetModelData(); auto* animData = mData->GetAnimationData(); CGraphics::SetModelMatrix(GetTransform() * zeus::CTransform::Scale(mData->GetScale())); if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay && xa2c_skeletonAlpha > 0.f) { const CModelFlags flags{5, 0, 3, zeus::CColor{1.f, xa2c_skeletonAlpha}}; animData->Render(x9f0_skeletonModel, flags, std::nullopt, nullptr); } if (x9a0_visible) { bool isXRay = mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay; if (isXRay) { g_Renderer->SetWorldFog(ERglFogMode::None, 0.f, 1.f, zeus::skBlack); const CModelFlags flags{5, 0, 1, zeus::CColor{1.f, 0.2f}}; auto& model = *animData->GetModelData().GetObj(); animData->Render(model, flags, std::nullopt, nullptr); } CPatterned::Render(mgr); if (isXRay) { mgr.SetupFogForArea(GetAreaIdAlways()); } } } void COmegaPirate::Retreat(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { SetShotAt(false, mgr); SetState(EState::Zero); SendScriptMsgs(EScriptObjectState::Inside, mgr, EScriptObjectMessage::None); xad0_scaleUpTrigger = false; xa44_targetable = false; xa4a_heartVisible = false; xb5c_hpLost = 0.f; xb60_hpLostInPhase = 0.f; xb64_stateTime = 5.f; ++xb68_; } else if (msg == EStateMsg::Update) { if (GetState() == EState::Zero) { if (GetBodyController()->GetCurrentStateId() == pas::EAnimationState::Step) { SetState(EState::Two); } else { GetBodyController()->GetCommandMgr().DeliverCmd( CBCStepCmd(pas::EStepDirection::Forward, pas::EStepType::BreakDodge)); } } else if (GetState() == EState::Two && GetBodyController()->GetCurrentStateId() != pas::EAnimationState::Step) { SetState(EState::Over); } } } void COmegaPirate::Run(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { xad4_cachedSpeed = x3b4_speed; x3b4_speed = 1.4f * xad4_cachedSpeed; } else if (msg == EStateMsg::Update) { if (GetBodyController()->GetCurrentStateId() == pas::EAnimationState::KnockBack) { x3b4_speed = xad4_cachedSpeed; } else if (xad4_cachedSpeed == x3b4_speed) { x3b4_speed = 1.4f * xad4_cachedSpeed; } } else if (msg == EStateMsg::Deactivate) { x3b4_speed = xad4_cachedSpeed; } CElitePirate::Run(mgr, msg, dt); } bool COmegaPirate::ShotAt(CStateManager& mgr, float arg) { return CElitePirate::ShotAt(mgr, arg); } bool COmegaPirate::ShouldCallForBackup(CStateManager& mgr, float arg) { if (CElitePirate::ShouldCallForBackup(mgr, arg)) { return ShouldCallForBackupFromLauncher(mgr, x990_launcherId2); } return false; } bool COmegaPirate::ShouldFire(CStateManager& mgr, float arg) { if (CElitePirate::ShouldFire(mgr, arg)) { return ShouldFireFromLauncher(mgr, x990_launcherId2); } return false; } bool COmegaPirate::ShouldMove(CStateManager& mgr, float arg) { return xb64_stateTime < x330_stateMachineState.GetTime(); } void COmegaPirate::Shuffle(CStateManager& mgr, EStateMsg msg, float dt) {} void COmegaPirate::Skid(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { SetState(EState::Zero); } else if (msg == EStateMsg::Update) { if (GetState() == EState::Zero) { if (GetBodyController()->GetCurrentStateId() == pas::EAnimationState::Step) { SetState(EState::Two); } else { GetBodyController()->GetCommandMgr().DeliverCmd( CBCStepCmd(pas::EStepDirection::Forward, pas::EStepType::Normal)); } } else if (GetState() == EState::Two && GetBodyController()->GetCurrentStateId() != pas::EAnimationState::Step) { SetState(EState::Over); } } } void COmegaPirate::Suck(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { SetState(EState::Zero); xa7c_xrayAlphaState = EXRayFadeState::FadeOut; xa88_xrayFadeInTrigger = true; } else if (msg == EStateMsg::Update) { if (GetState() == EState::Zero) { if (GetBodyController()->GetCurrentStateId() == pas::EAnimationState::Step) { SetState(EState::Two); } else { GetBodyController()->GetCommandMgr().DeliverCmd( CBCStepCmd(pas::EStepDirection::Backward, pas::EStepType::Normal)); GetBodyController()->SetLocomotionType(pas::ELocomotionType::Relaxed); } } else if (GetState() == EState::Two && GetBodyController()->GetCurrentStateId() != pas::EAnimationState::Step) { SetState(EState::Over); } } else if (msg == EStateMsg::Deactivate) { for (const auto& entry : x9dc_scriptPlatforms) { if (auto* platform = static_cast(mgr.ObjectById(entry.first))) { platform->SetDamageVulnerability(CDamageVulnerability::ImmuneVulnerabilty()); platform->RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); platform->SetDisableXRayAlpha(true); CModelFlags flags{5, 0, 3, zeus::CColor{1.f, 0.f}}; platform->SetDrawFlags(flags); platform->SetXRayFog(false); } } xb50_armorPieceHealTime = 0.f; xb58_healTime = 2.5f; xb4c_armorPiecesHealed = 0; } } void COmegaPirate::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { xad4_cachedSpeed = x3b4_speed; x3b4_speed = 1.4f * xad4_cachedSpeed; } else if (msg == EStateMsg::Update) { if (GetBodyController()->GetCurrentStateId() == pas::EAnimationState::KnockBack) { x3b4_speed = xad4_cachedSpeed; } else if (xad4_cachedSpeed == x3b4_speed) { x3b4_speed = 1.4f * xad4_cachedSpeed; } } else if (msg == EStateMsg::Deactivate) { x3b4_speed = xad4_cachedSpeed; } CElitePirate::TargetPatrol(mgr, msg, dt); } void COmegaPirate::Think(float dt, CStateManager& mgr) { if (!GetActive()) { return; } SetAlert(true); CElitePirate::Think(dt, mgr); { float maxHealth = xa98_maxEnergy; CHealthInfo* healthInfo = HealthInfo(mgr); if (healthInfo->GetHP() > 0.2f * maxHealth) { if (healthInfo->GetHP() > 0.7f * maxHealth) { if (xacc_ > 4) { xac4_ = 1; } } else { xac4_ = 2; } } else { xac4_ = 3; } } UpdateActorTransform(mgr, x990_launcherId2, "grenadeLauncher2_LCTR"sv); UpdateNormalAlpha(mgr, dt); UpdateSkeletonAlpha(mgr, dt); UpdateXRayAlpha(mgr, dt); if ((!x9a1_fadeIn || xa4a_heartVisible) && mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay && xa44_targetable) { AddMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); if (x9c8_scaleState == EScaleState::WaitForTrigger) { xa38_collisionActorMgr1->SetActive(mgr, false); xa9c_collisionActorMgr2->SetActive(mgr, false); } else { xa38_collisionActorMgr1->SetActive(mgr, true); xa9c_collisionActorMgr2->SetActive(mgr, true); if (auto* entity = mgr.ObjectById(xa48_)) { entity->SetActive(false); } } } else { RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); xa38_collisionActorMgr1->SetActive(mgr, false); if (x9a1_fadeIn) { xa9c_collisionActorMgr2->SetActive(mgr, true); if (auto* entity = mgr.ObjectById(xa48_)) { entity->SetActive(true); } } else { xa9c_collisionActorMgr2->SetActive(mgr, false); if (auto* entity = mgr.ObjectById(xa48_)) { entity->SetActive(false); } } } UpdateScale(mgr, dt); xa38_collisionActorMgr1->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); xa9c_collisionActorMgr2->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); if (auto* entity = static_cast(mgr.ObjectById(xa46_))) { float hp = GetHealthInfo(mgr)->GetHP(); *HealthInfo(mgr) = *entity->GetHealthInfo(mgr); float hpChange = hp - GetHealthInfo(mgr)->GetHP(); xb5c_hpLost += hpChange; xb60_hpLostInPhase += hpChange; } if (GetHealthInfo(mgr)->GetHP() > 0.f) { if (xb5c_hpLost > 100.f) { x9b4_lostAllHp = true; } else { if (xb60_hpLostInPhase > 20.f) { GetBodyController()->GetCommandMgr().DeliverCmd( CBCAdditiveReactionCmd(pas::EAdditiveReactionType::One, 1.f, false)); xb60_hpLostInPhase = 0.f; } } } else { DeathDestroy(mgr); } sub_8028c704(mgr, dt); for (auto& entry : x9dc_scriptPlatforms) { auto* platform = static_cast(mgr.ObjectById(entry.first)); if ((!xb78_codeTrigger && !xb79_bossPhaseActive) || xa4a_heartVisible) { platform->RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); } else { platform->AddMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); } } { const CPlayerState& playerState = *mgr.GetPlayerState(); CPlayer& player = mgr.GetPlayer(); if (GetCollisionActorManager().GetActive() && playerState.IsFiringComboBeam() && playerState.GetCurrentBeam() == CPlayerState::EBeamId::Wave && xad8_cover) { AddMaterial(EMaterialTypes::Target, mgr); player.ResetAimTargetPrediction(GetUniqueId()); for (auto& entry : x9dc_scriptPlatforms) { if (auto* platform = static_cast(mgr.ObjectById(entry.first))) { platform->RemoveMaterial(EMaterialTypes::Target, mgr); } } player.GetPlayerGun()->GetAuxWeapon().SetNewTarget(GetUniqueId(), mgr); } else if (!xa4a_heartVisible) { RemoveMaterial(EMaterialTypes::Target, mgr); for (auto& entry : x9dc_scriptPlatforms) { if (auto* platform = static_cast(mgr.ObjectById(entry.first))) { platform->AddMaterial(EMaterialTypes::Target, mgr); } } CAuxWeapon& weapon = player.GetPlayerGun()->GetAuxWeapon(); if (weapon.HasTarget(mgr) == GetUniqueId()) { if (player.ValidateOrbitTargetId(player.GetOrbitTargetId(), mgr) == CPlayer::EOrbitValidationResult::OK) { weapon.SetNewTarget(player.GetOrbitTargetId(), mgr); } else { weapon.SetNewTarget(kInvalidUniqueId, mgr); } } } } if (auto* launcher = static_cast(mgr.ObjectById(GetLauncherId()))) { launcher->SetFollowPlayer(xadf_launcher1FollowPlayer); } if (auto* launcher = static_cast(mgr.ObjectById(x990_launcherId2))) { launcher->SetFollowPlayer(xae0_launcher2FollowPlayer); } if (x9ec_decrement) { x9ec_decrement = false; x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "JumpBack"sv); } if (xb68_ > 1) { DoUserAnimEvent(mgr, CInt32POINode{}, EUserEventType::ObjectPickUp, dt); xb68_ = 0; } if (xb8c_avoidStaticCollisionTime > 0.f) { const zeus::CAABox& box = GetBoundingBox(); CGameCollision::AvoidStaticCollisionWithinRadius(mgr, *this, 8, dt, 1.f, 1.5f * (box.max.x() - box.min.x()), 10000.f, 0.25f); xb8c_avoidStaticCollisionTime = 0.f; } xb8c_avoidStaticCollisionTime += dt; } void COmegaPirate::WallDetach(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { SetState(EState::Zero); } else if (msg == EStateMsg::Update) { if (GetState() == EState::Zero) { if (GetBodyController()->GetCurrentStateId() == pas::EAnimationState::Step) { SetState(EState::Two); } else { GetBodyController()->GetCommandMgr().DeliverCmd(CBCStepCmd(pas::EStepDirection::Left, pas::EStepType::Dodge)); } } else if (GetState() == EState::Two && GetBodyController()->GetCurrentStateId() != pas::EAnimationState::Step) { SetState(EState::Over); } } else if (msg == EStateMsg::Deactivate) { mgr.SetBossParams(GetUniqueId(), xa98_maxEnergy, 89); xb79_bossPhaseActive = true; } } void COmegaPirate::WallHang(CStateManager& mgr, EStateMsg msg, float dt) {} void COmegaPirate::SetupHealthInfo(CStateManager& mgr) { CElitePirate::SetupHealthInfo(mgr); SetupLauncherHealthInfo(mgr, x990_launcherId2); } void COmegaPirate::SetLaunchersActive(CStateManager& mgr, bool val) { CElitePirate::SetLaunchersActive(mgr, val); SetLauncherActive(mgr, val, x990_launcherId2); } void COmegaPirate::CreateFlash(CStateManager& mgr, float arg) { mgr.AddObject(new CFlash(mgr.AllocateUniqueId(), CEntityInfo{GetAreaIdAlways(), CEntity::NullConnectionList}, GetRenderBounds().center(), xb70_thermalSpot, arg)); } void COmegaPirate::SetupCollisionManager(CStateManager& mgr) { std::vector sphereJoints; sphereJoints.reserve(skSphereJoints.size()); AddSphereCollisionList(skSphereJoints.data(), skSphereJoints.size(), sphereJoints); xa38_collisionActorMgr1 = std::make_unique(mgr, GetUniqueId(), GetAreaIdAlways(), sphereJoints, true); SetupCollisionActorInfo1(xa38_collisionActorMgr1, mgr); xa46_ = xa38_collisionActorMgr1->GetCollisionDescFromIndex(0).GetCollisionActorId(); if (auto* actor = static_cast(mgr.ObjectById(xa46_))) { *actor->HealthInfo(mgr) = *HealthInfo(mgr); } std::vector obbJoints; obbJoints.reserve(skObbJoints.size()); AddOBBAutoSizeCollisionList(skObbJoints.data(), skObbJoints.size(), obbJoints); xa9c_collisionActorMgr2 = std::make_unique(mgr, GetUniqueId(), GetAreaIdAlways(), obbJoints, true); SetupCollisionActorInfo2(xa9c_collisionActorMgr2, mgr); xa48_ = xa9c_collisionActorMgr2->GetCollisionDescFromIndex(0).GetCollisionActorId(); } void COmegaPirate::AddSphereCollisionList(const SSphereJointInfo* joints, size_t count, std::vector& outJoints) const { const CAnimData* animData = GetModelData()->GetAnimationData(); for (size_t i = 0; i < count; ++i) { const auto& joint = joints[i]; const CSegId seg = animData->GetLocatorSegId(joint.name); if (seg.IsInvalid()) { continue; } outJoints.emplace_back(CJointCollisionDescription::SphereCollision(seg, joint.radius, joint.name, 0.001f)); } } void COmegaPirate::AddOBBAutoSizeCollisionList(const SOBBJointInfo* joints, size_t count, std::vector& outJoints) const { const CAnimData* animData = GetModelData()->GetAnimationData(); for (size_t i = 0; i < count; ++i) { const auto& joint = joints[i]; const CSegId from = animData->GetLocatorSegId(joint.from); const CSegId to = animData->GetLocatorSegId(joint.to); if (to.IsInvalid() || from.IsInvalid()) { continue; } outJoints.emplace_back(CJointCollisionDescription::OBBAutoSizeCollision( from, to, joint.bounds, CJointCollisionDescription::EOrientationType::One, "Omega_Pirate_OBB_"s + std::to_string(i), 0.001f)); } } void COmegaPirate::SetupCollisionActorInfo1(const std::unique_ptr& actMgr, CStateManager& mgr) { for (size_t i = 0; i < actMgr->GetNumCollisionActors(); ++i) { const auto& colDesc = actMgr->GetCollisionDescFromIndex(i); const TUniqueId uid = colDesc.GetCollisionActorId(); if (TCastToPtr act = mgr.ObjectById(uid)) { act->AddMaterial(EMaterialTypes::ScanPassthrough, EMaterialTypes::CameraPassthrough, EMaterialTypes::AIJoint, EMaterialTypes::Immovable, mgr); const CMaterialFilter& selfFilter = GetMaterialFilter(); const CMaterialFilter& actFilter = act->GetMaterialFilter(); CMaterialFilter filter = CMaterialFilter::MakeIncludeExclude(selfFilter.GetIncludeList(), selfFilter.GetExcludeList()); filter.IncludeList().Add(actFilter.GetIncludeList()); filter.ExcludeList().Add(actFilter.GetExcludeList()); filter.ExcludeList().Add(EMaterialTypes::Platform); act->SetMaterialFilter(filter); act->RemoveMaterial(EMaterialTypes::ProjectilePassthrough, mgr); } } } void COmegaPirate::SetupCollisionActorInfo2(const std::unique_ptr& actMgr, CStateManager& mgr) { for (size_t i = 0; i < actMgr->GetNumCollisionActors(); ++i) { const auto& colDesc = actMgr->GetCollisionDescFromIndex(i); const TUniqueId uid = colDesc.GetCollisionActorId(); if (TCastToPtr act = mgr.ObjectById(uid)) { act->AddMaterial(EMaterialTypes::ScanPassthrough, EMaterialTypes::CameraPassthrough, EMaterialTypes::AIJoint, EMaterialTypes::Immovable, mgr); const CMaterialFilter& selfFilter = GetMaterialFilter(); const CMaterialFilter& actFilter = act->GetMaterialFilter(); CMaterialFilter filter = CMaterialFilter::MakeIncludeExclude(selfFilter.GetIncludeList(), selfFilter.GetExcludeList()); filter.IncludeList().Add(actFilter.GetIncludeList()); filter.IncludeList().Add(EMaterialTypes::Player); filter.ExcludeList().Add(actFilter.GetExcludeList()); filter.ExcludeList().Remove(EMaterialTypes::Player); filter.ExcludeList().Add(EMaterialTypes::Platform); act->SetMaterialFilter(filter); act->RemoveMaterial(EMaterialTypes::ProjectilePassthrough, mgr); act->SetDamageVulnerability(CDamageVulnerability::ReflectVulnerabilty()); } } } u8 COmegaPirate::sub_8028bfac() const { std::array arr{0, 0, 0, 0}; for (const auto i : xab4_) { ++arr[i]; } u8 ret = 0; for (size_t i = 0; i < arr.size(); ++i) { if (xb7c_[i] != 0 || arr[i] != 0) { ++ret; } } return ret; } void COmegaPirate::sub_8028cbec(u32 arg, CStateManager& mgr) { int i = mgr.GetActiveRandom()->Next() % 4; u32 v = 3 - (xab4_.size() + sub_8028c230()); u32 ct = std::min(arg, v); if (sub_8028bfac() < 2) { for (u32 n = 0; n < ct; ++n) { xab4_.push_back(i); } } else { sub_8028c840(ct, mgr); } } u8 COmegaPirate::sub_8028c230() const { return xb7c_[0] + xb7c_[1] + xb7c_[2] + xb7c_[3]; } void COmegaPirate::sub_8028c840(u32 arg, CStateManager& mgr) { std::array arr{0, 0, 0, 0}; for (const auto i : xab4_) { ++arr[i]; } std::vector vec; for (size_t i = 0; i < arr.size(); ++i) { if (xb7c_[i] != 0 || arr[i] != 0) { vec.push_back(i); } } if (vec.empty()) { sub_8028cbec(arg, mgr); } else { s32 rand = mgr.GetActiveRandom()->Next(); int sz = vec.size(); int val = vec[rand - (rand / sz) * sz]; u32 v = 3 - (xab4_.size() + sub_8028c230()); u32 ct = std::min(arg, v); for (u32 n = 0; n < ct; ++n) { xab4_.push_back(val); } } } void COmegaPirate::TeleportToFurthestPlatform(CStateManager& mgr) { size_t waypointIdx = 0; float maxDist = 0.f; zeus::CVector3f pos; for (size_t i = 0; i < x9a4_scriptWaypointPlatforms.size(); ++i) { const auto& entry = x9a4_scriptWaypointPlatforms[i]; if (const TCastToConstPtr waypoint = mgr.GetObjectById(entry.first)) { const auto waypointPos = waypoint->GetTranslation(); const float dist = (mgr.GetPlayer().GetTranslation() - waypointPos).magnitude(); if (dist > maxDist && waypoint->GetUniqueId() != xada_lastWaypointId) { waypointIdx = i; maxDist = dist; pos = waypointPos; } } } SetTranslation(FindGround(pos, mgr)); auto waypointId = x9a4_scriptWaypointPlatforms[waypointIdx].first; xada_lastWaypointId = waypointId; if (TCastToPtr waypoint = mgr.ObjectById(waypointId)) { waypoint->SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); } const zeus::CVector2f distXY = (mgr.GetPlayer().GetTranslation().toVec2f() - GetTranslation().toVec2f()).normalized(); const zeus::CVector2f frontVecXY = GetTransform().frontVector().toVec2f().normalized(); const zeus::CQuaternion quat = zeus::CQuaternion::shortestRotationArc(zeus::CVector3f{frontVecXY, 0.f}, zeus::CVector3f{distXY, 0.f}); SetTransform(zeus::CTransform{GetTransform().basis * zeus::CMatrix3f{quat}, GetTranslation()}); } zeus::CVector3f COmegaPirate::FindGround(const zeus::CVector3f& pos, CStateManager& mgr) const { auto result = mgr.RayStaticIntersection(pos, zeus::skDown, 30.f, CMaterialFilter::MakeInclude(EMaterialTypes::Solid)); return result.IsValid() ? result.GetPoint() : pos; } void COmegaPirate::UpdateNormalAlpha(CStateManager& mgr, float dt) { if (x994_normalFadeState == ENormalFadeState::One) { x99c_normalAlpha = 1.f - std::min(x998_normalFadeTime, 1.25f) / 1.25f; x42c_color.a() = x99c_normalAlpha; if (x998_normalFadeTime > 1.25f) { x994_normalFadeState = ENormalFadeState::Two; x9a1_fadeIn = false; x998_normalFadeTime = 0.f; } x998_normalFadeTime += dt; x9a0_visible = true; } else if (x994_normalFadeState == ENormalFadeState::Two) { x99c_normalAlpha = 0.f; if (x998_normalFadeTime > 1.5f && x9a1_fadeIn) { CreateFlash(mgr, 0.f); x994_normalFadeState = ENormalFadeState::Three; x998_normalFadeTime = 0.f; } x998_normalFadeTime += dt; x9a0_visible = false; } else if (x994_normalFadeState == ENormalFadeState::Three) { x99c_normalAlpha = std::min(x998_normalFadeTime, 1.f) / 1.25f; if (x998_normalFadeTime > 1.f) { x994_normalFadeState = ENormalFadeState::Zero; x998_normalFadeTime = 0.f; } x998_normalFadeTime += dt; x9a0_visible = true; } else { x99c_normalAlpha = 1.f; x9a0_visible = true; } float alpha = x99c_normalAlpha; if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) { alpha = 0.f; x99c_normalAlpha = 1.f; x9a0_visible = true; } x42c_color.a() = x99c_normalAlpha; if (alpha >= 1.f) { if (auto* launcher = static_cast(mgr.ObjectById(GetLauncherId()))) { launcher->SetVisible(true); launcher->SetAddColor(zeus::CColor{0.f}); } if (auto* launcher = static_cast(mgr.ObjectById(x990_launcherId2))) { launcher->SetVisible(true); launcher->SetAddColor(zeus::CColor{0.f}); } } else { if (auto* launcher = static_cast(mgr.ObjectById(GetLauncherId()))) { launcher->SetAddColor(zeus::CColor{1.f, alpha}); launcher->SetVisible(alpha != 0.f); } if (auto* launcher = static_cast(mgr.ObjectById(x990_launcherId2))) { launcher->SetAddColor(zeus::CColor{1.f, alpha}); launcher->SetVisible(alpha != 0.f); } } } void COmegaPirate::sub_8028c704(CStateManager& mgr, float dt) { int idx = xac8_; if (idx >= xab4_.size()) { return; } if (xab0_ <= 0.f) { ++xac8_; int val = xab4_[idx]; if (val == 0) { SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::None); xb7c_[0]++; } else if (val == 1) { SendScriptMsgs(EScriptObjectState::Open, mgr, EScriptObjectMessage::None); xb7c_[1]++; } else if (val == 2) { SendScriptMsgs(EScriptObjectState::CloseIn, mgr, EScriptObjectMessage::None); xb7c_[2]++; } else if (val == 3) { SendScriptMsgs(EScriptObjectState::Modify, mgr, EScriptObjectMessage::None); xb7c_[3]++; } xab0_ = 1.5f; } xab0_ -= dt; } void COmegaPirate::UpdateXRayAlpha(CStateManager& mgr, float dt) { if (xa7c_xrayAlphaState == EXRayFadeState::FadeIn) { xa80_xrayAlpha = std::min(xa84_xrayAlphaStateTime, xa90_xrayFadeInTime) / xa90_xrayFadeInTime; if (xa84_xrayAlphaStateTime > xa90_xrayFadeInTime) { xa7c_xrayAlphaState = EXRayFadeState::None; xa84_xrayAlphaStateTime = 0.f; } xa84_xrayAlphaStateTime += dt; } else if (xa7c_xrayAlphaState == EXRayFadeState::WaitForTrigger) { xa80_xrayAlpha = 0.f; if ((xa94_xrayFadeTriggerTime < xa84_xrayAlphaStateTime) && !xa88_xrayFadeInTrigger) { xa7c_xrayAlphaState = EXRayFadeState::FadeIn; xa84_xrayAlphaStateTime = 0.f; } xa84_xrayAlphaStateTime += dt; } else if (xa7c_xrayAlphaState == EXRayFadeState::FadeOut) { xa80_xrayAlpha = 1.f - std::min(xa84_xrayAlphaStateTime, xa8c_xrayFadeOutTime) / xa8c_xrayFadeOutTime; if (xa84_xrayAlphaStateTime > xa8c_xrayFadeOutTime) { xa7c_xrayAlphaState = EXRayFadeState::WaitForTrigger; xa84_xrayAlphaStateTime = 0.f; } xa84_xrayAlphaStateTime += dt; } else { xa80_xrayAlpha = 1.f; } } void COmegaPirate::UpdateScale(CStateManager& mgr, float dt) { auto* modelData = GetModelData(); zeus::CVector3f scale = modelData->GetScale(); switch (x9c8_scaleState) { case EScaleState::None: default: return; case EScaleState::ScaleDownX: scale.x() = x9d0_initialScale.x() * std::min(1.f, 0.005f + (1.f - std::min(x9cc_scaleTime, 0.25f) / 0.25f)); if (x9cc_scaleTime > 0.25f) { x9c8_scaleState = EScaleState::ScaleDownZ; x9cc_scaleTime = 0.f; } x9cc_scaleTime += dt; break; case EScaleState::ScaleDownY: scale.y() = x9d0_initialScale.y() * std::min(1.f, 0.005f + (1.f - std::min(x9cc_scaleTime, 0.25f) / 0.25f)); if (x9cc_scaleTime > 0.25f) { x9c8_scaleState = EScaleState::ScaleDownX; x9cc_scaleTime = 0.f; } x9cc_scaleTime += dt; break; case EScaleState::ScaleDownZ: scale.z() = x9d0_initialScale.z() * std::min(1.f, 0.005f + (1.f - std::min(x9cc_scaleTime, 0.25f) / 0.25f)); if (x9cc_scaleTime > 0.25f) { x9c8_scaleState = EScaleState::WaitForTrigger; x9cc_scaleTime = 0.f; } x9cc_scaleTime += dt; break; case EScaleState::WaitForTrigger: if (x9cc_scaleTime > 0.1f && xad0_scaleUpTrigger) { x9c8_scaleState = EScaleState::ScaleUpZ; x9cc_scaleTime = 0.f; } x9cc_scaleTime += dt; break; case EScaleState::ScaleUpX: scale.x() = x9d0_initialScale.x() * std::min(1.f, 0.005f + std::min(x9cc_scaleTime, 0.25f) / 0.25f); if (x9cc_scaleTime > 0.25f) { x9c8_scaleState = EScaleState::ScaleUpY; x9cc_scaleTime = 0.f; } x9cc_scaleTime += dt; break; case EScaleState::ScaleUpY: scale.y() = x9d0_initialScale.y() * std::min(1.f, 0.005f + std::min(x9cc_scaleTime, 0.25f) / 0.25f); if (x9cc_scaleTime > 0.25f) { x9c8_scaleState = EScaleState::None; x9cc_scaleTime = 0.f; } x9cc_scaleTime += dt; break; case EScaleState::ScaleUpZ: scale.z() = x9d0_initialScale.z() * std::min(1.f, 0.005f + std::min(x9cc_scaleTime, 0.25f) / 0.25f); if (x9cc_scaleTime > 0.25f) { x9c8_scaleState = EScaleState::ScaleUpX; x9cc_scaleTime = 0.f; } x9cc_scaleTime += dt; break; } modelData->SetScale(scale); if (auto* launcher = static_cast(mgr.ObjectById(GetLauncherId()))) { launcher->GetModelData()->SetScale(scale); } if (auto* launcher = static_cast(mgr.ObjectById(x990_launcherId2))) { launcher->GetModelData()->SetScale(scale); } for (const auto& entry : x9dc_scriptPlatforms) { if (auto* platform = static_cast(mgr.ObjectById(entry.first))) { platform->GetModelData()->SetScale(scale); } } } void COmegaPirate::UpdateSkeletonAlpha(CStateManager& mgr, float dt) { if (xa30_skeletonFadeState == ESkeletonFadeState::FadeOut) { xa2c_skeletonAlpha = 1.f - std::min(xa34_skeletonStateTime, 1.f); if (xa34_skeletonStateTime > 1.f) { xa30_skeletonFadeState = ESkeletonFadeState::None; xa34_skeletonStateTime = 0.f; } xa34_skeletonStateTime += dt; } else if (xa30_skeletonFadeState == ESkeletonFadeState::Flash) { xa2c_skeletonAlpha = 1.f; if (xa34_skeletonStateTime > 1.f) { xa30_skeletonFadeState = ESkeletonFadeState::FadeOut; xa34_skeletonStateTime = 0.f; CreateFlash(mgr, 0.75f); } xa34_skeletonStateTime += dt; } else if (xa30_skeletonFadeState == ESkeletonFadeState::FadeIn) { xa2c_skeletonAlpha = std::min(xa34_skeletonStateTime, 1.f); if (xa34_skeletonStateTime > 1.f) { xa30_skeletonFadeState = ESkeletonFadeState::Flash; xa34_skeletonStateTime = 0.f; } xa34_skeletonStateTime += dt; } else { xa2c_skeletonAlpha = 0.f; } } void COmegaPirate::DeathDestroy(CStateManager& mgr) { RemoveEmitter(); SetTransform(xa4c_initialXf); x9a1_fadeIn = true; xa4a_heartVisible = false; SendScriptMsgs(EScriptObjectState::DeathRattle, mgr, EScriptObjectMessage::None); SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); SendScriptMsgs(EScriptObjectState::Inside, mgr, EScriptObjectMessage::None); for (auto& entry : x9dc_scriptPlatforms) { if (auto* platform = static_cast(mgr.ObjectById(entry.first))) { platform->SetActive(false); platform->RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); mgr.FreeScriptObject(entry.first); } } x9dc_scriptPlatforms.clear(); if (auto* launcher = static_cast(mgr.ObjectById(GetLauncherId()))) { launcher->SetActive(false); } if (auto* launcher = static_cast(mgr.ObjectById(x990_launcherId2))) { launcher->SetActive(false); } SetActive(false); mgr.SetBossParams(kInvalidUniqueId, 0.f, 89); xa38_collisionActorMgr1->SetActive(mgr, false); xa9c_collisionActorMgr2->SetActive(mgr, false); } } // namespace metaforce::MP1