mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-01 08:27:46 +00:00
Gambit packs added. Basic timelines for bnpc actions can be defined.
This commit is contained in:
parent
4f3f866531
commit
928729326c
6 changed files with 223 additions and 21 deletions
135
src/world/AI/GambitPack.cpp
Normal file
135
src/world/AI/GambitPack.cpp
Normal file
|
@ -0,0 +1,135 @@
|
|||
#include <cstdint>
|
||||
#include <ForwardsZone.h>
|
||||
#include <Service.h>
|
||||
#include <Manager/ActionMgr.h>
|
||||
#include <Action/Action.h>
|
||||
#include "GambitTargetCondition.h"
|
||||
#include "GambitRule.h"
|
||||
#include "GambitPack.h"
|
||||
|
||||
using namespace Sapphire;
|
||||
using namespace Sapphire::World;
|
||||
|
||||
AI::GambitTimeLinePack::GambitTimeLinePack( int8_t loopCount ) :
|
||||
GambitPack( GambitPackType::TimeLine ),
|
||||
m_loopCount( loopCount ),
|
||||
m_currentIndex( 0 ),
|
||||
m_currentLoop( 0 ),
|
||||
m_startTimeMs( 0 )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void AI::GambitTimeLinePack::start()
|
||||
{
|
||||
m_startTimeMs = Common::Util::getTimeMs();
|
||||
}
|
||||
|
||||
void AI::GambitTimeLinePack::addTimeLine( const GambitRulePtr& pRule, uint32_t offsetInSeconds )
|
||||
{
|
||||
auto timeLine = std::make_pair( pRule, offsetInSeconds );
|
||||
m_gambits.push_back( timeLine );
|
||||
}
|
||||
|
||||
void AI::GambitTimeLinePack::addTimeLine( const GambitTargetConditionPtr& targetCondition, const Action::ActionPtr& action, uint32_t offsetInSeconds )
|
||||
{
|
||||
auto pRule = make_GambitRule( targetCondition, action, 0 );
|
||||
auto timeLine = std::make_pair( pRule, offsetInSeconds );
|
||||
m_gambits.push_back( timeLine );
|
||||
}
|
||||
|
||||
uint8_t AI::GambitTimeLinePack::getLoopCount() const
|
||||
{
|
||||
return m_loopCount;
|
||||
}
|
||||
|
||||
uint8_t AI::GambitTimeLinePack::getCurrentIndex() const
|
||||
{
|
||||
return m_currentIndex;
|
||||
}
|
||||
|
||||
void AI::GambitTimeLinePack::update( Entity::BNpc& bnpc, uint64_t tickCount )
|
||||
{
|
||||
if( m_startTimeMs == 0 || m_gambits.empty() )
|
||||
return;
|
||||
|
||||
auto& actionMgr = Common::Service< World::Manager::ActionMgr >::ref();
|
||||
|
||||
if( m_gambits.size() <= m_currentIndex )
|
||||
{
|
||||
if( m_currentLoop < m_loopCount || m_loopCount == -1 )
|
||||
{
|
||||
m_currentIndex = 0;
|
||||
m_currentLoop++;
|
||||
m_startTimeMs = Common::Util::getTimeMs();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_startTimeMs = 0;
|
||||
m_currentLoop = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto currentTimeLine = m_gambits.at( m_currentIndex );
|
||||
auto& pRule = currentTimeLine.first;
|
||||
auto offset = currentTimeLine.second * 1000;
|
||||
|
||||
if( tickCount - m_startTimeMs >= offset )
|
||||
{
|
||||
if( pRule->getGambitTargetCondition()->isConditionMet( bnpc ) )
|
||||
{
|
||||
pRule->setLastExecutionMs( tickCount );
|
||||
actionMgr.handleTargetedAction( bnpc, pRule->getActionPtr()->getId(), pRule->getGambitTargetCondition()->getTarget()->getId(), 0 );
|
||||
}
|
||||
m_currentIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AI::GambitRuleSetPack::GambitRuleSetPack() : GambitPack( GambitPackType::RuleSetList )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void AI::GambitRuleSetPack::addRule( const GambitRulePtr& pRule )
|
||||
{
|
||||
m_gambits.push_back( pRule );
|
||||
}
|
||||
|
||||
void AI::GambitRuleSetPack::addRule( const GambitTargetConditionPtr& targetCondition, const Action::ActionPtr& action, uint32_t coolDown )
|
||||
{
|
||||
auto pRule = make_GambitRule( targetCondition, action, coolDown );
|
||||
m_gambits.push_back( pRule );
|
||||
}
|
||||
|
||||
void AI::GambitRuleSetPack::update( Entity::BNpc& bnpc, uint64_t tickCount )
|
||||
{
|
||||
auto& actionMgr = Common::Service< World::Manager::ActionMgr >::ref();
|
||||
for( auto& gambitRule : m_gambits )
|
||||
{
|
||||
if( !gambitRule->isEnabled() )
|
||||
continue;
|
||||
|
||||
if( ( tickCount - gambitRule->getLastExecutionMs() ) > gambitRule->getCoolDown() )
|
||||
{
|
||||
if( !gambitRule->getGambitTargetCondition()->isConditionMet( bnpc ) )
|
||||
continue;
|
||||
|
||||
gambitRule->setLastExecutionMs( tickCount );
|
||||
actionMgr.handleTargetedAction( bnpc, gambitRule->getActionPtr()->getId(), gambitRule->getGambitTargetCondition()->getTarget()->getId(), 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AI::GambitTimeLinePackPtr AI::GambitPack::getAsTimeLine()
|
||||
{
|
||||
return std::dynamic_pointer_cast< GambitTimeLinePack, GambitPack >( shared_from_this() );
|
||||
}
|
||||
|
||||
AI::GambitRuleSetPackPtr AI::GambitPack::getAsRuleSet()
|
||||
{
|
||||
return std::dynamic_pointer_cast< GambitRuleSetPack, GambitPack >( shared_from_this() );
|
||||
}
|
60
src/world/AI/GambitPack.h
Normal file
60
src/world/AI/GambitPack.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
#include <cstdint>
|
||||
#include <ForwardsZone.h>
|
||||
#include "GambitTargetCondition.h"
|
||||
#include "GambitRule.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Sapphire::World::AI
|
||||
{
|
||||
enum class GambitPackType : uint8_t
|
||||
{
|
||||
None,
|
||||
RuleSetList,
|
||||
TimeLine
|
||||
};
|
||||
|
||||
class GambitPack : public std::enable_shared_from_this< GambitPack >
|
||||
{
|
||||
public:
|
||||
GambitPack( GambitPackType type ) : m_type( type ) { };
|
||||
virtual ~GambitPack() = default;
|
||||
GambitPackType getType() const { return m_type; }
|
||||
virtual void update( Entity::BNpc& bnpc, uint64_t tickCount ) = 0;
|
||||
GambitTimeLinePackPtr getAsTimeLine();
|
||||
GambitRuleSetPackPtr getAsRuleSet();
|
||||
private:
|
||||
GambitPackType m_type;
|
||||
};
|
||||
|
||||
class GambitTimeLinePack : public GambitPack
|
||||
{
|
||||
public:
|
||||
GambitTimeLinePack( int8_t loopCount );
|
||||
void update( Entity::BNpc& bnpc, uint64_t tickCount );
|
||||
void addTimeLine( const GambitRulePtr& pRule, uint32_t offsetInSeconds );
|
||||
void addTimeLine( const GambitTargetConditionPtr& targetCondition, const Action::ActionPtr& action, uint32_t offsetInSeconds );
|
||||
uint8_t getLoopCount() const;
|
||||
uint8_t getCurrentIndex() const;
|
||||
void start();
|
||||
|
||||
private:
|
||||
std::vector< std::pair< GambitRulePtr, uint32_t > > m_gambits;
|
||||
|
||||
uint64_t m_startTimeMs;
|
||||
uint8_t m_currentIndex;
|
||||
int8_t m_loopCount;
|
||||
uint8_t m_currentLoop;
|
||||
};
|
||||
|
||||
class GambitRuleSetPack : public GambitPack
|
||||
{
|
||||
public:
|
||||
GambitRuleSetPack();
|
||||
void addRule( const GambitRulePtr& pRule );
|
||||
void addRule( const GambitTargetConditionPtr& targetCondition, const Action::ActionPtr& action, uint32_t coolDown );
|
||||
void update( Entity::BNpc& bnpc, uint64_t tickCount );
|
||||
private:
|
||||
std::vector< GambitRulePtr > m_gambits;
|
||||
};
|
||||
}
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
#include <Action/Action.h>
|
||||
#include <AI/GambitRule.h>
|
||||
#include <AI/GambitPack.h>
|
||||
#include <AI/GambitTargetCondition.h>
|
||||
#include <AI/Fsm/StateMachine.h>
|
||||
#include <AI/Fsm/Condition.h>
|
||||
|
@ -598,6 +599,11 @@ void BNpc::aggro( const Sapphire::Entity::CharaPtr& pChara )
|
|||
auto& pRNGMgr = Common::Service< World::Manager::RNGMgr >::ref();
|
||||
auto variation = static_cast< uint32_t >( pRNGMgr.getRandGenerator< float >( 500, 1000 ).next() );
|
||||
|
||||
if( m_pGambitPack && m_pGambitPack->getAsTimeLine() )
|
||||
{
|
||||
m_pGambitPack->getAsTimeLine()->start();
|
||||
}
|
||||
|
||||
m_lastAttack = Common::Util::getTimeMs() + variation;
|
||||
|
||||
setStance( Stance::Active );
|
||||
|
@ -911,9 +917,22 @@ void BNpc::init()
|
|||
//setup a test gambit
|
||||
auto testGambitRule = AI::make_GambitRule( AI::make_TopHateTargetCondition(), Action::make_Action( getAsChara(), 88, 0 ), 5000 );
|
||||
auto testGambitRule1 = AI::make_GambitRule( AI::make_HPSelfPctLessThanTargetCondition( 50 ), Action::make_Action( getAsChara(), 120, 0 ), 5000 );
|
||||
/*
|
||||
auto gambitPack = AI::make_GambitRuleSetPack();
|
||||
gambitPack->addRule( AI::make_TopHateTargetCondition(), Action::make_Action( getAsChara(), 88, 0 ), 5000 );
|
||||
gambitPack->addRule( AI::make_HPSelfPctLessThanTargetCondition( 50 ), Action::make_Action( getAsChara(), 120, 0 ), 10000 );
|
||||
m_pGambitPack = gambitPack;
|
||||
*/
|
||||
|
||||
m_gambits.push_back( testGambitRule );
|
||||
m_gambits.push_back( testGambitRule1 );
|
||||
auto gambitPack = AI::make_GambitTimeLinePack( -1 );
|
||||
gambitPack->addTimeLine( AI::make_TopHateTargetCondition(), Action::make_Action( getAsChara(), 88, 0 ), 2 );
|
||||
gambitPack->addTimeLine( AI::make_TopHateTargetCondition(), Action::make_Action( getAsChara(), 89, 0 ), 4 );
|
||||
gambitPack->addTimeLine( AI::make_TopHateTargetCondition(), Action::make_Action( getAsChara(), 90, 0 ), 6 );
|
||||
gambitPack->addTimeLine( AI::make_TopHateTargetCondition(), Action::make_Action( getAsChara(), 91, 0 ), 8 );
|
||||
gambitPack->addTimeLine( AI::make_TopHateTargetCondition(), Action::make_Action( getAsChara(), 92, 0 ), 10 );
|
||||
gambitPack->addTimeLine( AI::make_TopHateTargetCondition(), Action::make_Action( getAsChara(), 81, 0 ), 12 );
|
||||
gambitPack->addTimeLine( AI::make_TopHateTargetCondition(), Action::make_Action( getAsChara(), 82, 0 ), 14 );
|
||||
m_pGambitPack = gambitPack;
|
||||
|
||||
using namespace AI::Fsm;
|
||||
m_fsm = make_StateMachine();
|
||||
|
@ -945,23 +964,8 @@ void BNpc::init()
|
|||
|
||||
void BNpc::processGambits( uint64_t tickCount )
|
||||
{
|
||||
auto& actionMgr = Common::Service< World::Manager::ActionMgr >::ref();
|
||||
for( auto& gambitRule : m_gambits )
|
||||
{
|
||||
if( !gambitRule->isEnabled() )
|
||||
continue;
|
||||
|
||||
if( ( tickCount - gambitRule->getLastExecutionMs() ) > gambitRule->getCoolDown() )
|
||||
{
|
||||
if( !gambitRule->getGambitTargetCondition()->isConditionMet( *this ) )
|
||||
continue;
|
||||
|
||||
gambitRule->setLastExecutionMs( tickCount );
|
||||
actionMgr.handleTargetedAction( *this, gambitRule->getActionPtr()->getId(), gambitRule->getGambitTargetCondition()->getTarget()->getId(), 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
m_tp = 1000;
|
||||
m_pGambitPack->update( *this, tickCount );
|
||||
}
|
||||
|
||||
uint32_t BNpc::getLastRoamTargetReachedTime() const
|
||||
|
|
|
@ -206,7 +206,7 @@ namespace Sapphire::Entity
|
|||
Common::FFXIVARR_POSITION3 m_naviTarget;
|
||||
|
||||
CharaPtr m_pOwner;
|
||||
std::vector< World::AI::GambitRulePtr > m_gambits;
|
||||
World::AI::GambitPackPtr m_pGambitPack;
|
||||
|
||||
std::shared_ptr< World::AI::Fsm::StateMachine > m_fsm;
|
||||
|
||||
|
|
|
@ -54,6 +54,9 @@ namespace World::AI
|
|||
TYPE_FORWARD( HPSelfPctLessThanTargetCondition );
|
||||
|
||||
TYPE_FORWARD( GambitRule );
|
||||
TYPE_FORWARD( GambitPack );
|
||||
TYPE_FORWARD( GambitTimeLinePack );
|
||||
TYPE_FORWARD( GambitRuleSetPack );
|
||||
}
|
||||
|
||||
namespace World::AI::Fsm
|
||||
|
|
|
@ -313,7 +313,7 @@ void PlayerMgr::onUpdate( Entity::Player& player, uint64_t tickCount )
|
|||
void PlayerMgr::checkAutoAttack( Entity::Player& player, uint64_t tickCount ) const
|
||||
{
|
||||
auto mainWeap = player.getItemAt( Common::GearSet0, Common::MainHand );
|
||||
if( !mainWeap || !player.isAutoattackOn() || player.checkAction() || !player.getTargetId() || player.getStance() != Common::Active )
|
||||
if( !mainWeap || player.checkAction() || !player.isAutoattackOn() || !player.getTargetId() || player.getStance() != Common::Active )
|
||||
return;
|
||||
|
||||
for( const auto& actor : player.getInRangeActors() )
|
||||
|
|
Loading…
Add table
Reference in a new issue