From 94333e47260c7f33a5142fcf08e013e557d309c9 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sat, 10 Nov 2018 20:24:24 -1000 Subject: [PATCH] Finish CStateMachine --- Runtime/World/CAiFuncMap.hpp | 6 +-- Runtime/World/CPatterned.cpp | 26 +++++----- Runtime/World/CPatterned.hpp | 1 - Runtime/World/CStateMachine.cpp | 87 ++++++++++++++++++++++++++++----- Runtime/World/CStateMachine.hpp | 61 ++++++++++++++--------- 5 files changed, 128 insertions(+), 53 deletions(-) diff --git a/Runtime/World/CAiFuncMap.hpp b/Runtime/World/CAiFuncMap.hpp index 710b84ef0..515fd2d6a 100644 --- a/Runtime/World/CAiFuncMap.hpp +++ b/Runtime/World/CAiFuncMap.hpp @@ -7,9 +7,9 @@ namespace urde { enum class EStateMsg { - Zero = 0, - One = 1, - Two = 2 + Activate = 0, + Update = 1, + Deactivate = 2 }; class CStateManager; diff --git a/Runtime/World/CPatterned.cpp b/Runtime/World/CPatterned.cpp index 6ec0d6074..5e6f4dcc9 100644 --- a/Runtime/World/CPatterned.cpp +++ b/Runtime/World/CPatterned.cpp @@ -157,7 +157,7 @@ void CPatterned::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CState break; case EScriptObjectMessage::Deleted: if (x330_stateMachineState.GetActorState() != nullptr) - x330_stateMachineState.GetActorState()->CallFunc(mgr, *this, EStateMsg::Two, 0.f); + x330_stateMachineState.GetActorState()->CallFunc(mgr, *this, EStateMsg::Deactivate, 0.f); break; case EScriptObjectMessage::Damage: { @@ -787,7 +787,7 @@ void CPatterned::PathFind(CStateManager& mgr, EStateMsg msg, float arg) const auto& waypoints = search->GetWaypoints(); switch (msg) { - case EStateMsg::Zero: + case EStateMsg::Activate: { if (search->Search(GetTranslation(), x2e0_destPos) == CPathFindSearch::EResult::Success) { @@ -803,7 +803,7 @@ void CPatterned::PathFind(CStateManager& mgr, EStateMsg msg, float arg) } break; } - case EStateMsg::One: + case EStateMsg::Update: { if (curWp < waypoints.size() - 1) { @@ -830,10 +830,10 @@ void CPatterned::Dead(CStateManager& mgr, EStateMsg msg, float arg) { switch (msg) { - case EStateMsg::Zero: + case EStateMsg::Activate: x31c_faceVec = zeus::CVector3f::skZero; break; - case EStateMsg::One: + case EStateMsg::Update: x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::Die)); if (!x400_27_fadeToDeath) { @@ -854,7 +854,7 @@ void CPatterned::Dead(CStateManager& mgr, EStateMsg msg, float arg) void CPatterned::TargetPlayer(CStateManager& mgr, EStateMsg msg, float arg) { - if (msg == EStateMsg::Zero) + if (msg == EStateMsg::Activate) { x2dc_destObj = mgr.GetPlayer().GetUniqueId(); SetDestPos(mgr.GetPlayer().GetTranslation()); @@ -865,7 +865,7 @@ void CPatterned::TargetPlayer(CStateManager& mgr, EStateMsg msg, float arg) void CPatterned::TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg) { - if (msg == EStateMsg::Zero) + if (msg == EStateMsg::Activate) { x2dc_destObj = GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow); if (TCastToConstPtr act = mgr.GetObjectById(x2dc_destObj)) @@ -879,7 +879,7 @@ void CPatterned::FollowPattern(CStateManager& mgr, EStateMsg msg, float arg) { switch (msg) { - case EStateMsg::Zero: + case EStateMsg::Activate: SetupPattern(mgr); if (x328_29_noPatternShagging || !IsPatternObstructed(mgr, GetTranslation(), x2e0_destPos)) { @@ -891,7 +891,7 @@ void CPatterned::FollowPattern(CStateManager& mgr, EStateMsg msg, float arg) x400_30_patternShagged = true; } break; - case EStateMsg::One: + case EStateMsg::Update: if (x328_24_inPosition) { x39c_curPattern += 1; @@ -917,7 +917,7 @@ void CPatterned::FollowPattern(CStateManager& mgr, EStateMsg msg, float arg) } ApproachDest(mgr); break; - case EStateMsg::Two: + case EStateMsg::Deactivate: x38c_patterns.clear(); x400_30_patternShagged = false; } @@ -927,7 +927,7 @@ void CPatterned::Patrol(CStateManager& mgr, EStateMsg msg, float arg) { switch (msg) { - case EStateMsg::Zero: + case EStateMsg::Activate: if (x3ac_lastPatrolDest == kInvalidUniqueId) { x2dc_destObj = GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow); @@ -951,7 +951,7 @@ void CPatterned::Patrol(CStateManager& mgr, EStateMsg msg, float arg) x2d8_patrolState = EPatrolState::Patrol; x2f8_waypointPauseRemTime = 0.f; break; - case EStateMsg::One: + case EStateMsg::Update: switch (x2d8_patrolState) { case EPatrolState::Patrol: @@ -983,7 +983,7 @@ void CPatterned::Patrol(CStateManager& mgr, EStateMsg msg, float arg) break; } break; - case EStateMsg::Two: + case EStateMsg::Deactivate: x3ac_lastPatrolDest = x2dc_destObj; x2d8_patrolState = EPatrolState::Invalid; break; diff --git a/Runtime/World/CPatterned.hpp b/Runtime/World/CPatterned.hpp index 594f03017..7121b0ddb 100644 --- a/Runtime/World/CPatterned.hpp +++ b/Runtime/World/CPatterned.hpp @@ -398,7 +398,6 @@ public: const CKnockBackController& GetKnockBackController() const { return x460_knockBackController; } void SetupPlayerCollision(bool); - void SetDestPos(const zeus::CVector3f& pos) { x2e0_destPos = pos; } void UpdateAlphaDelta(float dt, CStateManager& mgr); void SetModelAlpha(float a) { x42c_color.a = a; } diff --git a/Runtime/World/CStateMachine.cpp b/Runtime/World/CStateMachine.cpp index 2f8773468..104c42641 100644 --- a/Runtime/World/CStateMachine.cpp +++ b/Runtime/World/CStateMachine.cpp @@ -1,20 +1,21 @@ #include "CStateMachine.hpp" #include "CAi.hpp" +#include "CStateManager.hpp" namespace urde { CStateMachine::CStateMachine(CInputStream& in) { -#if 0 + CAiTrigger* lastTrig = nullptr; u32 stateCount = in.readUint32Big(); x0_states.reserve(stateCount); for (u32 i = 0; i < stateCount; ++i) { - std::string name = in.readString(31); + std::string name = in.readString(31, false); CAiStateFunc func = CAi::GetStateFunc(name.c_str()); - x0_states.emplace_back(func, name); + x0_states.emplace_back(func, name.c_str()); } x10_triggers.reserve(in.readUint32Big()); @@ -24,27 +25,43 @@ CStateMachine::CStateMachine(CInputStream& in) x0_states[i].SetNumTriggers(in.readUint32Big()); if (x0_states[i].GetNumTriggers() == 0) continue; - for (u32 j = 0; j < x0_states[i].GetNumTriggers(); ++j) - x10_triggers.emplace_back(); + CAiTrigger* firstTrig = x10_triggers.data() + x10_triggers.size(); + x0_states[i].SetTriggers(firstTrig); + x10_triggers.resize(x10_triggers.size() + x0_states[i].GetNumTriggers()); for (u32 j = 0; j < x0_states[i].GetNumTriggers(); ++j) { u32 triggerCount = in.readUint32Big(); - u32 r19 = triggerCount - 1; + u32 lastTriggerIdx = triggerCount - 1; for (u32 k = 0; k < triggerCount; ++k) { - std::string name = in.readString(31); - CAiTriggerFunc func = CAi::GetTrigerFunc(name.c_str()); - float f31 = in.readFloatBig(); + std::string name = in.readString(31, false); + bool isNot = name.front() == '!'; + CAiTriggerFunc func = CAi::GetTrigerFunc(isNot ? name.c_str() + 1 : name.c_str()); + float arg = in.readFloatBig(); + CAiTrigger* newTrig; + if (k < lastTriggerIdx) + { + x10_triggers.emplace_back(); + newTrig = &x10_triggers.back(); + } + else + { + newTrig = &firstTrig[j]; + } + if (k == 0) + newTrig->Setup(func, isNot, arg, &x0_states[in.readUint32Big()]); + else + newTrig->Setup(func, isNot, arg, lastTrig); + lastTrig = newTrig; } } } -#endif } s32 CStateMachine::GetStateIndex(std::string_view state) const { - auto it = std::find_if(x0_states.begin(), x0_states.end(), [&state](const CAiState& st) -> bool { + auto it = std::find_if(x0_states.begin(), x0_states.end(), [&state](const CAiState& st) { return (strncmp(st.GetName(), state.data(), 31) == 0); }); if (it == x0_states.end()) @@ -53,8 +70,54 @@ s32 CStateMachine::GetStateIndex(std::string_view state) const return it - x0_states.begin(); } -void CStateMachineState::SetState(CStateManager &, CAi &, s32 idx) +void CStateMachineState::Update(CStateManager& mgr, CAi& ai, float delta) { + if (x4_state) + { + x8_time += delta; + x4_state->CallFunc(mgr, ai, EStateMsg::Update, delta); + for (int i = 0; i < x4_state->GetNumTriggers(); ++i) + { + CAiTrigger* trig = x4_state->GetTrig(i); + CAiState* state = nullptr; + bool andPassed = true; + while (andPassed && trig) + { + andPassed = false; + if (trig->CallFunc(mgr, ai)) + { + andPassed = true; + state = trig->GetState(); + trig = trig->GetAnd(); + } + } + if (andPassed && state) + { + x4_state->CallFunc(mgr, ai, EStateMsg::Deactivate, 0.f); + x4_state = state; + x8_time = 0.f; + x18_24_ = false; + xc_random = mgr.GetActiveRandom()->Float(); + x4_state->CallFunc(mgr, ai, EStateMsg::Activate, delta); + return; + } + } + } +} + +void CStateMachineState::SetState(CStateManager& mgr, CAi& ai, s32 idx) +{ + CAiState* state = const_cast(&x0_machine->GetStateVector()[idx]); + if (x4_state != state) + { + if (x4_state) + x4_state->CallFunc(mgr, ai, EStateMsg::Deactivate, 0.f); + x4_state = state; + x8_time = 0.f; + xc_random = mgr.GetActiveRandom()->Float(); + x18_24_ = false; + x4_state->CallFunc(mgr, ai, EStateMsg::Activate, 0.f); + } } void CStateMachineState::SetState(CStateManager& mgr, CAi& ai, const CStateMachine* machine, std::string_view state) diff --git a/Runtime/World/CStateMachine.hpp b/Runtime/World/CStateMachine.hpp index 4856de087..63707069c 100644 --- a/Runtime/World/CStateMachine.hpp +++ b/Runtime/World/CStateMachine.hpp @@ -12,24 +12,39 @@ class CAiState; class CStateManager; class CAiTrigger { - u32 x0_ = 0; - u32 x4_ = 0; - u32 x8_ = 0; - float xc_ = 0.f; - u32 x10_ = 0; - u32 x14_ = 0; - bool x18_ = false; + CAiTriggerFunc x0_func; + float xc_arg = 0.f; + CAiTrigger* x10_andTrig = nullptr; + CAiState* x14_state = nullptr; + bool x18_lNot = false; public: CAiTrigger() = default; - bool GetAnd(); - void GetState(); - bool CallFunc(CStateManager&, CAi&) + CAiTrigger* GetAnd() const { return x10_andTrig; } + CAiState* GetState() const { return x14_state; } + bool CallFunc(CStateManager& mgr, CAi& ai) { - return false; + if (x0_func) + { + bool ret = (ai.*x0_func)(mgr, xc_arg); + return x18_lNot ? !ret : ret; + } + return true; } - void Setup(CAiTriggerFunc func, bool, float, CAiTrigger*); - void Setup(CAiTriggerFunc func, bool, float, CAiState*); + void Setup(CAiTriggerFunc func, bool lnot, float arg, CAiTrigger* andTrig) + { + x0_func = func; + x18_lNot = lnot; + xc_arg = arg; + x10_andTrig = andTrig; + } + void Setup(CAiTriggerFunc func, bool lnot, float arg, CAiState* state) + { + x0_func = func; + x18_lNot = lnot; + xc_arg = arg; + x14_state = state; + } }; class CAiState @@ -38,15 +53,18 @@ class CAiState CAiStateFunc x0_func; char xc_name[32]; u32 x2c_numTriggers; - u32 x30_; + CAiTrigger* x30_firstTrigger; public: CAiState(CAiStateFunc func, const char* name) - {} + { + x0_func = func; + strncpy(xc_name, name, 32); + } - s32 GetNumTriggers() const; - CAiTrigger& GetTrig(s32) const; + s32 GetNumTriggers() const { return x2c_numTriggers; } + CAiTrigger* GetTrig(s32 i) const { return &x30_firstTrigger[i]; } const char* GetName() const { return xc_name; } - void SetTriggers(CAiTrigger* triggers); + void SetTriggers(CAiTrigger* triggers) { x30_firstTrigger = triggers; } void SetNumTriggers(s32 numTriggers) { x2c_numTriggers = numTriggers; } void CallFunc(CStateManager& mgr, CAi& ai, EStateMsg msg, float delta) const { @@ -88,12 +106,7 @@ public: CAiState* GetActorState() const { return x4_state; } - void Update(CStateManager& mgr, CAi& ai, float delta) - { - x8_time += delta; - if (x4_state) - x4_state->CallFunc(mgr, ai, EStateMsg::One, delta); - } + void Update(CStateManager& mgr, CAi& ai, float delta); void SetState(CStateManager&, CAi&, s32); void SetState(CStateManager&, CAi&, const CStateMachine*, std::string_view); const std::vector* GetStateVector() const;