Finish CStateMachine

This commit is contained in:
Jack Andersen 2018-11-10 20:24:24 -10:00
parent 9512f6c98d
commit 94333e4726
5 changed files with 128 additions and 53 deletions

View File

@ -7,9 +7,9 @@ namespace urde
{ {
enum class EStateMsg enum class EStateMsg
{ {
Zero = 0, Activate = 0,
One = 1, Update = 1,
Two = 2 Deactivate = 2
}; };
class CStateManager; class CStateManager;

View File

@ -157,7 +157,7 @@ void CPatterned::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CState
break; break;
case EScriptObjectMessage::Deleted: case EScriptObjectMessage::Deleted:
if (x330_stateMachineState.GetActorState() != nullptr) 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; break;
case EScriptObjectMessage::Damage: case EScriptObjectMessage::Damage:
{ {
@ -787,7 +787,7 @@ void CPatterned::PathFind(CStateManager& mgr, EStateMsg msg, float arg)
const auto& waypoints = search->GetWaypoints(); const auto& waypoints = search->GetWaypoints();
switch (msg) switch (msg)
{ {
case EStateMsg::Zero: case EStateMsg::Activate:
{ {
if (search->Search(GetTranslation(), x2e0_destPos) == CPathFindSearch::EResult::Success) if (search->Search(GetTranslation(), x2e0_destPos) == CPathFindSearch::EResult::Success)
{ {
@ -803,7 +803,7 @@ void CPatterned::PathFind(CStateManager& mgr, EStateMsg msg, float arg)
} }
break; break;
} }
case EStateMsg::One: case EStateMsg::Update:
{ {
if (curWp < waypoints.size() - 1) if (curWp < waypoints.size() - 1)
{ {
@ -830,10 +830,10 @@ void CPatterned::Dead(CStateManager& mgr, EStateMsg msg, float arg)
{ {
switch (msg) switch (msg)
{ {
case EStateMsg::Zero: case EStateMsg::Activate:
x31c_faceVec = zeus::CVector3f::skZero; x31c_faceVec = zeus::CVector3f::skZero;
break; break;
case EStateMsg::One: case EStateMsg::Update:
x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::Die)); x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::Die));
if (!x400_27_fadeToDeath) 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) void CPatterned::TargetPlayer(CStateManager& mgr, EStateMsg msg, float arg)
{ {
if (msg == EStateMsg::Zero) if (msg == EStateMsg::Activate)
{ {
x2dc_destObj = mgr.GetPlayer().GetUniqueId(); x2dc_destObj = mgr.GetPlayer().GetUniqueId();
SetDestPos(mgr.GetPlayer().GetTranslation()); 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) 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); x2dc_destObj = GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow);
if (TCastToConstPtr<CActor> act = mgr.GetObjectById(x2dc_destObj)) if (TCastToConstPtr<CActor> act = mgr.GetObjectById(x2dc_destObj))
@ -879,7 +879,7 @@ void CPatterned::FollowPattern(CStateManager& mgr, EStateMsg msg, float arg)
{ {
switch (msg) switch (msg)
{ {
case EStateMsg::Zero: case EStateMsg::Activate:
SetupPattern(mgr); SetupPattern(mgr);
if (x328_29_noPatternShagging || !IsPatternObstructed(mgr, GetTranslation(), x2e0_destPos)) 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; x400_30_patternShagged = true;
} }
break; break;
case EStateMsg::One: case EStateMsg::Update:
if (x328_24_inPosition) if (x328_24_inPosition)
{ {
x39c_curPattern += 1; x39c_curPattern += 1;
@ -917,7 +917,7 @@ void CPatterned::FollowPattern(CStateManager& mgr, EStateMsg msg, float arg)
} }
ApproachDest(mgr); ApproachDest(mgr);
break; break;
case EStateMsg::Two: case EStateMsg::Deactivate:
x38c_patterns.clear(); x38c_patterns.clear();
x400_30_patternShagged = false; x400_30_patternShagged = false;
} }
@ -927,7 +927,7 @@ void CPatterned::Patrol(CStateManager& mgr, EStateMsg msg, float arg)
{ {
switch (msg) switch (msg)
{ {
case EStateMsg::Zero: case EStateMsg::Activate:
if (x3ac_lastPatrolDest == kInvalidUniqueId) if (x3ac_lastPatrolDest == kInvalidUniqueId)
{ {
x2dc_destObj = GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow); 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; x2d8_patrolState = EPatrolState::Patrol;
x2f8_waypointPauseRemTime = 0.f; x2f8_waypointPauseRemTime = 0.f;
break; break;
case EStateMsg::One: case EStateMsg::Update:
switch (x2d8_patrolState) switch (x2d8_patrolState)
{ {
case EPatrolState::Patrol: case EPatrolState::Patrol:
@ -983,7 +983,7 @@ void CPatterned::Patrol(CStateManager& mgr, EStateMsg msg, float arg)
break; break;
} }
break; break;
case EStateMsg::Two: case EStateMsg::Deactivate:
x3ac_lastPatrolDest = x2dc_destObj; x3ac_lastPatrolDest = x2dc_destObj;
x2d8_patrolState = EPatrolState::Invalid; x2d8_patrolState = EPatrolState::Invalid;
break; break;

View File

@ -398,7 +398,6 @@ public:
const CKnockBackController& GetKnockBackController() const { return x460_knockBackController; } const CKnockBackController& GetKnockBackController() const { return x460_knockBackController; }
void SetupPlayerCollision(bool); void SetupPlayerCollision(bool);
void SetDestPos(const zeus::CVector3f& pos) { x2e0_destPos = pos; } void SetDestPos(const zeus::CVector3f& pos) { x2e0_destPos = pos; }
void UpdateAlphaDelta(float dt, CStateManager& mgr); void UpdateAlphaDelta(float dt, CStateManager& mgr);
void SetModelAlpha(float a) { x42c_color.a = a; } void SetModelAlpha(float a) { x42c_color.a = a; }

View File

@ -1,20 +1,21 @@
#include "CStateMachine.hpp" #include "CStateMachine.hpp"
#include "CAi.hpp" #include "CAi.hpp"
#include "CStateManager.hpp"
namespace urde namespace urde
{ {
CStateMachine::CStateMachine(CInputStream& in) CStateMachine::CStateMachine(CInputStream& in)
{ {
#if 0 CAiTrigger* lastTrig = nullptr;
u32 stateCount = in.readUint32Big(); u32 stateCount = in.readUint32Big();
x0_states.reserve(stateCount); x0_states.reserve(stateCount);
for (u32 i = 0; i < stateCount; ++i) 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()); 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()); x10_triggers.reserve(in.readUint32Big());
@ -24,27 +25,43 @@ CStateMachine::CStateMachine(CInputStream& in)
x0_states[i].SetNumTriggers(in.readUint32Big()); x0_states[i].SetNumTriggers(in.readUint32Big());
if (x0_states[i].GetNumTriggers() == 0) if (x0_states[i].GetNumTriggers() == 0)
continue; continue;
for (u32 j = 0; j < x0_states[i].GetNumTriggers(); ++j) CAiTrigger* firstTrig = x10_triggers.data() + x10_triggers.size();
x10_triggers.emplace_back(); 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) for (u32 j = 0; j < x0_states[i].GetNumTriggers(); ++j)
{ {
u32 triggerCount = in.readUint32Big(); u32 triggerCount = in.readUint32Big();
u32 r19 = triggerCount - 1; u32 lastTriggerIdx = triggerCount - 1;
for (u32 k = 0; k < triggerCount; ++k) for (u32 k = 0; k < triggerCount; ++k)
{ {
std::string name = in.readString(31); std::string name = in.readString(31, false);
CAiTriggerFunc func = CAi::GetTrigerFunc(name.c_str()); bool isNot = name.front() == '!';
float f31 = in.readFloatBig(); 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 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); return (strncmp(st.GetName(), state.data(), 31) == 0);
}); });
if (it == x0_states.end()) if (it == x0_states.end())
@ -53,8 +70,54 @@ s32 CStateMachine::GetStateIndex(std::string_view state) const
return it - x0_states.begin(); 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<CAiState*>(&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) void CStateMachineState::SetState(CStateManager& mgr, CAi& ai, const CStateMachine* machine, std::string_view state)

View File

@ -12,24 +12,39 @@ class CAiState;
class CStateManager; class CStateManager;
class CAiTrigger class CAiTrigger
{ {
u32 x0_ = 0; CAiTriggerFunc x0_func;
u32 x4_ = 0; float xc_arg = 0.f;
u32 x8_ = 0; CAiTrigger* x10_andTrig = nullptr;
float xc_ = 0.f; CAiState* x14_state = nullptr;
u32 x10_ = 0; bool x18_lNot = false;
u32 x14_ = 0;
bool x18_ = false;
public: public:
CAiTrigger() = default; CAiTrigger() = default;
bool GetAnd(); CAiTrigger* GetAnd() const { return x10_andTrig; }
void GetState(); CAiState* GetState() const { return x14_state; }
bool CallFunc(CStateManager&, CAi&) 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 lnot, float arg, CAiTrigger* andTrig)
void Setup(CAiTriggerFunc func, bool, float, CAiState*); {
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 class CAiState
@ -38,15 +53,18 @@ class CAiState
CAiStateFunc x0_func; CAiStateFunc x0_func;
char xc_name[32]; char xc_name[32];
u32 x2c_numTriggers; u32 x2c_numTriggers;
u32 x30_; CAiTrigger* x30_firstTrigger;
public: public:
CAiState(CAiStateFunc func, const char* name) CAiState(CAiStateFunc func, const char* name)
{} {
x0_func = func;
strncpy(xc_name, name, 32);
}
s32 GetNumTriggers() const; s32 GetNumTriggers() const { return x2c_numTriggers; }
CAiTrigger& GetTrig(s32) const; CAiTrigger* GetTrig(s32 i) const { return &x30_firstTrigger[i]; }
const char* GetName() const { return xc_name; } 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 SetNumTriggers(s32 numTriggers) { x2c_numTriggers = numTriggers; }
void CallFunc(CStateManager& mgr, CAi& ai, EStateMsg msg, float delta) const void CallFunc(CStateManager& mgr, CAi& ai, EStateMsg msg, float delta) const
{ {
@ -88,12 +106,7 @@ public:
CAiState* GetActorState() const { return x4_state; } CAiState* GetActorState() const { return x4_state; }
void Update(CStateManager& mgr, CAi& ai, float delta) void Update(CStateManager& mgr, CAi& ai, float delta);
{
x8_time += delta;
if (x4_state)
x4_state->CallFunc(mgr, ai, EStateMsg::One, delta);
}
void SetState(CStateManager&, CAi&, s32); void SetState(CStateManager&, CAi&, s32);
void SetState(CStateManager&, CAi&, const CStateMachine*, std::string_view); void SetState(CStateManager&, CAi&, const CStateMachine*, std::string_view);
const std::vector<CAiState>* GetStateVector() const; const std::vector<CAiState>* GetStateVector() const;