From 147a9396c4a68905ff1d301d63847c60a2c01ebd Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sun, 30 Dec 2018 19:01:42 -1000 Subject: [PATCH] CBeetle implementation --- DataSpec/DNACommon/PAK.cpp | 7 +- DataSpec/DNACommon/PAK.hpp | 4 - DataSpec/DNAMP1/ScriptObjects/Beetle.hpp | 28 +- DataSpec/DNAMP1/ScriptObjects/Trigger.hpp | 6 +- Runtime/AutoMapper/CAutoMapper.cpp | 9 +- Runtime/CStateManager.cpp | 14 +- Runtime/Character/CBodyStateCmdMgr.hpp | 11 +- Runtime/Character/CharacterCommon.hpp | 2 +- Runtime/MP1/CSamusHud.cpp | 2 + Runtime/MP1/World/CBeetle.cpp | 1002 ++++++++++++++++++++- Runtime/MP1/World/CBeetle.hpp | 110 ++- Runtime/MP1/World/CSpacePirate.cpp | 19 +- Runtime/MP1/World/CSpacePirate.hpp | 9 +- Runtime/World/CAi.hpp | 3 +- Runtime/World/CDamageVulnerability.hpp | 2 +- Runtime/World/CPatterned.cpp | 11 +- Runtime/World/CPatterned.hpp | 7 +- Runtime/World/CTeamAiMgr.cpp | 2 +- Runtime/World/CTeamAiMgr.hpp | 17 +- Runtime/World/ScriptLoader.cpp | 27 +- assetnameparser/CMakeLists.txt | 12 +- hecl | 2 +- 22 files changed, 1214 insertions(+), 92 deletions(-) diff --git a/DataSpec/DNACommon/PAK.cpp b/DataSpec/DNACommon/PAK.cpp index b58fa0622..2bf50a515 100644 --- a/DataSpec/DNACommon/PAK.cpp +++ b/DataSpec/DNACommon/PAK.cpp @@ -382,8 +382,11 @@ std::string PAKRouter::getBestEntryName(const EntryType& entry, bool std::string name; for (const BRIDGETYPE& bridge : *m_bridges) { const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); + const typename BRIDGETYPE::PAKType::Entry* e = pak.lookupEntry(entry.id); + if (!e) + continue; - if (stdOverride && isShared()) { + if (stdOverride && !pak.m_noShare) { if (entry.type == FOURCC('MLVL')) return "!world"; else if (entry.type == FOURCC('MREA')) @@ -411,7 +414,7 @@ std::string PAKRouter::getBestEntryName(const IDType& entry, bool st if (!e) continue; - if (stdOverride && isShared()) { + if (stdOverride && !pak.m_noShare) { if (e->type == FOURCC('MLVL')) return "!world"; else if (e->type == FOURCC('MREA')) diff --git a/DataSpec/DNACommon/PAK.hpp b/DataSpec/DNACommon/PAK.hpp index bd365e06d..b4078fec2 100644 --- a/DataSpec/DNACommon/PAK.hpp +++ b/DataSpec/DNACommon/PAK.hpp @@ -175,10 +175,6 @@ public: hecl::ProjectPath getWorking(const IDType& id, bool silenceWarnings = false) const; hecl::ProjectPath getCooked(const EntryType* entry) const; hecl::ProjectPath getCooked(const IDType& id, bool silenceWarnings = false) const; - bool isShared() const { - const PAKType* pak = m_pak.get(); - return pak ? !pak->m_noShare : false; - } hecl::SystemString getResourceRelativePath(const EntryType& a, const IDType& b) const; diff --git a/DataSpec/DNAMP1/ScriptObjects/Beetle.hpp b/DataSpec/DNAMP1/ScriptObjects/Beetle.hpp index 6f3172b5c..478105242 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Beetle.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Beetle.hpp @@ -9,37 +9,37 @@ struct Beetle : IScriptObject { AT_DECL_DNA_YAML AT_DECL_DNAV String<-1> name; - Value unknown1; + Value flavor; Value location; Value orientation; Value scale; PatternedInfo patternedInfo; ActorParameters actorParameters; - DamageInfo damageInfo; - Value unknown2; - Value unknown3; - DamageVulnerability damageVulnerabilty1; - DamageVulnerability damageVulnerabilty2; - UniqueID32 model; - Value unknown4; - Value unknown5; - Value unknown6; + DamageInfo touchDamage; + Value tailAimReference; + Value unused; + DamageVulnerability tailVuln; + DamageVulnerability platingVuln; + UniqueID32 tailModel; + Value entranceType; + Value initialAttackDelay; + Value retreatTime; void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); } void nameIDs(PAKRouter& pakRouter) const { - if (model) { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); - ent->name = name + "_model"; + if (tailModel) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(tailModel); + ent->name = name + "_tailModel"; } patternedInfo.nameIDs(pakRouter, name + "_patterned"); actorParameters.nameIDs(pakRouter, name + "_actp"); } void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { - g_curSpec->flattenDependencies(model, pathsOut); + g_curSpec->flattenDependencies(tailModel, pathsOut); patternedInfo.depIDs(pathsOut); actorParameters.depIDs(pathsOut, lazyOut); } diff --git a/DataSpec/DNAMP1/ScriptObjects/Trigger.hpp b/DataSpec/DNAMP1/ScriptObjects/Trigger.hpp index 305b3285e..09490121c 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Trigger.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Trigger.hpp @@ -13,10 +13,10 @@ struct Trigger : IScriptObject { Value volume; DamageInfo damageInfo; Value force; - Value unknown; + Value flags; Value active; - Value unknown2; - Value unknown3; + Value deactivateOnEntered; + Value deactivateOnExited; zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const { zeus::CVector3f halfExtent = zeus::CVector3f(volume) / 2.f; diff --git a/Runtime/AutoMapper/CAutoMapper.cpp b/Runtime/AutoMapper/CAutoMapper.cpp index f577b8a70..57c925598 100644 --- a/Runtime/AutoMapper/CAutoMapper.cpp +++ b/Runtime/AutoMapper/CAutoMapper.cpp @@ -228,6 +228,7 @@ void CAutoMapper::UpdateHintNavigation(float dt, const CStateManager& mgr) { xa8_renderStates[2] = xa8_renderStates[0]; xa8_renderStates[1].x20_areaPoint = GetAreaPointOfInterest(mgr, nextStep.x4_areaId); xa8_renderStates[1].ResetInterpolation(); + xa8_renderStates[1].x4c_pointEase = SAutoMapperRenderState::Ease::Linear; ResetInterpolationTimer(2.f * g_tweakAutoMapper->GetHintPanTime()); x1e0_hintSteps.pop_front(); } @@ -238,6 +239,7 @@ void CAutoMapper::UpdateHintNavigation(float dt, const CStateManager& mgr) { xa8_renderStates[2] = xa8_renderStates[0]; xa8_renderStates[1].x20_areaPoint = mwData.GetWorldCenterPoint(); xa8_renderStates[1].ResetInterpolation(); + xa8_renderStates[1].x4c_pointEase = SAutoMapperRenderState::Ease::Linear; ResetInterpolationTimer(2.f * g_tweakAutoMapper->GetHintPanTime()); x1e0_hintSteps.pop_front(); break; @@ -269,7 +271,8 @@ void CAutoMapper::UpdateHintNavigation(float dt, const CStateManager& mgr) { nextStep.x4_float = std::max(0.f, nextStep.x4_float - dt); for (SAutoMapperHintLocation& loc : x1f8_hintLocations) { if (x24_world->IGetWorldAssetId() == loc.x8_worldId && xa0_curAreaId == loc.xc_areaId) { - nextStep.x4_float = 1.f - std::min(nextStep.x4_float / 0.5f, 1.f); + loc.x0_showBeacon = 1; + loc.x4_beaconAlpha = 1.f - std::min(nextStep.x4_float / 0.5f, 1.f); break; } } @@ -1021,9 +1024,9 @@ void CAutoMapper::ProcessControllerInput(const CFinalInput& input, CStateManager if (input.PZ() || input.PB()) { if (x328_ == 0) { - if (CanLeaveMapScreenInternal(mgr)) + if (CanLeaveMapScreenInternal(mgr)) { LeaveMapScreen(mgr); - if (NotHintNavigating()) { + } else if (NotHintNavigating()) { BeginMapperStateTransition(EAutoMapperState::MapScreenUniverse, mgr); x328_ = 1; } diff --git a/Runtime/CStateManager.cpp b/Runtime/CStateManager.cpp index 913639886..e62ddb1d0 100644 --- a/Runtime/CStateManager.cpp +++ b/Runtime/CStateManager.cpp @@ -1871,17 +1871,15 @@ void CStateManager::UpdateHintState(float dt) { void CStateManager::PreThinkObjects(float dt) { if (x84c_player->x9f4_deathTime > 0.f) { x84c_player->DoPreThink(dt, *this); - return; - } - - if (x904_gameState == EGameState::SoftPaused) + } else if (x904_gameState == EGameState::SoftPaused) { for (CEntity* ent : GetAllObjectList()) if (TCastToPtr effect = ent) effect->PreThink(dt, *this); - - for (CEntity* ent : GetAllObjectList()) - if (ent && !GetCameraObjectList().GetObjectById(ent->GetUniqueId())) - ent->PreThink(dt, *this); + } else { + for (CEntity* ent : GetAllObjectList()) + if (ent && !GetCameraObjectList().GetObjectById(ent->GetUniqueId())) + ent->PreThink(dt, *this); + } } void CStateManager::MovePlatforms(float dt) { diff --git a/Runtime/Character/CBodyStateCmdMgr.hpp b/Runtime/Character/CBodyStateCmdMgr.hpp index e301f1d8d..9d0425970 100644 --- a/Runtime/Character/CBodyStateCmdMgr.hpp +++ b/Runtime/Character/CBodyStateCmdMgr.hpp @@ -23,6 +23,8 @@ class CBCMeleeAttackCmd : public CBodyStateCmd { public: CBCMeleeAttackCmd() : CBodyStateCmd(EBodyStateCmd::MeleeAttack) {} CBCMeleeAttackCmd(pas::ESeverity severity) : CBodyStateCmd(EBodyStateCmd::MeleeAttack), x8_severity(severity) {} + CBCMeleeAttackCmd(pas::ESeverity severity, const zeus::CVector3f& target) : CBodyStateCmd(EBodyStateCmd::MeleeAttack) + , x8_severity(severity), xc_targetPos(target), x18_hasTargetPos(true) {} pas::ESeverity GetAttackSeverity() const { return x8_severity; } bool HasAttackTargetPos() const { return x18_hasTargetPos; } const zeus::CVector3f& GetAttackTargetPos() const { return xc_targetPos; } @@ -95,11 +97,16 @@ public: x1c_24_targetTransform = false; x1c_25_overrideAnim = false; } - CBCGenerateCmd(pas::EGenerateType type, s32 animId = -1) - : CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type), x18_animId(animId) { + CBCGenerateCmd(pas::EGenerateType type) + : CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type) { x1c_24_targetTransform = false; x1c_25_overrideAnim = false; } + CBCGenerateCmd(pas::EGenerateType type, s32 animId) + : CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type), x18_animId(animId) { + x1c_24_targetTransform = false; + x1c_25_overrideAnim = animId != -1; + } CBCGenerateCmd(pas::EGenerateType type, const zeus::CVector3f& vec, bool targetTransform = false, bool overrideAnim = false) : CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type), xc_targetPos(vec) { diff --git a/Runtime/Character/CharacterCommon.hpp b/Runtime/Character/CharacterCommon.hpp index eb774b732..ee94632a5 100644 --- a/Runtime/Character/CharacterCommon.hpp +++ b/Runtime/Character/CharacterCommon.hpp @@ -88,7 +88,7 @@ enum class ELoopAttackType { Invalid = -1 }; enum class EGenerateType { Invalid = -1, Zero, One, Two, Three, Four }; -enum class ESlideType { Invalid = -1 }; +enum class ESlideType { Invalid = -1, Zero = 0 }; enum class ETauntType { Invalid = -1, Zero, One, Two }; diff --git a/Runtime/MP1/CSamusHud.cpp b/Runtime/MP1/CSamusHud.cpp index baace315c..5a9bb04dc 100644 --- a/Runtime/MP1/CSamusHud.cpp +++ b/Runtime/MP1/CSamusHud.cpp @@ -1602,6 +1602,8 @@ void CSamusHud::SetMessage(std::u16string_view text, const CHUDMemoParms& info) x558_messageTextTime = info.GetDisplayTime(); if (info.IsHintMemo()) { if (!isWidgetVisible) { + x584_abuttonPulse = 0.f; + x560_messageTextScale = 0.f; CSfxManager::SfxStart(SFXui_show_hint_memo, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); } } else { diff --git a/Runtime/MP1/World/CBeetle.cpp b/Runtime/MP1/World/CBeetle.cpp index 366eda7f2..672d73735 100644 --- a/Runtime/MP1/World/CBeetle.cpp +++ b/Runtime/MP1/World/CBeetle.cpp @@ -1,18 +1,1012 @@ #include "CBeetle.hpp" +#include "CStateManager.hpp" #include "World/CDamageInfo.hpp" #include "Character/CCharLayoutInfo.hpp" #include "TCastTo.hpp" +#include "World/CPatternedInfo.hpp" +#include "Character/CPASAnimParmData.hpp" +#include "World/CTeamAiMgr.hpp" +#include "World/CWorld.hpp" +#include "World/CPlayer.hpp" +#include "World/CScriptWaypoint.hpp" namespace urde::MP1 { CBeetle::CBeetle(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, CPatterned::EFlavorType flavor, - CBeetle::EEntranceType, const CDamageInfo&, const CDamageVulnerability&, const zeus::CVector3f&, float, - float, float, const CDamageVulnerability&, const CActorParameters& aParams, - const std::experimental::optional) + CBeetle::EEntranceType entranceType, const CDamageInfo& touchDamage, + const CDamageVulnerability& platingVuln, const zeus::CVector3f& tailAimReference, + float initialAttackDelay, float retreatTime, float f3, + const CDamageVulnerability& tailVuln, const CActorParameters& aParams, + const std::experimental::optional& tailModel) : CPatterned(ECharacter::Beetle, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Ground, - EColliderType::One, EBodyType::BiPedal, aParams, EKnockBackVariant(flavor)) {} + EColliderType::One, EBodyType::BiPedal, aParams, EKnockBackVariant(flavor)) +, x56c_entranceType(entranceType) +, x574_tailAimReference(tailAimReference) +, x580_f3(f3) +, x584_touchDamage(touchDamage) +, x5ac_tailModel(tailModel ? std::experimental::optional(CModelData(*tailModel)) : + std::experimental::optional()) +, x5fc_pathFindSearch(nullptr, 1, pInfo.GetPathfindingIndex(), 1.f, 1.f) +, x744_platingVuln(platingVuln) +, x7ac_tailVuln(tailVuln) +, x814_attackDelayTimer(initialAttackDelay) +, x834_retreatTime(retreatTime) { + x5a0_headbuttDist = GetAnimationDistance(CPASAnimParmData(7, CPASAnimParm::FromEnum(0), CPASAnimParm::FromEnum(1))); + x5a4_jumpBackwardDist = x64_modelData->GetScale().y() * + GetAnimationDistance(CPASAnimParmData(3, CPASAnimParm::FromEnum(1), CPASAnimParm::FromEnum(0))); + MakeThermalColdAndHot(); + if (x3fc_flavor == EFlavorType::One) + x460_knockBackController.SetLocomotionDuringElectrocution(true); +} void CBeetle::Accept(IVisitor& visitor) { visitor.Visit(this); } +void CBeetle::SquadAdd(CStateManager& mgr) { + if (x570_aiMgr != kInvalidUniqueId) + if (TCastToPtr aimgr = mgr.ObjectById(x570_aiMgr)) + aimgr->AssignTeamAiRole(*this, CTeamAiRole::ETeamAiRole::Melee, + CTeamAiRole::ETeamAiRole::Unknown, CTeamAiRole::ETeamAiRole::Invalid); +} + +void CBeetle::SquadRemove(CStateManager& mgr) { + if (x570_aiMgr != kInvalidUniqueId) + if (TCastToPtr aimgr = mgr.ObjectById(x570_aiMgr)) + if (aimgr->IsPartOfTeam(GetUniqueId())) + aimgr->RemoveTeamAiRole(GetUniqueId()); +} + +void CBeetle::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; + if (CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x570_aiMgr, GetUniqueId())) { + x450_bodyController->SetLocomotionType( + role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Melee ? + pas::ELocomotionType::Lurk : pas::ELocomotionType::Relaxed); + } else { + SquadAdd(mgr); + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); + } + x460_knockBackController.SetAutoResetImpulse(IsOnGround()); + if (x814_attackDelayTimer > 0.f) + x814_attackDelayTimer -= dt; + if ((x824_predictPos - GetTranslation()).toVec2f().magSquared() > 0.1f * dt) + x820_posDeviationCounter += 1; + else + x820_posDeviationCounter = 0; + CPatterned::Think(dt, mgr); + x824_predictPos = x138_velocity * dt + GetTranslation(); +} + +void CBeetle::SetupRetreatPoints(CStateManager& mgr) { + for (const auto& conn : GetConnectionList()) { + if (conn.x0_state == EScriptObjectState::Retreat && conn.x4_msg == EScriptObjectMessage::Follow) { + if (TCastToConstPtr wp = mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))) { + x6e0_retreatPoints.push_back(wp->GetTranslation()); + if (x6e0_retreatPoints.size() == 8) + break; + } + } + } +} + +void CBeetle::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + bool forward = true; + switch (msg) { + case EScriptObjectMessage::Activate: + SquadAdd(mgr); + break; + case EScriptObjectMessage::Deactivate: + case EScriptObjectMessage::Deleted: + SquadRemove(mgr); + break; + case EScriptObjectMessage::OnFloor: + forward = false; + SetMomentumWR(zeus::CVector3f::skZero); + x328_27_onGround = true; + break; + case EScriptObjectMessage::Falling: + if (!x450_bodyController->IsFrozen()) { + SetMomentumWR({0.f, 0.f, -(GetGravityConstant() * xe8_mass)}); + x328_27_onGround = false; + } + forward = false; + break; + case EScriptObjectMessage::InitializedInArea: + if (x570_aiMgr == kInvalidUniqueId) { + x570_aiMgr = CTeamAiMgr::GetTeamAiMgr(*this, mgr); + if (GetActive()) + SquadAdd(mgr); + } + SetupRetreatPoints(mgr); + x5fc_pathFindSearch.SetArea( + mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea); + break; + default: + break; + } + if (forward) + CPatterned::AcceptScriptMsg(msg, sender, mgr); +} + +void CBeetle::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + if (x400_25_alive) { + switch (mgr.GetPlayerState()->GetActiveVisor(mgr)) { + case CPlayerState::EPlayerVisor::XRay: + x42c_color.a() = 76.5f / 255.f; + break; + case CPlayerState::EPlayerVisor::Thermal: + if (x838_25_burrowing) + x42c_color.a() = x830_intoGroundFactor; + else + x42c_color.a() = 1.f; + break; + default: + x42c_color.a() = 1.f; + break; + } + } + CPatterned::PreRender(mgr, frustum); +} + +void CBeetle::Render(const CStateManager& mgr) const { + if (x3fc_flavor == EFlavorType::One && x400_25_alive) { + zeus::CTransform tailXf = GetLctrTransform("Target_Tail"sv); + if (x428_damageCooldownTimer >= 0.f && x42c_color.a() == 1.f) { + if (x5ac_tailModel) { + CModelFlags flags(2, 0, 3, zeus::CColor::skWhite); + flags.addColor = x42c_color; + x5ac_tailModel->Render(mgr, tailXf, x90_actorLights.get(), flags); + } + } else if (x5ac_tailModel) { + CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); + x5ac_tailModel->Render(mgr, tailXf, x90_actorLights.get(), flags); + } + } + CPatterned::Render(mgr); +} + +const CDamageVulnerability* CBeetle::GetDamageVulnerability() const { + if (x838_25_burrowing) + return &CDamageVulnerability::PassThroughVulnerabilty(); + if (x3fc_flavor == EFlavorType::One) + return x450_bodyController->IsOnFire() ? &x7ac_tailVuln : &x744_platingVuln; + return CAi::GetDamageVulnerability(); +} + +const CDamageVulnerability* CBeetle::GetDamageVulnerability(const zeus::CVector3f& pos, + const zeus::CVector3f& dir, + const CDamageInfo& dInfo) const { + if (x838_25_burrowing) + return &CDamageVulnerability::PassThroughVulnerabilty(); + if (x3fc_flavor == EFlavorType::One) { + if (dInfo.GetWeaponMode().IsComboed() && dInfo.GetWeaponMode().GetType() == EWeaponType::Wave) + return &x7ac_tailVuln; + if (GetTransform().basis[1].dot(dir) > 0.f && + GetTransform().basis[1].dot(zeus::CUnitVector3f(pos - GetBoundingBox().center())) < -0.5f) + return &x7ac_tailVuln; + else + return &x744_platingVuln; + } + return GetDamageVulnerability(); +} + +zeus::CVector3f CBeetle::GetOrbitPosition(const CStateManager& mgr) const { + zeus::CVector3f ret = CPatterned::GetOrbitPosition(mgr); + ret.z() = float(GetBoundingBox().center().z()); + return ret; +} + +zeus::CVector3f CBeetle::GetAimPosition(const CStateManager& mgr, float dt) const { + if (x3fc_flavor == EFlavorType::One || x3fc_flavor == EFlavorType::Two) { + zeus::CTransform tailXf = GetLctrTransform("Target_Tail"sv); + zeus::CVector3f scaleRange = tailXf * x574_tailAimReference - GetTranslation(); + zeus::CAABox aabb = GetBoundingBox(); + float minFactor = 10.f; + for (int i = 0; i < 3; ++i) { + if (scaleRange[i] < 0.f) { + float factor = (aabb.min[i] - GetTranslation()[i]) / scaleRange[i]; + if (factor < minFactor) + minFactor = factor; + } else if (scaleRange[i] > 0.f) { + float factor = (aabb.max[i] - GetTranslation()[i]) / scaleRange[i]; + if (factor < minFactor) + minFactor = factor; + } + } + return scaleRange * minFactor + GetTranslation(); + } else { + return CPhysicsActor::GetAimPosition(mgr, dt); + } +} + +EWeaponCollisionResponseTypes CBeetle::GetCollisionResponseType(const zeus::CVector3f& pos, + const zeus::CVector3f& dir, + const CWeaponMode& wMode, + EProjectileAttrib attribs) const { + if (x450_bodyController->IsFrozen() && wMode.GetType() == EWeaponType::Ice) + return EWeaponCollisionResponseTypes::None; + if(x838_25_burrowing) + return EWeaponCollisionResponseTypes::Unknown69; + if (x3fc_flavor == EFlavorType::One) { + if (GetTransform().basis[1].dot(dir) > 0.f && + GetTransform().basis[1].dot(zeus::CUnitVector3f(pos - GetBoundingBox().center())) < -0.5f) + return EWeaponCollisionResponseTypes::Unknown44; + if (!x744_platingVuln.WeaponHurts(wMode, false)) + return EWeaponCollisionResponseTypes::Unknown69; + } + return EWeaponCollisionResponseTypes::Unknown19; +} + +void CBeetle::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { + bool handled = false; + switch (type) { + case EUserEventType::ChangeMaterial: + AddMaterial(EMaterialTypes::Character, EMaterialTypes::Solid, mgr); + x328_25_verticalMovement = true; + RemoveMaterial(EMaterialTypes::GroundCollider, mgr); + handled = true; + break; + case EUserEventType::GenerateEnd: + x328_25_verticalMovement = false; + AddMaterial(EMaterialTypes::GroundCollider, mgr); + handled = true; + break; + case EUserEventType::DamageOn: { + zeus::CVector3f center = + GetTransform() * (x64_modelData->GetScale() * GetLocatorTransform("LCTR_GARMOUTH"sv).origin); + zeus::CVector3f extent = x64_modelData->GetScale() * zeus::CVector3f(2.f, 2.f, 0.5f); + if (zeus::CAABox(center - extent, center + extent).intersects(mgr.GetPlayer().GetBoundingBox())) { + mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), x584_touchDamage, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), zeus::CVector3f::skZero); + } + handled = true; + break; + } + case EUserEventType::Delete: + handled = true; + break; + default: + break; + } + if (!handled) + CPatterned::DoUserAnimEvent(mgr, node, type, dt); +} + +void CBeetle::CollidedWith(TUniqueId uid, const CCollisionInfoList& list, CStateManager& mgr) { + static CMaterialList envList(EMaterialTypes::Ceiling, EMaterialTypes::Wall); + for (const auto& c : list) { + if (c.GetMaterialLeft().Intersection(envList) != 0 && + x450_bodyController->GetCurrentStateId() == pas::EAnimationState::MeleeAttack) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::NextState)); + SetVelocityWR(zeus::CVector3f::skZero); + } + } + CPatterned::CollidedWith(uid, list, mgr); +} + +void CBeetle::Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) { + if (x400_25_alive) { + if (x3fc_flavor == EFlavorType::One) { + zeus::CTransform backupXf = GetTransform(); + SetTransform(GetLctrTransform("Target_Tail"sv)); + SendScriptMsgs(EScriptObjectState::DeathRattle, mgr, EScriptObjectMessage::None); + SetTransform(backupXf); + } + CPatterned::Death(mgr, direction, state); + } +} + +void CBeetle::TakeDamage(const zeus::CVector3f& direction, float magnitude) { + x428_damageCooldownTimer = 0.33f; +} + +bool CBeetle::IsListening() const { + return true; +} + +zeus::CVector3f CBeetle::GetOrigin(const CStateManager& mgr, const CTeamAiRole& role, + const zeus::CVector3f& aimPos) const { + float midRange = (x2fc_minAttackRange + x300_maxAttackRange) * 0.5f; + zeus::CVector3f playerToThis = GetTranslation() - aimPos; + if (playerToThis.canBeNormalized()) + return aimPos + playerToThis.normalized() * midRange; + else + return aimPos + GetTransform().basis[1] * midRange; +} + +void CBeetle::FollowPattern(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + x568_stateProg = 1; + break; + case EStateMsg::Update: + switch (x568_stateProg) { + case 1: + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Step) { + x568_stateProg = 3; + } else if (IsOnGround()) { + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCStepCmd(pas::EStepDirection::Left, pas::EStepType::Normal)); + } + break; + case 3: + if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Step && IsOnGround()) { + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCStepCmd(pas::EStepDirection::Right, pas::EStepType::Normal)); + x568_stateProg = 2; + } + break; + case 2: + if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Step) + x568_stateProg = x814_attackDelayTimer <= 0.f ? 4 : 1; + break; + default: + break; + } + x450_bodyController->GetCommandMgr().DeliverTargetVector( + mgr.GetPlayer().GetTranslation() - GetTranslation()); + break; + default: + break; + } +} + +void CBeetle::RefinePathFindDest(CStateManager& mgr, zeus::CVector3f& dest) { + dest = mgr.GetPlayer().GetTranslation(); + if (CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x570_aiMgr, GetUniqueId())) { + dest = role->GetTeamPosition(); + } else { + zeus::CVector3f thisToDest = dest - GetTranslation(); + dest += (thisToDest.canBeNormalized() ? thisToDest.normalized() : GetTransform().basis[1]) * + (0.5f * (x2fc_minAttackRange + x300_maxAttackRange)); + } +} + +void CBeetle::SeparateFromMelees(CStateManager& mgr) { + for (CEntity* ent : mgr.GetListeningAiObjectList()) { + if (TCastToPtr ai = ent) { + if (ai.GetPtr() != this && ai->GetAreaIdAlways() == GetAreaIdAlways()) { + float dist = 4.f; + if (CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x570_aiMgr, ai->GetUniqueId())) + if (role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Melee) + dist *= 2.f; + zeus::CVector3f move = x45c_steeringBehaviors.Separation(*this, ai->GetTranslation(), dist); + if (!move.isZero()) + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, zeus::CVector3f::skZero, 1.f)); + } + } + } +} + +void CBeetle::PathFind(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + if (GetSearchPath()) { + RefinePathFindDest(mgr, x2e0_destPos); + CPatterned::PathFind(mgr, msg, dt); + } + break; + case EStateMsg::Update: { + zeus::CVector3f dest = mgr.GetPlayer().GetTranslation(); + RefinePathFindDest(mgr, dest); + zeus::CVector3f delta = dest - GetTranslation(); + zeus::CVector3f move; + if (!PathShagged(mgr, 0.f) && !x5fc_pathFindSearch.IsOver()) { + CPatterned::PathFind(mgr, msg, dt); + move = x450_bodyController->GetCommandMgr().GetMoveVector(); + } else { + move = x45c_steeringBehaviors.Arrival(*this, dest, 5.f); + } + if (GetTransform().basis[1].dot(move) >= 0.f || GetTransform().basis[1].dot(delta) <= 0.f) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, zeus::CVector3f::skZero, 1.f)); + } else { + zeus::CVector3f face = delta.canBeNormalized() ? delta.normalized() : GetTransform().basis[1]; + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, face, 1.f)); + } + SeparateFromMelees(mgr); + break; + } + default: + break; + } +} + +void CBeetle::TargetPlayer(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + if (CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x570_aiMgr, GetUniqueId())) + x2e0_destPos = role->GetTeamPosition(); + else + x2e0_destPos = mgr.GetPlayer().GetTranslation(); + x2dc_destObj = mgr.GetPlayer().GetUniqueId(); + x2ec_reflectedDestPos = GetTranslation(); + x328_24_inPosition = false; + } +} + +void CBeetle::Generate(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + if (x56c_entranceType == EEntranceType::FacePlayer || x450_bodyController->GetActive()) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero)); + SetTransform(zeus::lookAt(GetTranslation(), mgr.GetPlayer().GetTranslation())); + } else { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero, x388_anim)); + } + if (!x450_bodyController->GetActive()) + x450_bodyController->Activate(mgr); + RemoveMaterial(EMaterialTypes::Character, EMaterialTypes::Solid, mgr); + x568_stateProg = 0; + break; + case EStateMsg::Update: + switch (x568_stateProg) { + case 0: + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate) { + x568_stateProg = 2; + x5a8_animTimeRem = x450_bodyController->GetAnimTimeRemaining(); + } else { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero)); + } + break; + case 2: + if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Generate) { + x568_stateProg = 4; + } else if (x68_material.HasMaterial(EMaterialTypes::Solid) && x5a8_animTimeRem > 0.f) { + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, zeus::CAABox(GetTranslation() - 5.f, GetTranslation() + 5.f), + CMaterialFilter::MakeInclude({EMaterialTypes::Solid}), this); + if (!nearList.empty()) { + zeus::CVector3f totalSep; + float sepFactor = 5.f * dt / x5a8_animTimeRem; + for (TUniqueId id : nearList) { + if (CActor* act = static_cast(mgr.ObjectById(id))) { + zeus::CVector3f sep = x45c_steeringBehaviors.Separation(*this, act->GetTranslation(), 5.f); + sep.z() = std::max(0.f, float(sep.z())); + totalSep += sep * sepFactor; + } + } + SetTranslation(GetTranslation() + totalSep); + } + } + break; + default: + break; + } + break; + case EStateMsg::Deactivate: + AddMaterial(EMaterialTypes::Character, EMaterialTypes::Solid, EMaterialTypes::GroundCollider, mgr); + x328_25_verticalMovement = false; + x838_25_burrowing = false; + if (x328_26_longJump) + DeathDelete(mgr); + break; + default: + break; + } +} + +void CBeetle::Deactivate(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + x568_stateProg = 0; + SquadRemove(mgr); + x818_stateFinishTimer = 0.f; + break; + case EStateMsg::Update: + switch (x568_stateProg) { + case 0: + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate) { + RemoveMaterial(EMaterialTypes::Character, EMaterialTypes::Solid, + EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); + mgr.GetPlayer().SetOrbitRequestForTarget(GetUniqueId(), CPlayer::EPlayerOrbitRequest::ActivateOrbitSource, mgr); + x838_25_burrowing = true; + x5a8_animTimeRem = x450_bodyController->GetAnimTimeRemaining(); + x568_stateProg = 2; + } else if (IsOnGround()) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::One)); + } else { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd( + x45c_steeringBehaviors.Seek(*this, mgr.GetPlayer().GetTranslation()), zeus::CVector3f::skZero, 1.f)); + } + break; + case 2: + if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Generate) { + x568_stateProg = 3; + x830_intoGroundFactor = 0.f; + auto aabb = GetBoundingBox(); + SetTranslation((aabb.max.z() - aabb.min.z()) * 3.f * zeus::CVector3f::skDown + GetTranslation()); + } else { + float remTime = x450_bodyController->GetAnimTimeRemaining(); + x830_intoGroundFactor = x5a8_animTimeRem > 0.f ? remTime / x5a8_animTimeRem : 0.f; + } + break; + case 3: + x818_stateFinishTimer += dt; + if (x818_stateFinishTimer >= 0.75f) { + SendScriptMsgs(EScriptObjectState::DeactivateState, mgr, EScriptObjectMessage::None); + mgr.FreeScriptObject(GetUniqueId()); + x568_stateProg = 4; + x830_intoGroundFactor = 0.f; + } else { + auto aabb = GetBoundingBox(); + SetTranslation((aabb.max.z() - aabb.min.z()) * 4.f * zeus::CVector3f::skDown * dt + GetTranslation()); + } + break; + default: + break; + } + default: + break; + } +} + +void CBeetle::Attack(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + x838_26_canSkid = false; + x838_24_hitSomething = false; + x2e0_destPos = mgr.GetPlayer().GetTranslation(); + x2e0_destPos.z() = GetTranslation().z(); + x568_stateProg = 0; + break; + case EStateMsg::Update: + switch (x568_stateProg) { + case 0: + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::MeleeAttack) { + x568_stateProg = 1; + x838_26_canSkid = true; + } else if (IsOnGround()) { + zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f); + aimPos.z() = GetTranslation().z(); + zeus::CVector3f aimDelta = aimPos - GetTranslation(); + aimDelta.z() = 0.f; + if (aimDelta.canBeNormalized()) + aimPos += aimDelta.normalized() * 5.f; + x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::One, aimPos)); + } + break; + case 1: + if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::MeleeAttack) { + x568_stateProg = 4; + } else if (IsOnGround()) { + x450_bodyController->GetCommandMgr().DeliverTargetVector(x2e0_destPos - GetTranslation()); + } else { + x568_stateProg = 2; + } + break; + case 2: + if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::MeleeAttack) + x568_stateProg = 4; + break; + default: + break; + } + if (x328_26_longJump) + x838_24_hitSomething = true; + break; + case EStateMsg::Deactivate: + CTeamAiMgr::ResetTeamAiRole(CTeamAiMgr::EAttackType::Melee, mgr, x570_aiMgr, GetUniqueId(), true); + x814_attackDelayTimer = mgr.GetActiveRandom()->Float() * x308_attackTimeVariation + x304_averageAttackTime; + break; + } +} + +void CBeetle::JumpBack(CStateManager&, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + x568_stateProg = 0; + break; + case EStateMsg::Update: + switch (x568_stateProg) { + case 0: + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Step) { + x568_stateProg = 2; + } else if (IsOnGround()) { + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCStepCmd(pas::EStepDirection::Backward, pas::EStepType::Normal)); + } + break; + case 2: + if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Step) + x568_stateProg = 4; + break; + default: + break; + } + break; + default: + break; + } +} + +void CBeetle::DoubleSnap(CStateManager&, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + x568_stateProg = 0; + break; + case EStateMsg::Update: + switch (x568_stateProg) { + case 0: + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::MeleeAttack) { + x568_stateProg = 2; + } else { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::Zero)); + } + break; + case 2: + if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::MeleeAttack) + x568_stateProg = 4; + else + x450_bodyController->GetCommandMgr().DeliverTargetVector(x2e0_destPos - GetTranslation()); + break; + default: + break; + } + break; + default: + break; + } +} + +void CBeetle::Shuffle(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + x328_24_inPosition = false; + break; + case EStateMsg::Update: { + zeus::CVector3f playerPos = mgr.GetPlayer().GetTranslation(); + zeus::CVector3f playerToThis = GetTranslation() - playerPos; + float midRange = 0.5f * (x2fc_minAttackRange + x300_maxAttackRange); + zeus::CVector3f playerLimit; + if (playerToThis.canBeNormalized()) + playerLimit = playerToThis.normalized() * midRange + playerPos; + else + playerLimit = GetTransform().basis[1] * midRange + playerPos; + if ((GetTranslation() - playerLimit).magSquared() > 4.f) { + pas::EStepDirection dir = GetStepDirection(-playerToThis); + switch (dir) { + case pas::EStepDirection::Forward: + case pas::EStepDirection::Backward: { + zeus::CVector3f move = x45c_steeringBehaviors.Arrival(*this, x2e0_destPos, x300_maxAttackRange); + if (GetTransform().basis[1].dot(move) >= 0.f || GetTransform().basis[1].dot(playerToThis) >= 0.f) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, zeus::CVector3f::skZero, 1.f)); + } else { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, + playerToThis.canBeNormalized() ? -playerToThis.normalized() : GetTransform().basis[1], 1.f)); + } + break; + } + case pas::EStepDirection::Left: + case pas::EStepDirection::Right: { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCStepCmd(dir, pas::EStepType::Normal)); + break; + } + default: + break; + } + x450_bodyController->GetCommandMgr().DeliverTargetVector(-playerToThis); + } else { + x328_24_inPosition = true; + } + break; + } + default: + break; + } +} + +void CBeetle::TurnAround(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + x568_stateProg = 0; + break; + case EStateMsg::Update: + switch (x568_stateProg) { + case 0: + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Turn) { + x568_stateProg = 2; + } else { + zeus::CVector3f thisToPlayer = mgr.GetPlayer().GetTranslation() - GetTranslation(); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(zeus::CVector3f::skZero, + (thisToPlayer.magnitude() > FLT_EPSILON) ? thisToPlayer.normalized() : zeus::CVector3f::skZero, 1.f)); + } + break; + case 2: + if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Turn) + x568_stateProg = 4; + break; + default: + break; + } + break; + default: + break; + } +} + +void CBeetle::Skid(CStateManager&, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + if (IsOnGround() && x838_26_canSkid) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCSlideCmd(pas::ESlideType::Zero, GetTransform().basis[1])); + x568_stateProg = 2; + } + break; + case EStateMsg::Update: + if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Slide) + x568_stateProg = 4; + break; + case EStateMsg::Deactivate: + x838_26_canSkid = false; + break; + default: + break; + } +} + +void CBeetle::Taunt(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCTauntCmd(mgr.GetActiveRandom()->Float() < 0.75f ? pas::ETauntType::One : pas::ETauntType::Zero)); + x568_stateProg = 2; + break; + case EStateMsg::Update: + if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Taunt) + x568_stateProg = 4; + else + x450_bodyController->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); + break; + default: + break; + } +} + +s32 CBeetle::FindFurthestRetreatPoint(CStateManager& mgr) const { + s32 ret = -1; + if (x6e0_retreatPoints.empty()) + return ret; + zeus::CVector2f playerPos = mgr.GetPlayer().GetTranslation().toVec2f(); + ret = mgr.GetActiveRandom()->Range(0, s32(x6e0_retreatPoints.size() - 1)); + float maxDist = (playerPos - x6e0_retreatPoints[ret].toVec2f()).magSquared(); + if (maxDist < 100.f) { + s32 i = 0; + for (const auto& v : x6e0_retreatPoints) { + float dist = (playerPos - v.toVec2f()).magSquared(); + if (dist > maxDist) { + maxDist = dist; + ret = i; + } + ++i; + } + } + return ret; +} + +void CBeetle::Retreat(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + x568_stateProg = 0; + SquadRemove(mgr); + x818_stateFinishTimer = 0.f; + x3b4_speed = 2.f * x81c_; + break; + case EStateMsg::Update: + switch (x568_stateProg) { + case 0: + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate) { + RemoveMaterial(EMaterialTypes::Character, EMaterialTypes::Solid, + EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); + mgr.GetPlayer().SetOrbitRequestForTarget(GetUniqueId(), + CPlayer::EPlayerOrbitRequest::ActivateOrbitSource, mgr); + x838_25_burrowing = true; + x5a8_animTimeRem = x450_bodyController->GetAnimTimeRemaining(); + x568_stateProg = 2; + } else if (IsOnGround()) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::One)); + } else { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd( + x45c_steeringBehaviors.Seek(*this, mgr.GetPlayer().GetTranslation()), zeus::CVector3f::skZero, 1.f)); + } + break; + case 2: + if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Generate) { + x568_stateProg = 3; + x830_intoGroundFactor = 0.f; + auto aabb = GetBoundingBox(); + SetTranslation((aabb.max.z() - aabb.min.z()) * 3.f * zeus::CVector3f::skDown + GetTranslation()); + } else { + float remTime = x450_bodyController->GetAnimTimeRemaining(); + x830_intoGroundFactor = (x5a8_animTimeRem > 0.f) ? remTime / x5a8_animTimeRem : 0.f; + } + break; + case 3: + x818_stateFinishTimer += dt; + if (x818_stateFinishTimer >= x834_retreatTime) { + x568_stateProg = 4; + x830_intoGroundFactor = 0.f; + } else { + auto aabb = GetBoundingBox(); + zeus::CVector3f downVec = (aabb.max.z() - aabb.min.z()) * 3.f * zeus::CVector3f::skDown; + SetTranslation(((x834_retreatTime > 0.f) ? + (1.f / x834_retreatTime) * downVec : downVec) * dt + GetTranslation()); + } + break; + default: + break; + } + break; + case EStateMsg::Deactivate: { + s32 idx = FindFurthestRetreatPoint(mgr); + if (idx != -1) { + SetTranslation(x6e0_retreatPoints[idx]); + AddMaterial(EMaterialTypes::Character, EMaterialTypes::Solid, + EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); + } else { + SendScriptMsgs(EScriptObjectState::DeactivateState, mgr, EScriptObjectMessage::None); + mgr.FreeScriptObject(GetUniqueId()); + } + x400_24_hitByPlayerProjectile = false; + x3b4_speed = x81c_; + x838_25_burrowing = false; + break; + } + } +} + +bool CBeetle::InAttackPosition(CStateManager& mgr, float arg) { + float distSq = (mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared(); + if (distSq > x2fc_minAttackRange * x2fc_minAttackRange && distSq < x300_maxAttackRange * x300_maxAttackRange) + if (SpotPlayer(mgr, x3c8_leashRadius)) + return true; + return false; +} + +bool CBeetle::PathShagged(CStateManager&, float arg) { + return false; +} + +bool CBeetle::InRange(CStateManager& mgr, float arg) { + zeus::CVector3f targetPos = mgr.GetPlayer().GetTranslation(); + if (CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x570_aiMgr, GetUniqueId())) { + if (role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Melee) + targetPos = role->GetTeamPosition(); + } + return (targetPos - GetTranslation()).magSquared() < 100.f; +} + +bool CBeetle::PatternOver(CStateManager& mgr, float arg) { + return AnimOver(mgr, arg); +} + +bool CBeetle::HasAttackPattern(CStateManager&, float arg) { + return true; +} + +bool CBeetle::AnimOver(CStateManager&, float arg) { + return x568_stateProg == 4; +} + +bool CBeetle::ShouldAttack(CStateManager& mgr, float arg) { + if (x814_attackDelayTimer <= 0.f) { + if (TCastToPtr tmgr = mgr.ObjectById(x570_aiMgr)) { + if (tmgr->HasTeamAiRole(GetUniqueId())) + return tmgr->AddMeleeAttacker(GetUniqueId()); + } + return true; + } + return false; +} + +bool CBeetle::ShouldDoubleSnap(CStateManager& mgr, float arg) { + if (!GetSearchPath() && IsOnGround()) { + zeus::CVector3f targetPos = mgr.GetPlayer().GetTranslation(); + float dist = x5a0_headbuttDist + x300_maxAttackRange; + if (CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x570_aiMgr, GetUniqueId())) + targetPos = role->GetTeamPosition(); + zeus::CVector3f delta = targetPos - GetTranslation(); + if (delta.magSquared() > dist * dist && GetTransform().basis[1].dot(delta.normalized()) > 0.98f) { + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, GetTranslation(), GetTransform().basis[1], x5a0_headbuttDist, + CMaterialFilter::MakeInclude({EMaterialTypes::Character}), this); + TUniqueId bestId = kInvalidUniqueId; + CRayCastResult res = mgr.RayWorldIntersection(bestId, GetTranslation(), GetTransform().basis[1], + x5a0_headbuttDist, CMaterialFilter::MakeInclude({EMaterialTypes::Solid}), nearList); + if (res.IsInvalid()) + return true; + } + } + return false; +} + +bool CBeetle::ShouldTurn(CStateManager& mgr, float arg) { + return zeus::CVector2f::getAngleDiff(GetTransform().basis[1].toVec2f(), + (mgr.GetPlayer().GetTranslation() - GetTranslation()).toVec2f()) > zeus::degToRad(30.f); +} + +bool CBeetle::HitSomething(CStateManager&, float arg) { + return x838_24_hitSomething; +} + +bool CBeetle::ShouldJumpBack(CStateManager& mgr, float arg) { + zeus::CVector3f backDir = -GetTransform().basis[1]; + const auto& aabb = GetBaseBoundingBox(); + zeus::CVector3f pos = GetTranslation() + zeus::CVector3f(0.f, 0.f, (aabb.max.z() - aabb.min.z()) * 0.5f); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, pos, backDir, x5a4_jumpBackwardDist, + CMaterialFilter::MakeInclude({EMaterialTypes::Character}), this); + TUniqueId bestId = kInvalidUniqueId; + CRayCastResult res = mgr.RayWorldIntersection(bestId, pos, backDir, x5a4_jumpBackwardDist, + CMaterialFilter::MakeInclude({EMaterialTypes::Solid}), nearList); + return res.IsInvalid(); +} + +bool CBeetle::Stuck(CStateManager&, float arg) { + return x820_posDeviationCounter > 30; +} + +bool CBeetle::NoPathNodes(CStateManager&, float arg) { + return false; +} + +bool CBeetle::ShouldTaunt(CStateManager& mgr, float arg) { + if (CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x570_aiMgr, GetUniqueId())) { + if (role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Unknown || + role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Unassigned) { + return (role->GetTeamPosition() - GetTranslation()).magSquared() < 100.f; + } + } + return false; +} + +bool CBeetle::ShotAt(CStateManager&, float arg) { + if (x3fc_flavor == EFlavorType::Two && x6e0_retreatPoints.size() > 0) + return x400_24_hitByPlayerProjectile; + return false; +} + +void CBeetle::Burn(float duration, float damage) { + CDamageVulnerability dVuln = *GetDamageVulnerability(); + if (!x838_25_burrowing && x3fc_flavor == EFlavorType::One) + dVuln = x7ac_tailVuln; + switch (dVuln.GetVulnerability(CWeaponMode(EWeaponType::Wave), false)) { + case EVulnerability::Weak: + x450_bodyController->SetOnFire(1.5f * duration); + x3ec_pendingFireDamage = 1.5f * damage; + break; + case EVulnerability::Normal: + x450_bodyController->SetOnFire(duration); + x3ec_pendingFireDamage = damage; + break; + default: + break; + } +} + +void CBeetle::Shock(CStateManager& mgr, float duration, float damage) { + CDamageVulnerability dVuln = *GetDamageVulnerability(); + if (!x838_25_burrowing && x3fc_flavor == EFlavorType::One) + dVuln = x7ac_tailVuln; + switch (dVuln.GetVulnerability(CWeaponMode(EWeaponType::Wave), false)) { + case EVulnerability::Weak: + x450_bodyController->SetElectrocuting(1.5f * duration); + x3f0_pendingShockDamage = 1.5f * damage; + break; + case EVulnerability::Normal: + x450_bodyController->SetElectrocuting(duration); + x3f0_pendingShockDamage = damage; + break; + default: + break; + } +} + +CPathFindSearch* CBeetle::GetSearchPath() { + return &x5fc_pathFindSearch; +} + +float CBeetle::GetGravityConstant() const { + return 4.f * 24.525f; +} + } // namespace urde::MP1 diff --git a/Runtime/MP1/World/CBeetle.hpp b/Runtime/MP1/World/CBeetle.hpp index 625295ecb..7ed515354 100644 --- a/Runtime/MP1/World/CBeetle.hpp +++ b/Runtime/MP1/World/CBeetle.hpp @@ -1,9 +1,10 @@ #pragma once #include "World/CPatterned.hpp" +#include "World/CPathFindSearch.hpp" +#include "World/CDamageInfo.hpp" namespace urde { -class CDamageInfo; namespace MP1 { class CBeetle : public CPatterned { @@ -11,14 +12,113 @@ public: enum class EEntranceType : u32 { FacePlayer, UseOrientation }; private: + s32 x568_stateProg = -1; + EEntranceType x56c_entranceType; + TUniqueId x570_aiMgr = kInvalidUniqueId; + zeus::CVector3f x574_tailAimReference; + float x580_f3; + CDamageInfo x584_touchDamage; + float x5a0_headbuttDist = FLT_MAX; + float x5a4_jumpBackwardDist = FLT_MAX; + float x5a8_animTimeRem = 0.f; + std::experimental::optional x5ac_tailModel; + CPathFindSearch x5fc_pathFindSearch; + rstl::reserved_vector x6e0_retreatPoints; + CDamageVulnerability x744_platingVuln; + CDamageVulnerability x7ac_tailVuln; + float x814_attackDelayTimer; + float x818_stateFinishTimer = FLT_MAX; + float x81c_ = x3b4_speed; + u32 x820_posDeviationCounter = 0; + zeus::CVector3f x824_predictPos; + float x830_intoGroundFactor = 1.f; + float x834_retreatTime; + union { + struct { + bool x838_24_hitSomething : 1; + bool x838_25_burrowing : 1; + bool x838_26_canSkid : 1; + }; + u32 _dummy3 = 0; + }; + + void SquadAdd(CStateManager& mgr); + void SquadRemove(CStateManager& mgr); + void RefinePathFindDest(CStateManager& mgr, zeus::CVector3f& dest); + void SeparateFromMelees(CStateManager& mgr); + void SetupRetreatPoints(CStateManager& mgr); + s32 FindFurthestRetreatPoint(CStateManager& mgr) const; + public: DEFINE_PATTERNED(Beetle) - CBeetle(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, const CPatternedInfo&, - CPatterned::EFlavorType, EEntranceType, const CDamageInfo&, const CDamageVulnerability&, - const zeus::CVector3f&, float, float, float, const CDamageVulnerability&, const CActorParameters&, - const std::experimental::optional); + CBeetle(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CPatternedInfo& pInfo, CPatterned::EFlavorType flavor, + CBeetle::EEntranceType entranceType, const CDamageInfo& touchDamage, + const CDamageVulnerability& platingVuln, const zeus::CVector3f& tailAimReference, + float initialAttackDelay, float retreatTime, float f3, + const CDamageVulnerability& tailVuln, const CActorParameters& aParams, + const std::experimental::optional& tailModel); void Accept(IVisitor& visitor); + void Think(float dt, CStateManager& mgr); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); + void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum); + void Render(const CStateManager& mgr) const; + + const CDamageVulnerability* GetDamageVulnerability() const; + const CDamageVulnerability* GetDamageVulnerability(const zeus::CVector3f& pos, + const zeus::CVector3f& dir, + const CDamageInfo& dInfo) const; + zeus::CVector3f GetOrbitPosition(const CStateManager&) const; + zeus::CVector3f GetAimPosition(const CStateManager& mgr, float) const; + EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f& pos, + const zeus::CVector3f& dir, + const CWeaponMode& wMode, + EProjectileAttrib attribs) const; + void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float dt); + void CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager& mgr); + void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state); + void TakeDamage(const zeus::CVector3f& direction, float magnitude); + bool IsListening() const; + zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role, + const zeus::CVector3f& aimPos) const; + + void FollowPattern(CStateManager&, EStateMsg msg, float dt); + void PathFind(CStateManager& mgr, EStateMsg msg, float dt); + void TargetPlayer(CStateManager&, EStateMsg msg, float dt); + void Generate(CStateManager&, EStateMsg msg, float dt); + void Deactivate(CStateManager&, EStateMsg msg, float dt); + void Attack(CStateManager&, EStateMsg msg, float dt); + void JumpBack(CStateManager&, EStateMsg msg, float dt); + void DoubleSnap(CStateManager&, EStateMsg msg, float dt); + void Shuffle(CStateManager&, EStateMsg msg, float dt); + void TurnAround(CStateManager&, EStateMsg msg, float dt); + void Skid(CStateManager&, EStateMsg msg, float dt); + void Taunt(CStateManager&, EStateMsg msg, float dt); + void Retreat(CStateManager&, EStateMsg msg, float dt); + + bool InAttackPosition(CStateManager&, float arg); + bool PathShagged(CStateManager&, float arg); + bool InRange(CStateManager&, float arg); + bool PatternOver(CStateManager&, float arg); + bool HasAttackPattern(CStateManager&, float arg); + bool AnimOver(CStateManager&, float arg); + bool ShouldAttack(CStateManager&, float arg); + bool ShouldDoubleSnap(CStateManager&, float arg); + bool ShouldTurn(CStateManager&, float arg); + bool HitSomething(CStateManager&, float arg); + bool ShouldJumpBack(CStateManager&, float arg); + bool Stuck(CStateManager&, float arg); + bool NoPathNodes(CStateManager&, float arg); + bool ShouldTaunt(CStateManager&, float arg); + bool ShotAt(CStateManager&, float arg); + + void Burn(float duration, float damage); + void Shock(CStateManager& mgr, float duration, float damage); + + CPathFindSearch* GetSearchPath(); + float GetGravityConstant() const; + }; } // namespace MP1 } // namespace urde diff --git a/Runtime/MP1/World/CSpacePirate.cpp b/Runtime/MP1/World/CSpacePirate.cpp index d1d4e38c1..3beee8e05 100644 --- a/Runtime/MP1/World/CSpacePirate.cpp +++ b/Runtime/MP1/World/CSpacePirate.cpp @@ -485,12 +485,12 @@ bool CSpacePirate::ShouldFrenzy(CStateManager& mgr) { return x63c_frenzyFrames >= 0; } -void CSpacePirate::ResetTeamAiRole(CStateManager& mgr) { +void CSpacePirate::SquadReset(CStateManager& mgr) { CTeamAiMgr::ResetTeamAiRole(!x634_27_melee ? CTeamAiMgr::EAttackType::Projectile : CTeamAiMgr::EAttackType::Melee, mgr, x8c8_teamAiMgrId, GetUniqueId(), true); } -void CSpacePirate::AssignTeamAiRole(CStateManager& mgr) { +void CSpacePirate::SquadAdd(CStateManager& mgr) { if (x8c8_teamAiMgrId == kInvalidUniqueId) x8c8_teamAiMgrId = CTeamAiMgr::GetTeamAiMgr(*this, mgr); if (x8c8_teamAiMgrId != kInvalidUniqueId) { @@ -502,7 +502,7 @@ void CSpacePirate::AssignTeamAiRole(CStateManager& mgr) { } } -void CSpacePirate::RemoveTeamAiRole(CStateManager& mgr) { +void CSpacePirate::SquadRemove(CStateManager& mgr) { if (x8c8_teamAiMgrId != kInvalidUniqueId) { if (TCastToPtr aimgr = mgr.ObjectById(x8c8_teamAiMgrId)) { if (aimgr->IsPartOfTeam(GetUniqueId())) { @@ -611,7 +611,7 @@ void CSpacePirate::UpdateAttacks(float dt, CStateManager& mgr) { } if (reset) - ResetTeamAiRole(mgr); + SquadReset(mgr); xe7_31_targetable = CheckTargetable(mgr); } @@ -852,7 +852,7 @@ void CSpacePirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, C x638_31_mayStartAttack = true; else x400_24_hitByPlayerProjectile = true; - AssignTeamAiRole(mgr); + SquadAdd(mgr); } else if (x634_25_ceilingAmbush) { RemoveMaterial(EMaterialTypes::GroundCollider, mgr); x328_27_onGround = false; @@ -956,7 +956,7 @@ void CSpacePirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, C break; case EScriptObjectMessage::Deactivate: case EScriptObjectMessage::Deleted: - RemoveTeamAiRole(mgr); + SquadRemove(mgr); mChargePlayerList.remove(GetUniqueId()); break; case EScriptObjectMessage::Start: @@ -1137,7 +1137,8 @@ bool CSpacePirate::Listen(const zeus::CVector3f& pos, EListenNoiseType type) { return ret; } -zeus::CVector3f CSpacePirate::GetOrigin(const CStateManager& mgr, const CTeamAiRole& role) const { +zeus::CVector3f CSpacePirate::GetOrigin(const CStateManager& mgr, const CTeamAiRole& role, + const zeus::CVector3f& aimPos) const { return GetTranslation(); } @@ -1220,7 +1221,7 @@ void CSpacePirate::Dead(CStateManager& mgr, EStateMsg msg, float dt) { case EStateMsg::Activate: x764_boneTracking.SetActive(false); SetEyeParticleActive(mgr, false); - ResetTeamAiRole(mgr); + SquadReset(mgr); break; case EStateMsg::Update: if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Death) { @@ -1773,7 +1774,7 @@ void CSpacePirate::GetUp(CStateManager& mgr, EStateMsg msg, float dt) { switch (msg) { case EStateMsg::Activate: x32c_animState = EAnimState::Ready; - ResetTeamAiRole(mgr); + SquadReset(mgr); x8dc_leashTimer = 0.f; break; case EStateMsg::Update: diff --git a/Runtime/MP1/World/CSpacePirate.hpp b/Runtime/MP1/World/CSpacePirate.hpp index ed3418521..f367766bc 100644 --- a/Runtime/MP1/World/CSpacePirate.hpp +++ b/Runtime/MP1/World/CSpacePirate.hpp @@ -221,9 +221,9 @@ private: void UpdateCloak(float dt, CStateManager& mgr); bool ShouldFrenzy(CStateManager& mgr); - void ResetTeamAiRole(CStateManager& mgr); - void AssignTeamAiRole(CStateManager& mgr); - void RemoveTeamAiRole(CStateManager& mgr); + void SquadReset(CStateManager& mgr); + void SquadAdd(CStateManager& mgr); + void SquadRemove(CStateManager& mgr); bool CheckTargetable(CStateManager& mgr); bool FireProjectile(float dt, CStateManager& mgr); void UpdateAttacks(float dt, CStateManager& mgr); @@ -263,7 +263,8 @@ public: float magnitude); bool IsListening() const; bool Listen(const zeus::CVector3f&, EListenNoiseType); - zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role) const; + zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role, + const zeus::CVector3f& aimPos) const; void DetachActorFromPirate() { x7b4_attachedActor = kInvalidUniqueId; } bool AttachActorToPirate(TUniqueId id); void SetAttackTarget(TUniqueId id); diff --git a/Runtime/World/CAi.hpp b/Runtime/World/CAi.hpp index 1535756c4..36e23296a 100644 --- a/Runtime/World/CAi.hpp +++ b/Runtime/World/CAi.hpp @@ -53,7 +53,8 @@ public: const CWeaponMode&, EProjectileAttrib) const; void FluidFXThink(EFluidState, CScriptWater&, CStateManager&); - virtual zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role) const { + virtual zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role, + const zeus::CVector3f& aimPos) const { return x34_transform.origin; } virtual void Patrol(CStateManager&, EStateMsg, float) {} diff --git a/Runtime/World/CDamageVulnerability.hpp b/Runtime/World/CDamageVulnerability.hpp index df0b5975e..0538973d0 100644 --- a/Runtime/World/CDamageVulnerability.hpp +++ b/Runtime/World/CDamageVulnerability.hpp @@ -64,6 +64,6 @@ public: static const CDamageVulnerability& NormalVulnerabilty() { return sNormalVulnerability; } static const CDamageVulnerability& ImmuneVulnerabilty() { return sImmuneVulnerability; } static const CDamageVulnerability& ReflectVulnerabilty() { return sReflectVulnerability; } - static const CDamageVulnerability& PasshThroughVulnerabilty() { return sPassThroughVulnerability; } + static const CDamageVulnerability& PassThroughVulnerabilty() { return sPassThroughVulnerability; } }; } // namespace urde diff --git a/Runtime/World/CPatterned.cpp b/Runtime/World/CPatterned.cpp index a1d3326bd..87a0a70ca 100644 --- a/Runtime/World/CPatterned.cpp +++ b/Runtime/World/CPatterned.cpp @@ -183,6 +183,11 @@ void CPatterned::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CState } } +void CPatterned::MakeThermalColdAndHot() { + x403_24_keepThermalVisorState = true; + xe6_27_thermalVisorFlags = 3; +} + void CPatterned::UpdateThermalFrozenState(bool thawed) { x402_31_thawed = thawed; if (x403_24_keepThermalVisorState) @@ -243,7 +248,7 @@ void CPatterned::Think(float dt, CStateManager& mgr) { if (x460_knockBackController.x81_26_enableShock) { /* Shock on logical falling edge */ if (!x401_31_nextPendingShock && x402_24_pendingShock) - Shock(0.5f + mgr.GetActiveRandom()->Range(0.f, 0.5f), 0.2f); + Shock(mgr, 0.5f + mgr.GetActiveRandom()->Range(0.f, 0.5f), 0.2f); x402_24_pendingShock = x401_31_nextPendingShock; x401_31_nextPendingShock = false; @@ -437,7 +442,7 @@ void CPatterned::KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, c PhazeOut(mgr); break; case EKnockBackAnimationFollowUp::Shock: - Shock(x460_knockBackController.GetActiveParms().x8_followupDuration, -1.f); + Shock(mgr, x460_knockBackController.GetActiveParms().x8_followupDuration, -1.f); break; case EKnockBackAnimationFollowUp::Burn: Burn(x460_knockBackController.GetActiveParms().x8_followupDuration, 0.25f); @@ -967,7 +972,7 @@ void CPatterned::Burn(float duration, float damage) { } } -void CPatterned::Shock(float duration, float damage) { +void CPatterned::Shock(CStateManager& mgr, float duration, float damage) { switch (GetDamageVulnerability()->GetVulnerability(CWeaponMode(EWeaponType::Wave), false)) { case EVulnerability::Weak: x450_bodyController->SetElectrocuting(1.5f * duration); diff --git a/Runtime/World/CPatterned.hpp b/Runtime/World/CPatterned.hpp index 142d217be..42c924e11 100644 --- a/Runtime/World/CPatterned.hpp +++ b/Runtime/World/CPatterned.hpp @@ -64,7 +64,7 @@ public: WarWasp = 39, EnergyBall = 40 }; - enum class EFlavorType { Zero = 0, One = 1 }; + enum class EFlavorType { Zero = 0, One = 1, Two = 2 }; enum class EMovementType { Ground = 0, Flyer = 1 }; enum class EColliderType { Zero = 0, One = 1 }; enum class EPatternTranslate { RelativeStart, RelativePlayerStart, RelativePlayer, Absolute }; @@ -231,6 +231,7 @@ protected: std::experimental::optional> x54c_iceDeathExplosionParticle; zeus::CVector3f x55c_moveScale = zeus::CVector3f::skOne; + void MakeThermalColdAndHot(); void UpdateThermalFrozenState(bool thawed); void GenerateIceDeathExplosion(CStateManager& mgr); void GenerateDeathExplosion(CStateManager& mgr); @@ -334,8 +335,8 @@ public: virtual bool KnockbackWhenFrozen() const { return true; } virtual void MassiveDeath(CStateManager& mgr); virtual void MassiveFrozenDeath(CStateManager& mgr); - virtual void Burn(float, float); - virtual void Shock(float, float); + virtual void Burn(float duration, float damage); + virtual void Shock(CStateManager& mgr, float duration, float damage); virtual void Freeze(CStateManager& mgr, const zeus::CVector3f& pos, const zeus::CUnitVector3f& dir, float frozenDur); virtual void ThinkAboutMove(float); virtual CPathFindSearch* GetSearchPath() { return nullptr; } diff --git a/Runtime/World/CTeamAiMgr.cpp b/Runtime/World/CTeamAiMgr.cpp index 40789fcc7..1f2f85303 100644 --- a/Runtime/World/CTeamAiMgr.cpp +++ b/Runtime/World/CTeamAiMgr.cpp @@ -131,7 +131,7 @@ void CTeamAiMgr::PositionTeam(CStateManager& mgr) { default: for (auto& role : x58_roles) if (TCastToPtr ai = mgr.ObjectById(role.GetOwnerId())) - role.x1c_position = ai->GetOrigin(mgr, role); + role.x1c_position = ai->GetOrigin(mgr, role, aimPos); break; } } diff --git a/Runtime/World/CTeamAiMgr.hpp b/Runtime/World/CTeamAiMgr.hpp index 17f51637f..9e66414b7 100644 --- a/Runtime/World/CTeamAiMgr.hpp +++ b/Runtime/World/CTeamAiMgr.hpp @@ -74,14 +74,6 @@ private: void UpdateRoles(CStateManager& mgr); void SpacingSort(CStateManager& mgr, const zeus::CVector3f& pos); void PositionTeam(CStateManager& mgr); - bool IsMeleeAttacker(TUniqueId aiId) const; - bool CanAcceptMeleeAttacker(TUniqueId aiId) const; - bool AddMeleeAttacker(TUniqueId aiId); - void RemoveMeleeAttacker(TUniqueId aiId); - bool IsProjectileAttacker(TUniqueId aiId) const; - bool CanAcceptProjectileAttacker(TUniqueId aiId) const; - bool AddProjectileAttacker(TUniqueId aiId); - void RemoveProjectileAttacker(TUniqueId aiId); public: CTeamAiMgr(TUniqueId uid, std::string_view name, const CEntityInfo& info, const CTeamAiData& data); @@ -99,6 +91,15 @@ public: s32 GetNumAssignedOfRole(CTeamAiRole::ETeamAiRole role) const; s32 GetNumAssignedAiRoles() const; + bool IsMeleeAttacker(TUniqueId aiId) const; + bool CanAcceptMeleeAttacker(TUniqueId aiId) const; + bool AddMeleeAttacker(TUniqueId aiId); + void RemoveMeleeAttacker(TUniqueId aiId); + bool IsProjectileAttacker(TUniqueId aiId) const; + bool CanAcceptProjectileAttacker(TUniqueId aiId) const; + bool AddProjectileAttacker(TUniqueId aiId); + void RemoveProjectileAttacker(TUniqueId aiId); + static CTeamAiRole* GetTeamAiRole(CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId); static void ResetTeamAiRole(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId, bool clearRole); static bool CanAcceptAttacker(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId); diff --git a/Runtime/World/ScriptLoader.cpp b/Runtime/World/ScriptLoader.cpp index ba678091c..5d3d2b5f9 100644 --- a/Runtime/World/ScriptLoader.cpp +++ b/Runtime/World/ScriptLoader.cpp @@ -978,29 +978,30 @@ CEntity* ScriptLoader::LoadBeetle(CStateManager& mgr, CInputStream& in, int prop CPatternedInfo pInfo(in, pcount.second); CActorParameters aParams = LoadActorParameters(in); - CDamageInfo dInfo(in); - zeus::CVector3f v1 = zeus::CVector3f::ReadBig(in); - float f1 = in.readFloatBig(); - CDamageVulnerability dVuln1(in); - CDamageVulnerability dVuln2(in); - CAssetId abdomen = in.readUint32Big(); - MP1::CBeetle::EEntranceType entrance = MP1::CBeetle::EEntranceType(in.readUint32Big()); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); + CDamageInfo touchDamage(in); + zeus::CVector3f tailAimReference = zeus::CVector3f::ReadBig(in); + float unused = in.readFloatBig(); + CDamageVulnerability tailVuln(in); + CDamageVulnerability platingVuln(in); + CAssetId tailModel = in.readUint32Big(); + MP1::CBeetle::EEntranceType entranceType = MP1::CBeetle::EEntranceType(in.readUint32Big()); + float initialAttackDelay = in.readFloatBig(); + float retreatTime = in.readFloatBig(); FourCC animType = g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()); if (animType != SBIG('ANCS')) return nullptr; - std::experimental::optional abdomenRes; + std::experimental::optional tailRes; if (flavor == CPatterned::EFlavorType::One) - abdomenRes.emplace(CStaticRes(abdomen, scale)); + tailRes.emplace(CStaticRes(tailModel, scale)); const CAnimationParameters& animParams = pInfo.GetAnimationParameters(); CAnimRes animRes(animParams.GetACSFile(), animParams.GetCharacter(), scale, animParams.GetInitialAnimation(), true); - return new MP1::CBeetle(mgr.AllocateUniqueId(), name, info, xfrm, animRes, pInfo, flavor, entrance, dInfo, dVuln2, v1, - f2, f3, f1, dVuln1, aParams, abdomenRes); + return new MP1::CBeetle(mgr.AllocateUniqueId(), name, info, xfrm, animRes, pInfo, flavor, entranceType, touchDamage, + platingVuln, tailAimReference, initialAttackDelay, retreatTime, unused, tailVuln, aParams, + tailRes); } CEntity* ScriptLoader::LoadHUDMemo(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { diff --git a/assetnameparser/CMakeLists.txt b/assetnameparser/CMakeLists.txt index a6cb672d6..ee8c30453 100644 --- a/assetnameparser/CMakeLists.txt +++ b/assetnameparser/CMakeLists.txt @@ -1,6 +1,14 @@ cmake_minimum_required(VERSION 3.10 FATAL_ERROR) # because of c++17 -set(BUILD_TESTING OFF) -add_subdirectory(tinyxml2) + +set(TINYXML_LIB_VERSION "5.0.1") +set(TINYXML_LIB_SOVERSION "5") +add_library(tinyxml2_static STATIC tinyxml2/tinyxml2.cpp tinyxml2/tinyxml2.h) +set_target_properties(tinyxml2_static PROPERTIES + COMPILE_DEFINITONS "TINYXML2_EXPORT" + VERSION "${TINYXML_LIB_VERSION}" + SOVERSION "${TINYXML_LIB_SOVERSION}") +set_target_properties( tinyxml2_static PROPERTIES OUTPUT_NAME tinyxml2 ) + add_executable(assetnameparser "main.cpp") include_directories(${LOGVISOR_INCLUDE_DIR}) diff --git a/hecl b/hecl index 88299f0e7..cdba678ee 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 88299f0e7bdcd60797d9788c440d940f225333ea +Subproject commit cdba678eee605cf0aff96f1276bc3593fca0de2b