1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-21 20:27:46 +00:00

Encounter handling moved to scripts, removed obsolete EncounterFight implementation

This commit is contained in:
Mordred 2025-01-16 12:12:27 +01:00
parent e3b53b5e19
commit a14b44f654
10 changed files with 121 additions and 76 deletions

View file

@ -1,25 +1,68 @@
#include <ScriptObject.h> #include <ScriptObject.h>
#include <Territory/InstanceContent.h> #include <Territory/InstanceContent.h>
#include <Encounter/EncounterFight.h>
#include <Encounter/EncounterTimeline.h>
using namespace Sapphire; using namespace Sapphire;
class TheBowlofEmbers : public Sapphire::ScriptAPI::InstanceContentScript class TheBowlofEmbers : public Sapphire::ScriptAPI::InstanceContentScript
{ {
public: public:
static constexpr int NPC_IFRIT = 4126276;
static constexpr int VAL_IFRIT_HP = 13884;
TheBowlofEmbers() : Sapphire::ScriptAPI::InstanceContentScript( 20001 ) TheBowlofEmbers() : Sapphire::ScriptAPI::InstanceContentScript( 20001 )
{ } { }
void setupEncounter( InstanceContent& instance, EncounterFightPtr pEncounter )
{
pEncounter->init();
auto boss = instance.createBNpcFromLayoutId( NPC_IFRIT, VAL_IFRIT_HP, Common::BNpcType::Enemy );
boss->init();
pEncounter->addBNpc( boss );
}
void onInit( InstanceContent& instance ) override void onInit( InstanceContent& instance ) override
{ {
instance.addEObj( "Entrance", 2000182, 4177874, 4177871, 5, { -16.000000f, 0.000000f, 0.000000f }, 1.000000f, 0.000000f, 0); instance.addEObj( "Entrance", 2000182, 4177874, 4177871, 5, { -16.000000f, 0.000000f, 0.000000f }, 1.000000f, 0.000000f, 0);
// States -> vf_lock_on (id: 11) vf_lock_of (id: 12) // States -> vf_lock_on (id: 11) vf_lock_of (id: 12)
// instance.addEObj( "Exit", 2000139, 0, 4177870, 4, { 16.000000f, 0.000000f, 0.000000f }, 1.000000f, 0.000000f, 0); // instance.addEObj( "Exit", 2000139, 0, 4177870, 4, { 16.000000f, 0.000000f, 0.000000f }, 1.000000f, 0.000000f, 0);
auto pEncounter = std::make_shared< EncounterFight >( std::dynamic_pointer_cast< InstanceContent, Territory >( instance.shared_from_this() ) );
setupEncounter( instance, pEncounter );
instance.setEncounterTimeline( "IfritNormal" );
instance.setEncounter( pEncounter );
}
void onReset( InstanceContent& instance ) override
{
auto pEncounter = instance.getEncounter();
if( !pEncounter )
return;
setupEncounter( instance, pEncounter );
} }
void onUpdate( InstanceContent& instance, uint64_t tickCount ) override void onUpdate( InstanceContent& instance, uint64_t tickCount ) override
{
auto pEncounter = instance.getEncounter();
if( pEncounter )
{ {
// Fight start condition
auto ifrit = pEncounter->getBNpc( NPC_IFRIT );
if( ifrit && ifrit->hateListGetHighestValue() != 0 && pEncounter->getStatus() == EncounterFightStatus::IDLE )
{
pEncounter->setStartTime( tickCount );
pEncounter->start();
}
// Fight end condition
if( pEncounter->getStatus() == EncounterFightStatus::ACTIVE && ifrit && ( !ifrit->isAlive() ) )
{
//Logger::debug( "Setting duty state to failed!" );
pEncounter->setStatus( EncounterFightStatus::FAIL );
}
}
} }
void onEnterTerritory( InstanceContent& instance, Entity::Player& player, uint32_t eventId, uint16_t param1, void onEnterTerritory( InstanceContent& instance, Entity::Player& player, uint32_t eventId, uint16_t param1,

View file

@ -98,10 +98,33 @@ namespace Sapphire
virtual ~EncounterFight() = default; virtual ~EncounterFight() = default;
virtual void init() = 0; void init()
virtual void start() = 0; {
virtual void update( uint64_t currTime ) = 0; m_status = EncounterFightStatus::IDLE;
virtual void reset() = 0; m_startTime = 0;
};
virtual void start() { m_status = EncounterFightStatus::ACTIVE; };
virtual void update( uint64_t currTime )
{
m_pInstance->getEncounterTimeline().update( getInstance(), currTime );
}
void reset()
{
for( auto& pBNpc : m_bnpcs )
{
removeBNpc( pBNpc.first );
m_pInstance->removeActor( pBNpc.second );
}
m_pInstance->getEncounterTimeline().reset( getInstance() );
init();
}
void setStartTime( uint64_t startTime )
{
m_startTime = startTime;
}
void addState( EncounterState::EncounterStatePtr pState, bool initState = true ) void addState( EncounterState::EncounterStatePtr pState, bool initState = true )
{ {
@ -110,11 +133,16 @@ namespace Sapphire
pState->init(); pState->init();
} }
EncounterFightStatus getEncounterFightStatus() const EncounterFightStatus getStatus() const
{ {
return m_status; return m_status;
} }
void setStatus( EncounterFightStatus status )
{
m_status = status;
}
void addBNpc( Entity::BNpcPtr pBNpc ) void addBNpc( Entity::BNpcPtr pBNpc )
{ {
m_bnpcs[ pBNpc->getLayoutId() ] = pBNpc; m_bnpcs[ pBNpc->getLayoutId() ] = pBNpc;

View file

@ -1,53 +0,0 @@
#include <Encounter/EncounterFight.h>
#include <Encounter/EncounterTimeline.h>
namespace Sapphire
{
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:
IfritEncounterFight( InstanceContentPtr pInstance ) : EncounterFight( pInstance )
{
pInstance->setEncounterTimeline( "IfritNormal" );
};
void init() override
{
m_startTime = 0;
// todo: i don't like this
auto boss = m_pInstance->createBNpcFromLayoutId( NPC_IFRIT, VAL_IFRIT_HP, Common::BNpcType::Enemy );
boss->init();
addBNpc( boss );
}
void start() override
{
}
void reset() override
{
if( auto boss = m_pInstance->getActiveBNpcByLayoutId( NPC_IFRIT ); boss )
{
removeBNpc( NPC_IFRIT );
m_pInstance->removeActor( boss );
}
m_pInstance->getEncounterTimeline().reset( getInstance() );
init();
}
void update( uint64_t deltaTime ) override
{
m_pInstance->getEncounterTimeline().update( getInstance(), deltaTime );
}
};
}// namespace Sapphire

View file

@ -147,12 +147,6 @@ namespace Sapphire::Encounter
{ {
if( subActor.second ) if( subActor.second )
{ {
auto inRange = subActor.second->getInRangeActors();
for( const auto& pActor : inRange )
{
if( auto pPlayer = pActor->getAsPlayer() )
subActor.second->despawn( pPlayer );
}
// todo: need to reset the ai on interrupt // todo: need to reset the ai on interrupt
auto pAction = subActor.second->getCurrentAction(); auto pAction = subActor.second->getCurrentAction();
if( pAction ) if( pAction )
@ -189,7 +183,6 @@ namespace Sapphire::Encounter
auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref(); auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref();
for( const auto& player : pTeri->getPlayers() ) for( const auto& player : pTeri->getPlayers() )
{ {
// pActor->spawn( player.second );
playerMgr.sendDebug( *player.second, fmt::format( "Spawned subactor {}", name ) ); playerMgr.sendDebug( *player.second, fmt::format( "Spawned subactor {}", name ) );
} }
} }
@ -212,7 +205,6 @@ namespace Sapphire::Encounter
{ {
auto& pBNpc = subActor.second; auto& pBNpc = subActor.second;
pTeri->removeActor( pBNpc ); pTeri->removeActor( pBNpc );
// todo: despawn?
subActor.second = nullptr; subActor.second = nullptr;
} }
} }

View file

@ -235,6 +235,10 @@ namespace Sapphire::ScriptAPI
{ {
} }
void InstanceContentScript::onReset( InstanceContent& instance )
{
}
void InstanceContentScript::onTalk( Sapphire::InstanceContent& instance, Sapphire::Entity::Player& player, Sapphire::Entity::EventObject& eobj, void InstanceContentScript::onTalk( Sapphire::InstanceContent& instance, Sapphire::Entity::Player& player, Sapphire::Entity::EventObject& eobj,
uint32_t eventId ) uint32_t eventId )
{ {

View file

@ -352,6 +352,8 @@ namespace Sapphire::ScriptAPI
virtual void onInit( Sapphire::InstanceContent& instance ); virtual void onInit( Sapphire::InstanceContent& instance );
virtual void onReset( Sapphire::InstanceContent& instance );
virtual void onTalk( Sapphire::InstanceContent& instance, Sapphire::Entity::Player& player, Sapphire::Entity::EventObject& eobj, uint32_t eventId ); virtual void onTalk( Sapphire::InstanceContent& instance, Sapphire::Entity::Player& player, Sapphire::Entity::EventObject& eobj, uint32_t eventId );
virtual void onTalk( Sapphire::InstanceContent& instance, Sapphire::Entity::Player& player, uint32_t eventId, uint64_t actorId ); virtual void onTalk( Sapphire::InstanceContent& instance, Sapphire::Entity::Player& player, uint32_t eventId, uint64_t actorId );

View file

@ -693,6 +693,21 @@ bool Sapphire::Scripting::ScriptMgr::onInstanceInit( InstanceContent& instance )
return false; return false;
} }
bool Sapphire::Scripting::ScriptMgr::onInstanceReset( InstanceContent& instance )
{
auto instId = instance.getDirectorId();
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::InstanceContentScript >( instance.getDirectorId() );
if( script )
{
script->onReset( instance );
return true;
}
return false;
}
bool Sapphire::Scripting::ScriptMgr::onInstanceUpdate( InstanceContent& instance, uint64_t tickCount ) bool Sapphire::Scripting::ScriptMgr::onInstanceUpdate( InstanceContent& instance, uint64_t tickCount )
{ {
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::InstanceContentScript >( instance.getDirectorId() ); auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::InstanceContentScript >( instance.getDirectorId() );

View file

@ -100,6 +100,8 @@ namespace Sapphire::Scripting
bool onInstanceInit( InstanceContent& instance ); bool onInstanceInit( InstanceContent& instance );
bool onInstanceReset( InstanceContent& instance );
bool onInstanceUpdate( InstanceContent& instance, uint64_t tickCount ); bool onInstanceUpdate( InstanceContent& instance, uint64_t tickCount );
bool bool

View file

@ -28,7 +28,7 @@
#include "InstanceContent.h" #include "InstanceContent.h"
#include "InstanceObjectCache.h" #include "InstanceObjectCache.h"
#include <Encounter/InstanceContent/IfritNormal.h> #include <Encounter/EncounterFight.h>
#include <Task/MoveTerritoryTask.h> #include <Task/MoveTerritoryTask.h>
@ -72,11 +72,6 @@ bool Sapphire::InstanceContent::init()
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
scriptMgr.onInstanceInit( *this ); scriptMgr.onInstanceInit( *this );
// todo: every fight is now ifrit
m_pEncounter = std::make_shared< IfritEncounterFight >( std::dynamic_pointer_cast< InstanceContent, Territory >( shared_from_this() ) );
m_pEncounter->init();
return true; return true;
} }
@ -129,6 +124,7 @@ void Sapphire::InstanceContent::onLeaveTerritory( Entity::Player& player )
void Sapphire::InstanceContent::onUpdate( uint64_t tickCount ) void Sapphire::InstanceContent::onUpdate( uint64_t tickCount )
{ {
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
switch( m_state ) switch( m_state )
{ {
case Created: case Created:
@ -186,6 +182,8 @@ void Sapphire::InstanceContent::onUpdate( uint64_t tickCount )
else if( tickCount < m_instanceResetTime ) else if( tickCount < m_instanceResetTime )
return; return;
if( m_instanceResetFinishTime == 0 ) if( m_instanceResetFinishTime == 0 )
{ {
m_instanceResetFinishTime = tickCount + 5000; m_instanceResetFinishTime = tickCount + 5000;
@ -216,6 +214,8 @@ void Sapphire::InstanceContent::onUpdate( uint64_t tickCount )
if( m_pEntranceEObj ) if( m_pEntranceEObj )
m_pEntranceEObj->setPermissionInvisibility( 0 ); m_pEntranceEObj->setPermissionInvisibility( 0 );
scriptMgr.onInstanceReset( *this );
return; return;
} }
else if( tickCount < m_instanceResetFinishTime ) else if( tickCount < m_instanceResetFinishTime )
@ -255,7 +255,7 @@ void Sapphire::InstanceContent::onUpdate( uint64_t tickCount )
updateBNpcs( tickCount ); updateBNpcs( tickCount );
if( m_pEncounter->getEncounterFightStatus() == EncounterFightStatus::FAIL ) if( m_pEncounter->getStatus() == EncounterFightStatus::FAIL )
m_state = DutyReset; m_state = DutyReset;
break; break;
} }
@ -291,7 +291,6 @@ void Sapphire::InstanceContent::onUpdate( uint64_t tickCount )
} }
} }
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
scriptMgr.onInstanceUpdate( *this, tickCount ); scriptMgr.onInstanceUpdate( *this, tickCount );
m_pEncounter->update( tickCount ); m_pEncounter->update( tickCount );
@ -798,3 +797,13 @@ std::set< uint32_t > Sapphire::InstanceContent::getSpawnedPlayerIds() const
{ {
return m_spawnedPlayers; return m_spawnedPlayers;
} }
void Sapphire::InstanceContent::setEncounter( Sapphire::EncounterFightPtr pEncounter )
{
m_pEncounter = pEncounter;
}
Sapphire::EncounterFightPtr Sapphire::InstanceContent::getEncounter()
{
return m_pEncounter;
}

View file

@ -209,6 +209,9 @@ namespace Sapphire
std::set< uint32_t > getSpawnedPlayerIds() const; std::set< uint32_t > getSpawnedPlayerIds() const;
void movePlayerToEntrance( Entity::Player& player ); void movePlayerToEntrance( Entity::Player& player );
void setEncounter( EncounterFightPtr pEncounter );
EncounterFightPtr getEncounter();
private: private:
std::shared_ptr< Excel::ExcelStruct< Excel::InstanceContent > > m_instanceConfiguration; std::shared_ptr< Excel::ExcelStruct< Excel::InstanceContent > > m_instanceConfiguration;
std::shared_ptr< Excel::ExcelStruct< Excel::ContentFinderCondition > > m_contentFinderCondition; std::shared_ptr< Excel::ExcelStruct< Excel::ContentFinderCondition > > m_contentFinderCondition;