1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-05 02:07:46 +00:00

EncounterFight and state refactor;

This commit is contained in:
Alice Ogeda 2023-03-24 11:21:09 -03:00 committed by Tahir
parent 9d49139a0c
commit 6bd8dee22d
3 changed files with 164 additions and 153 deletions

View file

@ -7,6 +7,8 @@
namespace Sapphire namespace Sapphire
{ {
using EncounterCallback = std::function< void( EncounterFightPtr, EncounterState ) >;
class EncounterState class EncounterState
{ {
public: public:
@ -19,6 +21,11 @@ namespace Sapphire
StateStackPtr m_stateStack; StateStackPtr m_stateStack;
std::shared_ptr< EncounterFight > m_pEncounter; std::shared_ptr< EncounterFight > m_pEncounter;
uint64_t m_startTime{ 0 }; uint64_t m_startTime{ 0 };
uint64_t m_currTime{ 0 };
EncounterCallback m_onInitCb;
EncounterCallback m_onUpdateCb;
EncounterCallback m_onFinishCb;
public: public:
EncounterState( std::shared_ptr< EncounterFight > pEncounter ) : EncounterState( std::shared_ptr< EncounterFight > pEncounter ) :
@ -26,13 +33,51 @@ namespace Sapphire
{ {
}; };
virtual ~EncounterState() = default; bool shouldFinish() const { return m_bShouldFinish; };
bool shouldFinish() { return m_bShouldFinish; };
virtual void init() = 0; void setFinishFlag() { m_bShouldFinish = true; };
virtual void update( uint64_t deltaTime ) = 0;
virtual void finish() = 0; uint64_t getStartTime() const { return m_startTime; };
uint64_t getCurrTime() const { return m_currTime; };
uint64_t getElapsedTime() const { return m_currTime - m_startTime; };
void init()
{
if( m_onInitCb )
m_onInitCb( m_pEncounter, *this );
}
void update( uint64_t currTime )
{
if( m_startTime == 0 )
m_startTime = currTime;
m_currTime = currTime;
if( m_onUpdateCb )
m_onUpdateCb( m_pEncounter, *this );
}
void finish()
{
if( m_onFinishCb )
m_onFinishCb( m_pEncounter, *this );
}
void setOnInitCallback( EncounterCallback cb )
{
m_onInitCb = cb;
}
void setOnUpdateCallback( EncounterCallback cb )
{
m_onUpdateCb = cb;
}
void setOnFinishCallback( EncounterCallback cb )
{
m_onFinishCb = cb;
}
}; };
enum class EncounterFightStatus enum class EncounterFightStatus
@ -50,19 +95,44 @@ namespace Sapphire
m_pInstance( pInstance ) m_pInstance( pInstance )
{ {
}; };
virtual ~EncounterFight() = default; virtual ~EncounterFight() = default;
virtual void init() = 0; virtual void init() = 0;
virtual void start() = 0; virtual void start() = 0;
virtual void update( uint64_t deltaTime ) = 0; virtual void update( uint64_t currTime ) = 0;
virtual void reset() = 0; virtual void reset() = 0;
virtual void addState( EncounterState::EncounterStatePtr pState, bool initState = true ) = 0; void addState( EncounterState::EncounterStatePtr pState, bool initState = true )
virtual void addBNpc( Entity::BNpcPtr pBNpc ) = 0; {
virtual void removeBNpc( uint32_t layoutId ) = 0; m_stateStack->push( pState );
virtual Entity::BNpcPtr getBNpc( uint32_t layoutId ) = 0; if( initState )
pState->init();
}
virtual EncounterFightStatus getEncounterFightStatus() const = 0; EncounterFightStatus getEncounterFightStatus() const
{
return m_status;
}
void addBNpc( Entity::BNpcPtr pBNpc )
{
m_bnpcs[ pBNpc->getLayoutId() ] = pBNpc;
}
Entity::BNpcPtr getBNpc( uint32_t layoutId ) const
{
auto bnpc = m_bnpcs.find( layoutId );
if( bnpc != std::end( m_bnpcs ) )
return bnpc->second;
return nullptr;
}
void removeBNpc( uint32_t layoutId )
{
m_bnpcs.erase( layoutId );
}
protected: protected:
uint64_t m_startTime{ 0 }; uint64_t m_startTime{ 0 };

View file

@ -2,98 +2,13 @@
namespace Sapphire namespace Sapphire
{ {
class IfritNormalData
{
public:
static constexpr int IFRIT = 4126276;
static constexpr int HELLFIRE = 0;
};
class IfritStateTwo : public EncounterState
{
public:
IfritStateTwo( EncounterFightPtr pEncounter ) : EncounterState( pEncounter )
{
}
void init() override
{
Logger::info( "stage 2 init" );
}
void update( uint64_t deltaTime ) override
{
if( m_startTime == 0 )
m_startTime = deltaTime;
auto timeElapsedMs = deltaTime - m_startTime;
auto pIfrit = m_pEncounter->getBNpc( IfritNormalData::IFRIT );
pIfrit->setRot( pIfrit->getRot() - .2f );
pIfrit->sendPositionUpdate();
if( timeElapsedMs > 5000 )
{
m_bShouldFinish = true;
}
}
void finish() override
{
Logger::info( "stage 2 done, going back to stage 1" );
}
};
class IfritStateOne : public EncounterState
{
public:
IfritStateOne( EncounterFightPtr pEncounter ) : EncounterState( pEncounter )
{
}
void init() override
{
Logger::info( "stage 1 init" );
}
void update( uint64_t deltaTime ) override
{
if( m_startTime == 0 )
m_startTime = deltaTime;
auto timeElapsedMs = deltaTime - m_startTime;
auto pIfrit = m_pEncounter->getBNpc( IfritNormalData::IFRIT );
pIfrit->setRot( pIfrit->getRot() + .2f );
pIfrit->sendPositionUpdate();
if( timeElapsedMs > 10000 )
{
m_bShouldFinish = true;
return;
}
if( timeElapsedMs > 5000 )
{
auto ifritTwoState = std::make_shared< IfritStateTwo >( m_pEncounter );
m_pEncounter->addState( ifritTwoState );
}
}
void finish() override
{
Logger::info( "stage 1 finish - enrage" );
auto pIfrit = m_pEncounter->getBNpc( IfritNormalData::IFRIT );
pIfrit->hateListGetHighest()->die();
}
};
class IfritEncounterFight : public EncounterFight class IfritEncounterFight : public EncounterFight
{ {
private:
static constexpr int NPC_IFRIT = 4126276;
static constexpr int VAL_IFRIT_HP = 13884;
static constexpr int ACT_HELLFIRE = 0;
public: public:
IfritEncounterFight( InstanceContentPtr pInstance ) : EncounterFight( pInstance ) IfritEncounterFight( InstanceContentPtr pInstance ) : EncounterFight( pInstance )
{ {
@ -108,35 +23,97 @@ namespace Sapphire
m_stateStack = std::make_shared< EncounterState::StateStack >(); m_stateStack = std::make_shared< EncounterState::StateStack >();
// todo: i don't like this // todo: i don't like this
auto boss = m_pInstance->createBNpcFromLayoutId( IfritNormalData::IFRIT, 13884, Common::BNpcType::Enemy ); auto boss = m_pInstance->createBNpcFromLayoutId( NPC_IFRIT, VAL_IFRIT_HP, Common::BNpcType::Enemy );
addBNpc( boss ); addBNpc( boss );
//instance.sendForward();
/*
auto ifritStateTwo = std::make_shared< IfritStateTwo >( m_stateStack );
m_stateStack->push( ifritStateTwo );*/
}
void addState( EncounterState::EncounterStatePtr pState, bool initState = true ) override
{
m_stateStack->push( pState );
if( initState )
pState->init();
} }
void start() override void start() override
{ {
auto ifritInitState = std::make_shared< IfritStateOne >( shared_from_this() ); auto ifritInitState = makeIfritPhaseOneState();
addState( ifritInitState ); addState( ifritInitState );
m_status = EncounterFightStatus::ACTIVE; m_status = EncounterFightStatus::ACTIVE;
} }
void reset() override
{
if( auto boss = m_pInstance->getActiveBNpcByLayoutId( NPC_IFRIT ); boss )
{
removeBNpc( NPC_IFRIT );
m_pInstance->removeActor( boss );
}
init();
}
EncounterStatePtr makeIfritPhaseOneState()
{
auto ifritInitState = std::make_shared< EncounterState >( shared_from_this() );
ifritInitState->setOnUpdateCallback( [ & ]( EncounterFightPtr pEncounter, EncounterState state )
{
auto timeElapsedMs = state.getElapsedTime();
auto pIfrit = pEncounter->getBNpc( NPC_IFRIT );
pIfrit->setRot( pIfrit->getRot() + .2f );
pIfrit->sendPositionUpdate();
// todo: use gambits+timelines for this
if( timeElapsedMs > 10000 )
{
state.setFinishFlag();
return;
}
// todo: use gambits+timelines for this
if( timeElapsedMs > 5000 )
{
auto ifritTwoState = makeIfritPhaseTwoState();
pEncounter->addState( ifritTwoState );
}
}
);
ifritInitState->setOnFinishCallback( [ & ]( EncounterFightPtr pEncounter, EncounterState state )
{
Logger::info( "stage 1 finish - enrage" );
auto pIfrit = pEncounter->getBNpc( NPC_IFRIT );
pIfrit->hateListGetHighest()->die();
}
);
return ifritInitState;
}
EncounterStatePtr makeIfritPhaseTwoState()
{
auto ifritTwoState = std::make_shared< EncounterState >( shared_from_this() );
ifritTwoState->setOnUpdateCallback( [ & ]( EncounterFightPtr pEncounter, EncounterState state ) {
auto timeElapsedMs = state.getElapsedTime();
auto pIfrit = pEncounter->getBNpc( NPC_IFRIT );
pIfrit->setRot( pIfrit->getRot() - .2f );
pIfrit->sendPositionUpdate();
// todo: use gambits+timelines for this
if( timeElapsedMs > 5000 )
{
state.setFinishFlag();
}
} );
return ifritTwoState;
}
void update( uint64_t deltaTime ) override void update( uint64_t deltaTime ) override
{ {
// todo: better way to start fights here.. // todo: better way to start fights here..
// this probably doesn't need to be overriden either
auto ifrit = getBNpc( IfritNormalData::IFRIT ); auto ifrit = getBNpc( NPC_IFRIT );
if( ifrit; ifrit->hateListGetHighestValue() != 0 && m_status == EncounterFightStatus::IDLE ) if( ifrit; ifrit->hateListGetHighestValue() != 0 && m_status == EncounterFightStatus::IDLE )
{ {
@ -161,42 +138,5 @@ namespace Sapphire
m_stateStack->top()->update( deltaTime ); m_stateStack->top()->update( deltaTime );
} }
} }
void reset() override
{
auto boss = m_pInstance->getActiveBNpcByLayoutId( IfritNormalData::IFRIT );
if( boss )
{
removeBNpc( IfritNormalData::IFRIT );
m_pInstance->removeActor( boss );
}
init();
}
EncounterFightStatus getEncounterFightStatus() const override
{
return m_status;
}
void addBNpc( Entity::BNpcPtr pBNpc ) override
{
m_bnpcs[ pBNpc->getLayoutId() ] = pBNpc;
}
Entity::BNpcPtr getBNpc( uint32_t layoutId ) override
{
auto bnpc = m_bnpcs.find( layoutId );
if( bnpc != std::end( m_bnpcs ) )
return bnpc->second;
return nullptr;
}
void removeBNpc( uint32_t layoutId ) override
{
m_bnpcs.erase( layoutId );
}
}; };
} }

View file

@ -30,6 +30,7 @@ TYPE_FORWARD( Land );
TYPE_FORWARD( Linkshell ); TYPE_FORWARD( Linkshell );
TYPE_FORWARD( FreeCompany ); TYPE_FORWARD( FreeCompany );
TYPE_FORWARD( EncounterFight ); TYPE_FORWARD( EncounterFight );
TYPE_FORWARD( EncounterState );
namespace World namespace World
{ {