#include "Runtime/MP1/World/CFlaahgraTentacle.hpp" #include #include "Runtime/CStateManager.hpp" #include "Runtime/Collision/CCollisionActor.hpp" #include "Runtime/World/CPlayer.hpp" #include "Runtime/World/CScriptTrigger.hpp" #include "TCastTo.hpp" // Generated file, do not modify include path namespace metaforce::MP1 { namespace { constexpr std::string_view skpTentacleTip = "Arm_12"sv; constexpr std::array skJointList{{ {"Arm_8", 2.f}, {"Arm_10", 1.2f}, {"Arm_12", 1.2f}, }}; } // Anonymous namespace CFlaahgraTentacle::CFlaahgraTentacle(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms) : CPatterned(ECharacter::FlaahgraTentacle, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, EMovementType::Flyer, EColliderType::One, EBodyType::Restricted, actParms, EKnockBackVariant::Large) { GetActorLights()->SetCastShadows(false); x460_knockBackController.SetAutoResetImpulse(false); CreateShadow(false); } void CFlaahgraTentacle::Accept(IVisitor& visitor) { visitor.Visit(this); } void CFlaahgraTentacle::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { switch (msg) { case EScriptObjectMessage::Registered: { x450_bodyController->Activate(mgr); SetupCollisionManager(mgr); break; } case EScriptObjectMessage::Deleted: { x56c_collisionManager->Destroy(mgr); if (const TCastToPtr trigger = mgr.ObjectById(x58c_triggerId)) { trigger->SetForceVector(x580_forceVector); } break; } case EScriptObjectMessage::Touched: { if (const TCastToConstPtr colAct = mgr.GetObjectById(uid)) { if (colAct->GetLastTouchedObject() == mgr.GetPlayer().GetUniqueId() && x420_curDamageRemTime <= 0.f) { mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), GetContactDamage(), CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); x420_curDamageRemTime = x424_damageWaitTime; } } break; } case EScriptObjectMessage::Play: { x578_ = 0.04f; break; } case EScriptObjectMessage::Deactivate: { DeathDelete(mgr); break; } case EScriptObjectMessage::Open: { ExtractTentacle(mgr); break; } case EScriptObjectMessage::Close: { RetractTentacle(mgr); break; } case EScriptObjectMessage::InitializedInArea: { SaveBombSlotInfo(mgr); break; } default: break; } CPatterned::AcceptScriptMsg(msg, uid, mgr); } void CFlaahgraTentacle::Think(float dt, CStateManager& mgr) { if (!GetActive()) { return; } CPatterned::Think(dt, mgr); x56c_collisionManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); if (x574_ > 0.f) { x574_ -= dt; } if (x578_ > 0.f) { x578_ -= dt; } } void CFlaahgraTentacle::AddSphereCollisionList(const SSphereJointInfo* sphereJoints, size_t jointCount, std::vector& outJoints) { const CAnimData* animData = GetModelData()->GetAnimationData(); for (size_t i = 0; i < jointCount; ++i) { const SSphereJointInfo& sphereJoint = sphereJoints[i]; const CSegId segId = animData->GetLocatorSegId(sphereJoint.name); if (segId.IsInvalid()) { continue; } outJoints.push_back(CJointCollisionDescription::SphereCollision(segId, sphereJoint.radius, sphereJoint.name, 10.f)); } } void CFlaahgraTentacle::SetupCollisionManager(CStateManager& mgr) { std::vector jointList; AddSphereCollisionList(skJointList.data(), skJointList.size(), jointList); x56c_collisionManager = std::make_unique(mgr, GetUniqueId(), GetAreaIdAlways(), jointList, true); for (u32 i = 0; i < x56c_collisionManager->GetNumCollisionActors(); ++i) { const CJointCollisionDescription& desc = x56c_collisionManager->GetCollisionDescFromIndex(i); if (const TCastToPtr colAct = mgr.ObjectById(desc.GetCollisionActorId())) { colAct->SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( {EMaterialTypes::Player}, {EMaterialTypes::Character, EMaterialTypes::CollisionActor, EMaterialTypes::NoStaticCollision, EMaterialTypes::NoPlatformCollision})); colAct->AddMaterial(EMaterialTypes::ScanPassthrough); colAct->SetDamageVulnerability(*GetDamageVulnerability()); if (x57c_tentacleTipAct == kInvalidUniqueId && desc.GetName() == skpTentacleTip) { x57c_tentacleTipAct = desc.GetCollisionActorId(); } } } RemoveMaterial(EMaterialTypes::Solid, EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); AddMaterial(EMaterialTypes::Scannable, mgr); } zeus::CVector3f CFlaahgraTentacle::GetAimPosition(const CStateManager& mgr, float dt) const { if (const TCastToConstPtr colAct = mgr.GetObjectById(x57c_tentacleTipAct)) { return colAct->GetTranslation(); } return CPatterned::GetAimPosition(mgr, dt); } void CFlaahgraTentacle::ExtractTentacle(CStateManager& mgr) { if (!Inside(mgr, 0.f)) { return; } x58e_24_ = true; if (const TCastToPtr trigger = mgr.ObjectById(x58c_triggerId)) { trigger->SetForceVector(x580_forceVector); } } void CFlaahgraTentacle::RetractTentacle(CStateManager& mgr) { x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch); if (const TCastToPtr trigger = mgr.ObjectById(x58c_triggerId)) { trigger->SetForceVector({}); } } void CFlaahgraTentacle::SaveBombSlotInfo(CStateManager& mgr) { for (const SConnection& conn : GetConnectionList()) { if (conn.x0_state != EScriptObjectState::Modify || conn.x4_msg != EScriptObjectMessage::ToggleActive) { continue; } const TUniqueId uid = mgr.GetIdForScript(conn.x8_objId); if (const TCastToConstPtr trigger = mgr.GetObjectById(uid)) { x58c_triggerId = uid; x580_forceVector = trigger->GetForceVector(); return; } } } bool CFlaahgraTentacle::ShouldAttack(CStateManager& mgr, float) { if (x578_ > 0.f) { return true; } if (x574_ > 0.f || mgr.GetPlayer().IsInWaterMovement()) { return false; } if (const TCastToConstPtr colAct = mgr.GetObjectById(x57c_tentacleTipAct)) { const float mag = (mgr.GetPlayer().GetTranslation().toVec2f() - colAct->GetTranslation().toVec2f()).magSquared(); return mag >= (x2fc_minAttackRange * x2fc_minAttackRange) && mag <= (x300_maxAttackRange * x300_maxAttackRange); } return false; } void CFlaahgraTentacle::Attack(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { x568_ = 0; } else if (msg == EStateMsg::Update) { if (x568_ == 0) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::MeleeAttack) { x568_ = 2; } else { x450_bodyController->GetCommandMgr().DeliverCmd( CBCMeleeAttackCmd((x578_ > 0.f ? pas::ESeverity::Zero : pas::ESeverity::One), {})); } } else if (x568_ == 2 && x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::MeleeAttack) { x568_ = 3; } } else if (msg == EStateMsg::Deactivate) { x574_ = (x308_attackTimeVariation * mgr.GetActiveRandom()->Float()) + x304_averageAttackTime; x578_ = 0.f; } } void CFlaahgraTentacle::Retreat(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Update) { if (!x58e_24_) { return; } if (x330_stateMachineState.GetTime() <= 1.f) { return; } if (const TCastToConstPtr trigger = mgr.ObjectById(x58c_triggerId)) { if (!trigger->IsPlayerTriggerProc()) { x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); } } } else if (msg == EStateMsg::Deactivate) { x58e_24_ = false; } } void CFlaahgraTentacle::InActive(CStateManager& mgr, EStateMsg msg, float arg) { if (msg == EStateMsg::Activate) { x570_ = 0.f; } else if (msg == EStateMsg::Update) { if (Inside(mgr, 0.f)) { return; } if (const TCastToConstPtr trigger = mgr.ObjectById(x58c_triggerId)) { if (trigger->IsPlayerTriggerProc()) { if (x570_ > 1.f) { RetractTentacle(mgr); ExtractTentacle(mgr); } else { x570_ += arg; } } } } } void CFlaahgraTentacle::Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) { if (!IsAlive()) { return; } x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "Dead"); if (GetBodyController()->GetPercentageFrozen() > 0.f) { GetBodyController()->UnFreeze(); } x400_25_alive = false; } } // namespace metaforce::MP1