diff --git a/src/scripts/instances/trials/TheBowlofEmbers.cpp b/src/scripts/instances/trials/TheBowlofEmbers.cpp index f9b151fc..c3b1f019 100644 --- a/src/scripts/instances/trials/TheBowlofEmbers.cpp +++ b/src/scripts/instances/trials/TheBowlofEmbers.cpp @@ -1,25 +1,68 @@ #include #include +#include + +#include using namespace Sapphire; class TheBowlofEmbers : public Sapphire::ScriptAPI::InstanceContentScript { public: + static constexpr int NPC_IFRIT = 4126276; + static constexpr int VAL_IFRIT_HP = 13884; + 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 { 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) -// 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 { + 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, diff --git a/src/world/Encounter/EncounterFight.h b/src/world/Encounter/EncounterFight.h index f3fe9c39..1650160d 100644 --- a/src/world/Encounter/EncounterFight.h +++ b/src/world/Encounter/EncounterFight.h @@ -98,10 +98,33 @@ namespace Sapphire virtual ~EncounterFight() = default; - virtual void init() = 0; - virtual void start() = 0; - virtual void update( uint64_t currTime ) = 0; - virtual void reset() = 0; + void init() + { + m_status = EncounterFightStatus::IDLE; + 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 ) { @@ -110,11 +133,16 @@ namespace Sapphire pState->init(); } - EncounterFightStatus getEncounterFightStatus() const + EncounterFightStatus getStatus() const { return m_status; } + void setStatus( EncounterFightStatus status ) + { + m_status = status; + } + void addBNpc( Entity::BNpcPtr pBNpc ) { m_bnpcs[ pBNpc->getLayoutId() ] = pBNpc; diff --git a/src/world/Encounter/InstanceContent/IfritNormal.h b/src/world/Encounter/InstanceContent/IfritNormal.h deleted file mode 100644 index 2a7f7e12..00000000 --- a/src/world/Encounter/InstanceContent/IfritNormal.h +++ /dev/null @@ -1,53 +0,0 @@ -#include - -#include - -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 \ No newline at end of file diff --git a/src/world/Encounter/TimelineActor.cpp b/src/world/Encounter/TimelineActor.cpp index 83e8fffe..818ff400 100644 --- a/src/world/Encounter/TimelineActor.cpp +++ b/src/world/Encounter/TimelineActor.cpp @@ -147,12 +147,6 @@ namespace Sapphire::Encounter { 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 auto pAction = subActor.second->getCurrentAction(); if( pAction ) @@ -189,7 +183,6 @@ namespace Sapphire::Encounter auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref(); for( const auto& player : pTeri->getPlayers() ) { - // pActor->spawn( player.second ); playerMgr.sendDebug( *player.second, fmt::format( "Spawned subactor {}", name ) ); } } @@ -212,7 +205,6 @@ namespace Sapphire::Encounter { auto& pBNpc = subActor.second; pTeri->removeActor( pBNpc ); - // todo: despawn? subActor.second = nullptr; } } diff --git a/src/world/Script/NativeScriptApi.cpp b/src/world/Script/NativeScriptApi.cpp index 01587b8d..25d747f5 100644 --- a/src/world/Script/NativeScriptApi.cpp +++ b/src/world/Script/NativeScriptApi.cpp @@ -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, uint32_t eventId ) { diff --git a/src/world/Script/NativeScriptApi.h b/src/world/Script/NativeScriptApi.h index f43e4e4f..fbc5cc6f 100644 --- a/src/world/Script/NativeScriptApi.h +++ b/src/world/Script/NativeScriptApi.h @@ -352,6 +352,8 @@ namespace Sapphire::ScriptAPI 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, uint32_t eventId, uint64_t actorId ); diff --git a/src/world/Script/ScriptMgr.cpp b/src/world/Script/ScriptMgr.cpp index f6662b62..29125ab6 100644 --- a/src/world/Script/ScriptMgr.cpp +++ b/src/world/Script/ScriptMgr.cpp @@ -693,6 +693,21 @@ bool Sapphire::Scripting::ScriptMgr::onInstanceInit( InstanceContent& instance ) 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 ) { auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::InstanceContentScript >( instance.getDirectorId() ); diff --git a/src/world/Script/ScriptMgr.h b/src/world/Script/ScriptMgr.h index 6e2a85f1..1be0e96c 100644 --- a/src/world/Script/ScriptMgr.h +++ b/src/world/Script/ScriptMgr.h @@ -100,6 +100,8 @@ namespace Sapphire::Scripting bool onInstanceInit( InstanceContent& instance ); + bool onInstanceReset( InstanceContent& instance ); + bool onInstanceUpdate( InstanceContent& instance, uint64_t tickCount ); bool diff --git a/src/world/Territory/InstanceContent.cpp b/src/world/Territory/InstanceContent.cpp index 348b87b3..16073a0a 100644 --- a/src/world/Territory/InstanceContent.cpp +++ b/src/world/Territory/InstanceContent.cpp @@ -28,7 +28,7 @@ #include "InstanceContent.h" #include "InstanceObjectCache.h" -#include +#include #include @@ -72,11 +72,6 @@ bool Sapphire::InstanceContent::init() auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); 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; } @@ -129,6 +124,7 @@ void Sapphire::InstanceContent::onLeaveTerritory( Entity::Player& player ) void Sapphire::InstanceContent::onUpdate( uint64_t tickCount ) { + auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); switch( m_state ) { case Created: @@ -186,6 +182,8 @@ void Sapphire::InstanceContent::onUpdate( uint64_t tickCount ) else if( tickCount < m_instanceResetTime ) return; + + if( m_instanceResetFinishTime == 0 ) { m_instanceResetFinishTime = tickCount + 5000; @@ -216,6 +214,8 @@ void Sapphire::InstanceContent::onUpdate( uint64_t tickCount ) if( m_pEntranceEObj ) m_pEntranceEObj->setPermissionInvisibility( 0 ); + scriptMgr.onInstanceReset( *this ); + return; } else if( tickCount < m_instanceResetFinishTime ) @@ -255,7 +255,7 @@ void Sapphire::InstanceContent::onUpdate( uint64_t tickCount ) updateBNpcs( tickCount ); - if( m_pEncounter->getEncounterFightStatus() == EncounterFightStatus::FAIL ) + if( m_pEncounter->getStatus() == EncounterFightStatus::FAIL ) m_state = DutyReset; break; } @@ -291,7 +291,6 @@ void Sapphire::InstanceContent::onUpdate( uint64_t tickCount ) } } - auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); scriptMgr.onInstanceUpdate( *this, tickCount ); m_pEncounter->update( tickCount ); @@ -797,4 +796,14 @@ size_t Sapphire::InstanceContent::getInstancePlayerCount() const std::set< uint32_t > Sapphire::InstanceContent::getSpawnedPlayerIds() const { return m_spawnedPlayers; -} \ No newline at end of file +} + +void Sapphire::InstanceContent::setEncounter( Sapphire::EncounterFightPtr pEncounter ) +{ + m_pEncounter = pEncounter; +} + +Sapphire::EncounterFightPtr Sapphire::InstanceContent::getEncounter() +{ + return m_pEncounter; +} diff --git a/src/world/Territory/InstanceContent.h b/src/world/Territory/InstanceContent.h index 50a41c41..b1d1834a 100644 --- a/src/world/Territory/InstanceContent.h +++ b/src/world/Territory/InstanceContent.h @@ -209,6 +209,9 @@ namespace Sapphire std::set< uint32_t > getSpawnedPlayerIds() const; void movePlayerToEntrance( Entity::Player& player ); + + void setEncounter( EncounterFightPtr pEncounter ); + EncounterFightPtr getEncounter(); private: std::shared_ptr< Excel::ExcelStruct< Excel::InstanceContent > > m_instanceConfiguration; std::shared_ptr< Excel::ExcelStruct< Excel::ContentFinderCondition > > m_contentFinderCondition;