From 05e5fb9774fb3770758752629bee7ca655cbcf2d Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sun, 20 Jan 2019 14:28:25 -0800 Subject: [PATCH] More CBabygoth Imps --- Runtime/Character/CAnimData.hpp | 1 + Runtime/MP1/World/CBabygoth.cpp | 464 ++++++++++++++++++++++++++------ Runtime/MP1/World/CBabygoth.hpp | 45 +++- 3 files changed, 420 insertions(+), 90 deletions(-) diff --git a/Runtime/Character/CAnimData.hpp b/Runtime/Character/CAnimData.hpp index 1a2692800..54bcc82d7 100644 --- a/Runtime/Character/CAnimData.hpp +++ b/Runtime/Character/CAnimData.hpp @@ -234,6 +234,7 @@ public: CParticleDatabase& GetParticleDB() { return x120_particleDB; } void SetParticleCEXTValue(std::string_view name, int idx, float value); + float GetSpeedScale() const { return x200_speedScale; } u32 GetPassedBoolPOICount() const { return x20c_passedBoolCount; } u32 GetPassedIntPOICount() const { return x210_passedIntCount; } u32 GetPassedParticlePOICount() const { return x214_passedParticleCount; } diff --git a/Runtime/MP1/World/CBabygoth.cpp b/Runtime/MP1/World/CBabygoth.cpp index 06e11ff3d..87e0565e0 100644 --- a/Runtime/MP1/World/CBabygoth.cpp +++ b/Runtime/MP1/World/CBabygoth.cpp @@ -19,56 +19,57 @@ namespace urde::MP1 { const std::string_view CBabygoth::skpMouthDamageJoint = "LCTR_SHEMOUTH"sv; + CBabygothData::CBabygothData(CInputStream& in) - : x0_(in.readFloatBig()) - , x4_(in.readFloatBig()) - , x8_(in) - , xc_(in) - , x28_(in) - , x44_(in) - , x48_fireBreathRes(in) - , x4c_fireBreathDamage(in) - , x68_(in) - , xd0_shellVulnerabilities(in) - , x138_(in) - , x13c_(in) - , x140_shellHitPoints(in.readFloatBig()) - , x144_shellCrackSfx(CSfxManager::TranslateSFXID(in.readUint32Big())) - , x148_(in) - , x14c_(in) - , x150_(in) - , x154_(in) - , x158_(CSfxManager::TranslateSFXID(in.readUint32Big())) - , x15a_(CSfxManager::TranslateSFXID(in.readUint32Big())) - , x15c_(CSfxManager::TranslateSFXID(in.readUint32Big())) - , x160_(in.readFloatBig()) - , x164_(in.readFloatBig()) - , x168_(in.readFloatBig()) - , x16c_(in) - , x170_(CSfxManager::TranslateSFXID(in.readUint32Big())) - , x174_(in) {} +: x0_(in.readFloatBig()) +, x4_(in.readFloatBig()) +, x8_(in) +, xc_(in) +, x28_(in) +, x44_(in) +, x48_fireBreathRes(in) +, x4c_fireBreathDamage(in) +, x68_(in) +, xd0_shellVulnerabilities(in) +, x138_(in) +, x13c_(in) +, x140_shellHitPoints(in.readFloatBig()) +, x144_shellCrackSfx(CSfxManager::TranslateSFXID(in.readUint32Big())) +, x148_(in) +, x14c_(in) +, x150_(in) +, x154_(in) +, x158_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, x15a_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, x15c_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, x160_(in.readFloatBig()) +, x164_(in.readFloatBig()) +, x168_(in.readFloatBig()) +, x16c_(in) +, x170_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, x174_(in) {} CBabygoth::CBabygoth(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, const CBabygothData& babyData) - : CPatterned(ECharacter::Babygoth, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Medium) - , x570_babyData(babyData) - , x6ec_(nullptr, 1, pInfo.GetPathfindingIndex(), 1.f, 1.f) - , x7d0_(nullptr, 1, pInfo.GetPathfindingIndex(), 1.f, 1.f) - , x8d0_(x3b4_speed) - , x8f0_boneTracking(*ModelData()->AnimationData(), "Head_1"sv, zeus::degToRad(80.f), zeus::degToRad(180.f), false) - , x930_aabox(GetBoundingBox(), GetMaterialList()) - , x958_(babyData.x8_, babyData.xc_) - , x984_flameThrowerDesc(babyData.x44_.IsValid() ? g_SimplePool->GetObj({SBIG('WPSC'), babyData.x44_}) - : g_SimplePool->GetObj("FlameThrower"sv)) - , x98c_(pInfo.GetDamageVulnerability()) - , xa00_shellHitPoints(babyData.GetShellHitPoints()) { +: CPatterned(ECharacter::Babygoth, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, + EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Medium) +, x570_babyData(babyData) +, x6ec_(nullptr, 1, pInfo.GetPathfindingIndex(), 1.f, 1.f) +, x7d0_(nullptr, 1, pInfo.GetPathfindingIndex(), 1.f, 1.f) +, x8d0_(x3b4_speed) +, x8f0_boneTracking(*ModelData()->AnimationData(), "Head_1"sv, zeus::degToRad(80.f), zeus::degToRad(180.f), false) +, x930_aabox(GetBoundingBox(), GetMaterialList()) +, x958_(babyData.x8_, babyData.xc_) +, x984_flameThrowerDesc(babyData.x44_.IsValid() ? g_SimplePool->GetObj({SBIG('WPSC'), babyData.x44_}) + : g_SimplePool->GetObj("FlameThrower"sv)) +, x98c_(pInfo.GetDamageVulnerability()) +, xa00_shellHitPoints(babyData.GetShellHitPoints()) { TLockedToken model = g_SimplePool->GetObj({SBIG('CMDL'), babyData.x138_}); TLockedToken skin = g_SimplePool->GetObj({SBIG('CSKR'), babyData.x13c_}); - xa08_noShellModel = CToken( - TObjOwnerDerivedFromIObj::GetNewDerivedObject(std::make_unique( - model, skin, x64_modelData->AnimationData()->GetModelData()->GetLayoutInfo(), 1, 1))); + xa08_noShellModel = + CToken(TObjOwnerDerivedFromIObj::GetNewDerivedObject(std::make_unique( + model, skin, x64_modelData->AnimationData()->GetModelData()->GetLayoutInfo(), 1, 1))); xa14_ = g_SimplePool->GetObj({SBIG('PART'), babyData.x14c_}); xa20_ = g_SimplePool->GetObj({SBIG('PART'), babyData.x150_}); xa2c_ = g_SimplePool->GetObj({SBIG('PART'), babyData.x154_}); @@ -82,8 +83,8 @@ CBabygoth::CBabygoth(TUniqueId uid, std::string_view name, const CEntityInfo& in x460_knockBackController.SetEnableShock(true); x460_knockBackController.SetEnableExplodeDeath(true); x8d4_stepBackwardDist = - GetAnimationDistance(CPASAnimParmData(3, CPASAnimParm::FromEnum(1), CPASAnimParm::FromEnum(0))) * - GetModelData()->GetScale().y(); // B_backward_sheegoth + GetAnimationDistance(CPASAnimParmData(3, CPASAnimParm::FromEnum(1), CPASAnimParm::FromEnum(0))) * + GetModelData()->GetScale().y(); // B_backward_sheegoth xa08_noShellModel->SetLayoutInfo(GetModelData()->GetAnimationData()->GetModelData()->GetLayoutInfo()); MakeThermalColdAndHot(); } @@ -99,7 +100,7 @@ void CBabygoth::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateM const CBodyStateInfo& bStateInfo = x450_bodyController->GetBodyStateInfo(); float maxSpeed = bStateInfo.GetMaxSpeed(); x450_bodyController->GetCommandMgr().SetSteeringSpeedRange( - 0.f, maxSpeed <= 0.f ? 1.f : bStateInfo.GetLocomotionSpeed(pas::ELocomotionAnim::Walk) / maxSpeed); + 0.f, maxSpeed <= 0.f ? 1.f : bStateInfo.GetLocomotionSpeed(pas::ELocomotionAnim::Walk) / maxSpeed); x9f4_mouthLocator = GetModelData()->GetAnimationData()->GetLocatorSegId(skpMouthDamageJoint); break; } @@ -193,7 +194,7 @@ void CBabygoth::Think(float dt, CStateManager& mgr) { if (!GetActive()) return; - sub8021ec58(dt, mgr); + AvoidPlayerCollision(dt, mgr); if (xa49_26_) { if (sub8023a180(x6e8_teamMgr, mgr) == 0) sub8021d6e8(mgr); @@ -214,23 +215,57 @@ void CBabygoth::Think(float dt, CStateManager& mgr) { TryToGetUp(mgr); CheckShouldWakeUp(mgr, dt); if (!x400_25_alive && x450_bodyController->GetBodyStateInfo().GetCurrentState()->IsDying()) - ResetProjectileCollision(mgr); + SetProjectilePasshtrough(mgr); } +void CBabygoth::DoUserAnimEvent(urde::CStateManager& mgr, const urde::CInt32POINode& node, EUserEventType type, + float dt) { + switch (type) { + case EUserEventType::Projectile: { + zeus::CTransform xf = GetLctrTransform(node.GetLocatorName()); + zeus::CVector3f plAimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f); + return; + } + case EUserEventType::DamageOn: { + if (xa48_26_) { + if (CFlameThrower* flame = static_cast(mgr.ObjectById(x980_flameThrower))) + flame->Fire(GetTransform(), mgr, false); + } + break; + } + case EUserEventType::DamageOff: { + if (xa48_26_) { + if (CFlameThrower* flame = static_cast(mgr.ObjectById(x980_flameThrower))) + flame->Reset(mgr, false); + } + break; + } + case EUserEventType::BeginAction: { + if (xa48_26_) { + x8f0_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId()); + x8f0_boneTracking.SetActive(true); + } + break; + } + case EUserEventType::ScreenShake: + return; + case EUserEventType::BecomeShootThrough: + SetProjectilePasshtrough(mgr); + return; + default: + break; + } + CPatterned::DoUserAnimEvent(mgr, node, type, dt); +} const SSphereJointInfo CBabygoth::skSphereJointList[skSphereJointCount] = { - {"L_knee", 1.2f}, - {"R_knee", 1.2f}, - {"LCTR_SHEMOUTH", 1.7f}, - {"Pelvis", 1.2f}, - {"butt_LCTR", 0.9f} -}; + {"L_knee", 1.2f}, {"R_knee", 1.2f}, {"LCTR_SHEMOUTH", 1.7f}, {"Pelvis", 1.2f}, {"butt_LCTR", 0.9f}}; void CBabygoth::AddSphereCollisionList(const SSphereJointInfo* sphereJointInfo, s32 jointCount, std::vector& jointList) { for (s32 i = 0; i < jointCount; ++i) { CSegId seg = GetModelData()->GetAnimationData()->GetLocatorSegId(sphereJointInfo[i].name); - jointList.push_back(CJointCollisionDescription::SphereCollision(seg, sphereJointInfo[i].radius, - sphereJointInfo[i].name, 1000.f)); + jointList.push_back( + CJointCollisionDescription::SphereCollision(seg, sphereJointInfo[i].radius, sphereJointInfo[i].name, 1000.f)); } } @@ -254,6 +289,7 @@ void CBabygoth::SetupCollisionManager(CStateManager& mgr) { } SetupHealthInfo(mgr); } + void CBabygoth::SetupHealthInfo(CStateManager& mgr) { CHealthInfo* thisHealth = HealthInfo(mgr); x8ec_ = thisHealth->GetHP(); @@ -276,9 +312,9 @@ void CBabygoth::CreateFlameThrower(CStateManager& mgr) { x980_flameThrower = mgr.AllocateUniqueId(); mgr.AddObject(new CFlameThrower(x984_flameThrowerDesc, "IceSheegoth_Flame"sv, EWeaponType::Plasma, CFlameInfo(6, 4, x570_babyData.GetFireBreathResId(), 15, 0.0625f, 20.f, 1.f), {}, - EMaterialTypes::CollisionActor, x570_babyData.GetFireBreathDamage(), x980_flameThrower, - GetAreaIdAlways(), GetUniqueId(), EProjectileAttrib::None, x570_babyData.x16c_, - x570_babyData.x170_, x570_babyData.x174_)); + EMaterialTypes::CollisionActor, x570_babyData.GetFireBreathDamage(), + x980_flameThrower, GetAreaIdAlways(), GetUniqueId(), EProjectileAttrib::None, + x570_babyData.x16c_, x570_babyData.x170_, x570_babyData.x174_)); } void CBabygoth::ApplyContactDamage(TUniqueId uid, CStateManager& mgr) { @@ -286,7 +322,7 @@ void CBabygoth::ApplyContactDamage(TUniqueId uid, CStateManager& mgr) { if (colAct->GetHealthInfo(mgr)->GetHP() > 0.f && colAct->GetLastTouchedObject() == mgr.GetPlayer().GetUniqueId()) { if (xa48_28_) { mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), x570_babyData.x28_, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); xa48_28_ = false; x420_curDamageRemTime = x424_damageWaitTime; } else if (x420_curDamageRemTime <= 0.f) { @@ -308,13 +344,10 @@ void CBabygoth::RemoveFromTeam(urde::CStateManager& mgr) { } } -void CBabygoth::CrackShell(CStateManager&, const TLockedToken&, const zeus::CTransform&, s16, bool) { +void CBabygoth::ApplySeparationBehavior(CStateManager& mgr) {} +void CBabygoth::CrackShell(CStateManager&, const TLockedToken&, const zeus::CTransform&, s16, bool) {} -} - -void CBabygoth::sub8021d478(CStateManager&, TUniqueId) { - -} +void CBabygoth::sub8021d478(CStateManager&, TUniqueId) {} void CBabygoth::Shock(CStateManager& mgr, float duration, float damage) { if (x9f8_shellIds.empty()) @@ -337,7 +370,11 @@ void CBabygoth::UpdateTouchBounds() { x930_aabox.Box() = bounds; } -void CBabygoth::sub8021ec58(float dt, CStateManager& mgr) { +void CBabygoth::UpdateAttackPosition(CStateManager&, zeus::CVector3f&) {} + +void CBabygoth::sub8021d644(urde::CStateManager&) {} + +void CBabygoth::AvoidPlayerCollision(float dt, CStateManager& mgr) { if (x450_bodyController->GetLocomotionType() == pas::ELocomotionType::Crouch || x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Step) return; @@ -350,8 +387,9 @@ void CBabygoth::sub8021ec58(float dt, CStateManager& mgr) { if (dev->magnitude() > 0.9f * GetModelData()->GetScale().y()) { zeus::CVector3f posDiff = GetTranslation() - pl.GetTranslation(); zeus::CVector3f xpos = GetTransform().transposeRotate( - (posDiff.dot(dev->magnitude() - 0.9f * GetModelData()->GetScale().y() * (*dev).normalized()) / - posDiff.magSquared()) * posDiff); + (posDiff.dot(dev->magnitude() - 0.9f * GetModelData()->GetScale().y() * (*dev).normalized()) / + posDiff.magSquared()) * + posDiff); ApplyImpulseWR(GetMoveToORImpulseWR(xpos, dt), zeus::CAxisAngle::sIdentity); } @@ -359,12 +397,9 @@ void CBabygoth::sub8021ec58(float dt, CStateManager& mgr) { } } -s32 CBabygoth::sub8023a180(TUniqueId, CStateManager&) { - return 0; -} +s32 CBabygoth::sub8023a180(TUniqueId, CStateManager&) { return 0; } -void CBabygoth::sub8021d6e8(CStateManager& mgr) { -} +void CBabygoth::sub8021d6e8(CStateManager& mgr) {} void CBabygoth::sub8021e2c4(float dt) { if (x8d8_ > 0.f) @@ -377,9 +412,7 @@ void CBabygoth::sub8021e2c4(float dt) { x8e8_ += dt; } -void CBabygoth::sub8021e708(CStateManager&) { - -} +void CBabygoth::sub8021e708(CStateManager&) {} void CBabygoth::UpdateParticleEffects(float dt, CStateManager& mgr) { if (CFlameThrower* flame = static_cast(mgr.ObjectById(x980_flameThrower))) { @@ -404,7 +437,7 @@ bool CBabygoth::CheckShouldWakeUp(CStateManager& mgr, float dt) { return xa48_24_isAlert; } -void CBabygoth::ResetProjectileCollision(CStateManager& mgr) { +void CBabygoth::SetProjectilePasshtrough(CStateManager& mgr) { for (u32 i = 0; i < x928_colActMgr->GetNumCollisionActors(); ++i) { const auto& desc = x928_colActMgr->GetCollisionDescFromIndex(i); if (TCastToPtr act = mgr.ObjectById(desc.GetCollisionActorId())) { @@ -413,6 +446,92 @@ void CBabygoth::ResetProjectileCollision(CStateManager& mgr) { } } +void CBabygoth::TurnAround(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + x8f0_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId()); + x8f0_boneTracking.SetActive(true); + UpdateAttackPosition(mgr, x2e0_destPos); + SetPathFindMode(EPathFindMode::Zero); + CPatterned::PathFind(mgr, msg, arg); + x450_bodyController->GetCommandMgr().ClearLocomotionCmds(); + } else if (msg == EStateMsg::Update) { + if (ShouldTurn(mgr, arg)) { + float speed = (GetModelData()->GetAnimationData()->GetSpeedScale() > 0.f + ? 1.f / GetModelData()->GetAnimationData()->GetSpeedScale() + : 0.f); + zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, speed) - GetTranslation(); + if (aimPos.canBeNormalized()) + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd({}, aimPos.normalized(), 1.f)); + } + } else if (msg == EStateMsg::Deactivate) { + x8f0_boneTracking.SetActive(false); + } +} + +void CBabygoth::GetUp(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x568_ = 0; + xa49_24_ = true; + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Getup) + x568_ = 3; + else + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGetupCmd(pas::EGetupType::Zero)); + } else if (x568_ == 3 && x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Getup) + x568_ = 4; + } else if (msg == EStateMsg::Deactivate) { + xa49_24_ = false; + } +} + +void CBabygoth::Enraged(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + xa48_29_ = true; + x568_ = 0; + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Generate) + x568_ = 3; + else + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Three)); + } else if (x568_ == 3 && + x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Generate) + x568_ = 4; + } +} + +void CBabygoth::FollowPattern(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x568_ = (xa49_25_ ? 0 : 4); + xa49_25_ = false; + x8f0_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId()); + x8f0_boneTracking.SetActive(true); + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCStepCmd(pas::EStepDirection::Backward, pas::EStepType::Normal)); + } else if (x568_ == 3) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Step) + x450_bodyController->GetCommandMgr().SetTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); + else + x568_ = 4; + } + } else if (msg == EStateMsg::Deactivate) { + x8f0_boneTracking.SetActive(false); + SetPathFindMode(EPathFindMode::Zero); + } +} + +void CBabygoth::Taunt(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCTauntCmd(pas::ETauntType::One)); + } else if (msg == EStateMsg::Update && + x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Taunt) { + x568_ = 4; + } +} + void CBabygoth::Crouch(CStateManager& mgr, EStateMsg msg, float arg) { if (msg == EStateMsg::Activate) { RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr); @@ -425,4 +544,193 @@ void CBabygoth::Crouch(CStateManager& mgr, EStateMsg msg, float arg) { AddMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr); } } + +void CBabygoth::Deactivate(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x568_ = 1; + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Generate) { + x568_ = 3; + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch); + } + } else if (x568_ == 1) { + if ((x3a0_latestLeashPosition - GetTranslation()).magSquared() > 1.f) + x568_ = 2; + else { + zeus::CVector3f arrivalVec = x45c_steeringBehaviors.Arrival(*this, x3a0_latestLeashPosition, 15.f); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(arrivalVec, {}, 1.f)); + } + } else if (x568_ == 2) { + float angle = zeus::CVector3f::getAngleDiff(GetTranslation(), x8c4_); + if (angle > zeus::degToRad(5.f)) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd({}, x8c4_, 1.f)); + return; + } + x568_ = 0; + } else if (x568_ == 3 && + x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Generate) { + x568_ = 4; + } + } +} + +void CBabygoth::Generate(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x568_ = 0; + x8c4_ = GetTransform().basis[1]; + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Generate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None); + } else { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero)); + } + } else if (x568_ == 3 && + x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Generate) + x568_ = 4; + } +} + +void CBabygoth::TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + xa49_29_ = false; + sub8021d644(mgr); + x400_24_hitByPlayerProjectile = false; + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + if (HasPatrolPath(mgr, 0.f)) { + Patrol(mgr, msg, arg); + UpdateDest(mgr); + } else { + SetDestPos(x3a0_latestLeashPosition); + } + x8b8_ = x2e0_destPos; + if (GetSearchPath()) { + SetPathFindMode(EPathFindMode::Zero); + PathFind(mgr, msg, arg); + } + } else if (msg == EStateMsg::Update) { + if (GetSearchPath() && !PathShagged(mgr, 0.f)) { + SetPathFindMode(EPathFindMode::Zero); + PathFind(mgr, msg, arg); + ApplySeparationBehavior(mgr); + } else { + zeus::CVector3f arrivalVec = x45c_steeringBehaviors.Arrival(*this, x8b8_, 9.f); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(arrivalVec, {}, 1.f)); + } + } +} + +void CBabygoth::Patrol(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Update) + ApplySeparationBehavior(mgr); + + CPatterned::Patrol(mgr, msg, arg); +} + +void CBabygoth::Approach(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + x8f0_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId()); + x8f0_boneTracking.SetActive(true); + UpdateAttackPosition(mgr, x2e0_destPos); + SetPathFindMode(EPathFindMode::Zero); + CPatterned::PathFind(mgr, msg, arg); + if (!xa49_27_) + x450_bodyController->GetCommandMgr().ClearLocomotionCmds(); + xa48_31_ = true; + xa48_28_ = true; + } else if (msg == EStateMsg::Update) { + SetPathFindMode(EPathFindMode::One); + if (xa48_31_) { + x2e0_destPos = x8b8_; + if (x7d0_.FindClosestReachablePoint(GetTranslation(), x2e0_destPos) == CPathFindSearch::EResult::Success && + (x2e0_destPos - GetTranslation()).magSquared() < 10.f) { + x2e0_destPos = GetTranslation(); + } + x8b8_ = x2e0_destPos; + CPatterned::PathFind(mgr, msg, arg); + + if (!xa49_27_) + x450_bodyController->GetCommandMgr().ClearLocomotionCmds(); + + xa48_31_ = true; + } + + xa49_27_ = IsDestinationObstructed(mgr); + if (xa49_27_ && GetSearchPath() && !PathShagged(mgr, 0.f) && + (x7d0_.GetCurrentWaypoint() < x7d0_.GetWaypoints().size() - 1)) { + CPatterned::PathFind(mgr, msg, arg); + ApplySeparationBehavior(mgr); + } else if (ShouldTurn(mgr, 0.f)) { + zeus::CVector3f direction = mgr.GetPlayer().GetTranslation() - GetTranslation(); + if (direction.canBeNormalized()) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(direction.normalized(), {}, 1.f)); + } + } + xa49_27_ = true; + } else if (msg == EStateMsg::Deactivate) { + x8f0_boneTracking.SetActive(false); + SetPathFindMode(EPathFindMode::Zero); + } +} + +void CBabygoth::PathFind(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + xa49_28_ = false; + xa49_26_ = true; + xa48_24_isAlert = false; + x8e8_ = 0.f; + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + x8f0_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId()); + x8f0_boneTracking.SetActive(true); + UpdateAttackPosition(mgr, x2e0_destPos); + x8b8_ = x2e0_destPos; + SetPathFindMode(EPathFindMode::Zero); + CPatterned::PathFind(mgr, msg, arg); + } else if (msg == EStateMsg::Update) { + SetPathFindMode(EPathFindMode::Zero); + if (GetSearchPath() && !PathShagged(mgr, 0.f) && x6ec_.GetCurrentWaypoint() < x6ec_.GetWaypoints().size() - 1) { + CPatterned::PathFind(mgr, msg, arg); + x8e8_ = 0.f; + zeus::CVector3f move = x450_bodyController->GetCommandMgr().GetMoveVector(); + if (move.canBeNormalized()) { + float mag = x45c_steeringBehaviors.Arrival(*this, mgr.GetPlayer().GetTranslation(), 15.f).magnitude(); + x450_bodyController->GetCommandMgr().ClearLocomotionCmds(); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(mag * move.normalized(), {}, 10.f)); + } + ApplySeparationBehavior(mgr); + if (GetTransform().basis[1].magSquared() < 0.f && move.canBeNormalized()) { + x450_bodyController->GetCommandMgr().ClearLocomotionCmds(); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd({}, move.normalized(), 1.f)); + } + } else { + zeus::CVector3f diffPos = mgr.GetPlayer().GetTranslation() - GetTranslation(); + if (diffPos.canBeNormalized()) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd({}, diffPos.normalized(), 1.f)); + } + } + } else if (msg == EStateMsg::Deactivate) { + x8f0_boneTracking.SetActive(false); + } +} + +void CBabygoth::SpecialAttack(CStateManager&, EStateMsg, float) {} + +void CBabygoth::Attack(CStateManager&, EStateMsg, float) {} + +void CBabygoth::ProjectileAttack(CStateManager&, EStateMsg, float) {} + +bool CBabygoth::IsDestinationObstructed(CStateManager& mgr) { + for (auto obj : mgr.GetListeningAiObjectList()) { + if (TCastToPtr ai = obj) { + if (ai->GetAreaIdAlways() == GetAreaIdAlways()) { + if ((x8b8_ - ai->GetTranslation()).magSquared() <= 10.f) + return true; + } + } + } + return false; +} } // namespace urde::MP1 diff --git a/Runtime/MP1/World/CBabygoth.hpp b/Runtime/MP1/World/CBabygoth.hpp index f67e7b285..139601535 100644 --- a/Runtime/MP1/World/CBabygoth.hpp +++ b/Runtime/MP1/World/CBabygoth.hpp @@ -8,7 +8,7 @@ namespace urde { class CCollisionActorManager; class CWeaponDescription; -} +} // namespace urde namespace urde::MP1 { struct CBabygothData { @@ -50,16 +50,14 @@ public: CAssetId GetFireBreathResId() const { return x48_fireBreathRes; } CDamageInfo GetFireBreathDamage() const { return x4c_fireBreathDamage; } const CDamageVulnerability& GetShellDamageVulnerability() const { return xd0_shellVulnerabilities; } - float GetShellHitPoints() const { return x140_shellHitPoints; } + float GetShellHitPoints() const { return x140_shellHitPoints; } s16 GetShellCrackSfx() { return x144_shellCrackSfx; } }; class CBabygoth final : public CPatterned { public: - enum class EPathFindMode { - Zero, - One - }; + enum class EPathFindMode { Zero, One }; + private: static constexpr s32 skSphereJointCount = 5; static const SSphereJointInfo skSphereJointList[skSphereJointCount]; @@ -92,7 +90,7 @@ private: TUniqueId x9f6_ = kInvalidUniqueId; rstl::reserved_vector x9f8_shellIds; float xa00_shellHitPoints; - u32 xa04_ = 1; + u32 xa04_ = 0; TLockedToken xa08_noShellModel; TToken xa14_; TToken xa20_; @@ -123,6 +121,7 @@ private: void CreateFlameThrower(CStateManager&); void ApplyContactDamage(TUniqueId, CStateManager&); void RemoveFromTeam(CStateManager&); + void ApplySeparationBehavior(CStateManager&); bool IsMouthCollisionActor(TUniqueId uid) { return x9f6_ == uid; } bool IsShell(TUniqueId uid) { for (TUniqueId shellId : x9f8_shellIds) { @@ -133,7 +132,7 @@ private: } void CrackShell(CStateManager&, const TLockedToken&, const zeus::CTransform&, s16, bool); void sub8021d478(CStateManager&, TUniqueId); - void sub8021ec58(float, CStateManager&); + void AvoidPlayerCollision(float, CStateManager&); s32 sub8023a180(TUniqueId, CStateManager&); void sub8021d6e8(CStateManager&); void sub8021e2c4(float); @@ -141,8 +140,12 @@ private: void UpdateParticleEffects(float, CStateManager&); void TryToGetUp(CStateManager& mgr); bool CheckShouldWakeUp(CStateManager&, float); - void ResetProjectileCollision(CStateManager&); + void SetProjectilePasshtrough(CStateManager&); void UpdateTouchBounds(); + void UpdateAttackPosition(CStateManager&, zeus::CVector3f&); + void sub8021d644(CStateManager&); + bool IsDestinationObstructed(CStateManager&); + public: DEFINE_PATTERNED(Babygoth) CBabygoth(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, @@ -154,6 +157,7 @@ public: } void Think(float, CStateManager&); + void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt); float GetGravityConstant() const { return 10.f * 24.525f; } void SetPathFindMode(EPathFindMode mode) { x8b4_pathFindMode = mode; } const CCollisionPrimitive* GetCollisionPrimitive() const { return &x930_aabox; } @@ -172,15 +176,32 @@ public: } void Shock(CStateManager&, float, float); + void TurnAround(CStateManager&, EStateMsg, float); + void GetUp(CStateManager&, EStateMsg, float); + void Enraged(CStateManager&, EStateMsg, float); + void FollowPattern(CStateManager&, EStateMsg, float); + void Taunt(CStateManager&, EStateMsg, float); void Crouch(CStateManager&, EStateMsg, float); + void Deactivate(CStateManager&, EStateMsg, float); + void Generate(CStateManager&, EStateMsg, float); + void TargetPatrol(CStateManager&, EStateMsg, float); + void Patrol(CStateManager&, EStateMsg, float); + void Approach(CStateManager&, EStateMsg, float); + void PathFind(CStateManager&, EStateMsg, float); + void SpecialAttack(CStateManager&, EStateMsg, float); + void Attack(CStateManager&, EStateMsg, float); + void ProjectileAttack(CStateManager&, EStateMsg, float); + + bool AnimOver(CStateManager&, float) { return x568_ == 4; } + bool SpotPlayer(CStateManager& mgr, float arg) { if (xa48_24_isAlert) return true; return CPatterned::SpotPlayer(mgr, arg); } - bool InPosition(CStateManager&, float) { - return (x8b8_ - GetTranslation()).magSquared() < 9.f; - } + bool InPosition(CStateManager&, float) { return (x8b8_ - GetTranslation()).magSquared() < 9.f; } + + bool ShotAt(CStateManager&, float) { return x400_24_hitByPlayerProjectile; } }; } // namespace urde::MP1