From 4623ed535a33c7ca79a07d44286764bc2cffe409 Mon Sep 17 00:00:00 2001 From: collett Date: Sat, 4 Jan 2020 19:47:34 +0900 Subject: [PATCH] Interrupt casting if target died and casting queue. --- src/world/Action/Action.cpp | 29 ++++++++++++++++++++++ src/world/Action/Action.h | 1 + src/world/Actor/Player.cpp | 43 ++++++++++++++++++++++++++++++++- src/world/Actor/Player.h | 7 ++++++ src/world/Manager/ActionMgr.cpp | 18 ++++++++++---- 5 files changed, 92 insertions(+), 6 deletions(-) diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index 26d89af8..d4ef7850 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -162,6 +162,11 @@ bool Action::Action::isInterrupted() const return m_interruptType != Common::ActionInterruptType::None; } +Common::ActionInterruptType Action::Action::getInterruptType() const +{ + return m_interruptType; +} + void Action::Action::setInterrupted( Common::ActionInterruptType type ) { m_interruptType = type; @@ -212,6 +217,30 @@ bool Action::Action::update() return true; } + if ( m_pTarget == nullptr && m_targetId != 0 ) + { + // try to search for the target actor + for( auto actor : m_pSource->getInRangeActors( true ) ) + { + if ( actor->getId() == m_targetId ) + { + m_pTarget = actor->getAsChara(); + break; + } + } + } + + if ( m_pTarget != nullptr ) + { + if ( !m_pTarget->isAlive() ) + { + // interrupt the cast if target died + setInterrupted( Common::ActionInterruptType::RegularInterrupt ); + interrupt(); + return true; + } + } + return false; } diff --git a/src/world/Action/Action.h b/src/world/Action/Action.h index ce10de5c..60c5ffeb 100644 --- a/src/world/Action/Action.h +++ b/src/world/Action/Action.h @@ -37,6 +37,7 @@ namespace Sapphire::World::Action Entity::CharaPtr getSourceChara() const; bool isInterrupted() const; + Common::ActionInterruptType getInterruptType() const; void setInterrupted( Common::ActionInterruptType type ); uint32_t getCastTime() const; diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 4ebe604d..ec6877f0 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -76,7 +76,8 @@ Sapphire::Entity::Player::Player( FrameworkPtr pFw ) : m_emoteMode( 0 ), m_directorInitialized( false ), m_onEnterEventDone( false ), - m_falling( false ) + m_falling( false ), + m_pQueuedAction( nullptr ) { m_id = 0; m_currentStance = Stance::Passive; @@ -2131,3 +2132,43 @@ Sapphire::Common::ActiveLand Sapphire::Entity::Player::getActiveLand() const { return m_activeLand; } + +bool Sapphire::Entity::Player::hasQueuedAction() const +{ + return m_pQueuedAction != nullptr; +} + +void Sapphire::Entity::Player::setQueuedAction( Sapphire::World::Action::ActionPtr pAction ) +{ + m_pQueuedAction = nullptr; // overwrite whatever is already there + m_pQueuedAction = std::move( pAction ); +} + +bool Sapphire::Entity::Player::checkAction() +{ + if( m_pCurrentAction == nullptr ) + return false; + + if( m_pCurrentAction->update() ) + { + if ( m_pCurrentAction->isInterrupted() && m_pCurrentAction->getInterruptType() != Common::ActionInterruptType::DamageInterrupt ) + { + // we moved (or whatever not damage interrupt) so we don't want to execute queued cast + m_pQueuedAction = nullptr; + } + m_pCurrentAction = nullptr; + + if( hasQueuedAction() ) + { + sendDebug( "Queued skill start: {0}", m_pQueuedAction->getId() ); + if ( m_pQueuedAction->hasCastTime() ) + { + setCurrentAction( m_pQueuedAction ); + } + m_pQueuedAction->start(); + m_pQueuedAction = nullptr; + } + } + + return true; +} \ No newline at end of file diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index 54cb4a34..cba65767 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -643,6 +643,11 @@ namespace Sapphire::Entity /*! return a const pointer to the mount guide bitmask array */ const uint8_t* getMountGuideBitmask() const; + bool checkAction() override; + + bool hasQueuedAction() const; + + void setQueuedAction( World::Action::ActionPtr pAction ); // Spawn handling ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1002,6 +1007,8 @@ namespace Sapphire::Entity uint32_t m_inventorySequence; + World::Action::ActionPtr m_pQueuedAction; + private: using InventoryMap = std::map< uint16_t, Sapphire::ItemContainerPtr >; diff --git a/src/world/Manager/ActionMgr.cpp b/src/world/Manager/ActionMgr.cpp index 43d14170..878b27aa 100644 --- a/src/world/Manager/ActionMgr.cpp +++ b/src/world/Manager/ActionMgr.cpp @@ -87,12 +87,20 @@ void World::Manager::ActionMgr::bootstrapAction( Entity::Player& player, return; } - // if we have a cast time we want to associate the action with the player so update is called - if( currentAction->hasCastTime() ) + if ( player.getCurrentAction() ) { - player.setCurrentAction( currentAction ); + player.sendDebug( "Skill queued: {0}", currentAction->getId() ); + player.setQueuedAction( currentAction ); } + else + { + // if we have a cast time we want to associate the action with the player so update is called + if( currentAction->hasCastTime() ) + { + player.setCurrentAction( currentAction ); + } - // todo: what do in cases of swiftcast/etc? script callback? - currentAction->start(); + // todo: what do in cases of swiftcast/etc? script callback? + currentAction->start(); + } } \ No newline at end of file