mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-06 10:47:45 +00:00
Added the framework for a fsm for future use on bnpcs.
This commit is contained in:
parent
fe9a2ef974
commit
e72fe535f6
7 changed files with 189 additions and 41 deletions
38
src/world/AI/Fsm.cpp
Normal file
38
src/world/AI/Fsm.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include <cstdint>
|
||||||
|
#include <ForwardsZone.h>
|
||||||
|
#include <Actor/BNpc.h>
|
||||||
|
#include "Fsm.h"
|
||||||
|
#include "FsmState.h"
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
using namespace Sapphire;
|
||||||
|
using namespace Sapphire::World;
|
||||||
|
|
||||||
|
AI::FsmStatePtr AI::Fsm::addState( FsmStatePtr state )
|
||||||
|
{
|
||||||
|
m_states.push_back( state );
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AI::Fsm::setCurrentState( FsmStatePtr state )
|
||||||
|
{
|
||||||
|
m_pCurrentState = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AI::Fsm::update( Entity::BNpc& bnpc, float deltaTime )
|
||||||
|
{
|
||||||
|
if( !m_pCurrentState )
|
||||||
|
return;
|
||||||
|
|
||||||
|
FsmTransitionPtr transition = m_pCurrentState->getTriggeredTransition( bnpc );
|
||||||
|
|
||||||
|
if( transition )
|
||||||
|
{
|
||||||
|
m_pCurrentState->onExit( bnpc );
|
||||||
|
m_pCurrentState = transition->getTargetState();
|
||||||
|
m_pCurrentState->onEnter( bnpc );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pCurrentState->onUpdate( bnpc, deltaTime );
|
||||||
|
}
|
23
src/world/AI/Fsm.h
Normal file
23
src/world/AI/Fsm.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#include <cstdint>
|
||||||
|
#include <ForwardsZone.h>
|
||||||
|
#include <Actor/BNpc.h>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Sapphire::World::AI
|
||||||
|
{
|
||||||
|
class Fsm
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Fsm() = default;
|
||||||
|
~Fsm() = default;
|
||||||
|
|
||||||
|
FsmStatePtr addState( FsmStatePtr state );
|
||||||
|
void setCurrentState( FsmStatePtr state );
|
||||||
|
virtual void update( Entity::BNpc& bnpc, float deltaTime );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector< FsmStatePtr > m_states;
|
||||||
|
FsmStatePtr m_pCurrentState;
|
||||||
|
};
|
||||||
|
}
|
23
src/world/AI/FsmCondition.h
Normal file
23
src/world/AI/FsmCondition.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#include <cstdint>
|
||||||
|
#include <ForwardsZone.h>
|
||||||
|
#include <Actor/BNpc.h>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Sapphire::World::AI
|
||||||
|
{
|
||||||
|
class FsmCondition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FsmCondition() = default;
|
||||||
|
virtual ~FsmCondition() = default;
|
||||||
|
|
||||||
|
virtual bool isConditionMet( Sapphire::Entity::BNpc& src ) const = 0;
|
||||||
|
virtual bool update( Sapphire::Entity::BNpc& src, float time )
|
||||||
|
{
|
||||||
|
if( isConditionMet( src ) )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
37
src/world/AI/FsmState.h
Normal file
37
src/world/AI/FsmState.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#include <cstdint>
|
||||||
|
#include <ForwardsZone.h>
|
||||||
|
#include <Actor/BNpc.h>
|
||||||
|
#include "FsmTransition.h"
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Sapphire::World::AI
|
||||||
|
{
|
||||||
|
class FsmState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~FsmState() = default;
|
||||||
|
|
||||||
|
virtual void onUpdate( Entity::BNpc& bnpc, float deltaTime ) = 0;
|
||||||
|
virtual void onEnter( Entity::BNpc& bnpc ) { }
|
||||||
|
virtual void onExit( Entity::BNpc& bnpc ) { }
|
||||||
|
|
||||||
|
void addTransition( FsmTransitionPtr transition )
|
||||||
|
{
|
||||||
|
m_transitions.push_back( transition );
|
||||||
|
}
|
||||||
|
|
||||||
|
FsmTransitionPtr getTriggeredTransition( Entity::BNpc& bnpc )
|
||||||
|
{
|
||||||
|
for( auto transition : m_transitions )
|
||||||
|
{
|
||||||
|
if( transition->hasTriggered( bnpc ) )
|
||||||
|
return transition;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector< FsmTransitionPtr > m_transitions;
|
||||||
|
};
|
||||||
|
}
|
22
src/world/AI/FsmTransition.h
Normal file
22
src/world/AI/FsmTransition.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include <cstdint>
|
||||||
|
#include <ForwardsZone.h>
|
||||||
|
#include <Actor/BNpc.h>
|
||||||
|
#include "FsmCondition.h"
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Sapphire::World::AI
|
||||||
|
{
|
||||||
|
class FsmTransition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FsmTransition( FsmStatePtr targetState, FsmConditionPtr condition ) : m_pTargetState( targetState ), m_pCondition( condition ) { }
|
||||||
|
virtual ~FsmTransition() = default;
|
||||||
|
|
||||||
|
FsmStatePtr getTargetState() { return m_pTargetState; }
|
||||||
|
bool hasTriggered( Entity::BNpc& bnpc ) { return m_pCondition->isConditionMet( bnpc ); }
|
||||||
|
private:
|
||||||
|
FsmStatePtr m_pTargetState;
|
||||||
|
FsmConditionPtr m_pCondition;
|
||||||
|
};
|
||||||
|
}
|
|
@ -649,6 +649,8 @@ void BNpc::update( uint64_t tickCount )
|
||||||
if( !pNaviProvider )
|
if( !pNaviProvider )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Chara::update( tickCount );
|
||||||
|
|
||||||
if( !checkAction() )
|
if( !checkAction() )
|
||||||
processGambits( tickCount );
|
processGambits( tickCount );
|
||||||
|
|
||||||
|
@ -740,14 +742,22 @@ void BNpc::update( uint64_t tickCount )
|
||||||
|
|
||||||
auto distanceOrig = Common::Util::distance( getPos(), m_spawnPos );
|
auto distanceOrig = Common::Util::distance( getPos(), m_spawnPos );
|
||||||
|
|
||||||
if( pHatedActor && !pHatedActor->isAlive() )
|
if( !pHatedActor->isAlive() || getTerritoryId() != pHatedActor->getTerritoryId() )
|
||||||
{
|
{
|
||||||
hateListRemove( pHatedActor );
|
hateListRemove( pHatedActor );
|
||||||
pHatedActor = hateListGetHighest();
|
pHatedActor = hateListGetHighest();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( pHatedActor )
|
if( !pHatedActor )
|
||||||
{
|
{
|
||||||
|
changeTarget( INVALID_GAME_OBJECT_ID64 );
|
||||||
|
setStance( Stance::Passive );
|
||||||
|
//setOwner( nullptr );
|
||||||
|
m_state = BNpcState::Retreat;
|
||||||
|
pNaviProvider->updateAgentParameters( *this );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
auto distance = Common::Util::distance( getPos(), pHatedActor->getPos() );
|
auto distance = Common::Util::distance( getPos(), pHatedActor->getPos() );
|
||||||
|
|
||||||
if( !hasFlag( NoDeaggro ) && ( ( distanceOrig > maxDistanceToOrigin ) || distance > 30.0f ) )
|
if( !hasFlag( NoDeaggro ) && ( ( distanceOrig > maxDistanceToOrigin ) || distance > 30.0f ) )
|
||||||
|
@ -782,21 +792,11 @@ void BNpc::update( uint64_t tickCount )
|
||||||
// in combat range. ATTACK!
|
// in combat range. ATTACK!
|
||||||
autoAttack( pHatedActor );
|
autoAttack( pHatedActor );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
changeTarget( INVALID_GAME_OBJECT_ID64 );
|
|
||||||
setStance( Stance::Passive );
|
|
||||||
//setOwner( nullptr );
|
|
||||||
m_state = BNpcState::Retreat;
|
|
||||||
pNaviProvider->updateAgentParameters( *this );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Chara::update( tickCount );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BNpc::restHp()
|
void BNpc::restHp()
|
||||||
|
|
|
@ -54,6 +54,11 @@ namespace World::AI
|
||||||
TYPE_FORWARD( HPSelfPctLessThanTargetCondition );
|
TYPE_FORWARD( HPSelfPctLessThanTargetCondition );
|
||||||
|
|
||||||
TYPE_FORWARD( GambitRule );
|
TYPE_FORWARD( GambitRule );
|
||||||
|
|
||||||
|
TYPE_FORWARD( FsmCondition );
|
||||||
|
TYPE_FORWARD( FsmState );
|
||||||
|
TYPE_FORWARD( FsmTransition );
|
||||||
|
TYPE_FORWARD( Fsm );
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Inventory
|
namespace Inventory
|
||||||
|
|
Loading…
Add table
Reference in a new issue