From 4185ef5f38f38a90eb5098e3b73050f4681f55e5 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Mon, 11 Feb 2019 00:40:00 +1100 Subject: [PATCH] cleanup action start behaviour, interrupt any unimplemented actions --- src/world/Action/Action.cpp | 57 +++++++++++++++++++++------------ src/world/Action/Action.h | 16 ++++----- src/world/Manager/ActionMgr.cpp | 22 ++++++------- src/world/Script/ScriptMgr.cpp | 26 ++++++++++++--- 4 files changed, 74 insertions(+), 47 deletions(-) diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index 3849e29b..e3ad0d8b 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -95,13 +95,6 @@ void Sapphire::Action::Action::setInterrupted( Common::ActionInterruptType type m_interruptType = type; } -void Sapphire::Action::Action::start() -{ - m_startTime = Util::getTimeMs(); - - onStart(); -} - uint32_t Sapphire::Action::Action::getCastTime() const { return m_castTime; @@ -112,7 +105,7 @@ void Sapphire::Action::Action::setCastTime( uint32_t castTime ) m_castTime = castTime; } -bool Sapphire::Action::Action::isCastedAction() const +bool Sapphire::Action::Action::hasCastTime() const { return m_castTime > 0; } @@ -130,7 +123,7 @@ bool Sapphire::Action::Action::update() if( isInterrupted() ) { - onInterrupt(); + castInterrupt(); return true; } @@ -141,26 +134,28 @@ bool Sapphire::Action::Action::update() uint64_t currTime = Util::getTimeMs(); - if( !isCastedAction() || std::difftime( currTime, m_startTime ) > m_castTime ) + if( !hasCastTime() || std::difftime( currTime, m_startTime ) > m_castTime ) { - onFinish(); + castFinish(); return true; } return false; } -void Sapphire::Action::Action::onStart() +void Sapphire::Action::Action::castStart() { assert( m_pSource ); + m_startTime = Util::getTimeMs(); + auto player = m_pSource->getAsPlayer(); if( player ) { - player->sendDebug( "onStart()" ); + player->sendDebug( "castStart()" ); } - if( isCastedAction() ) + if( hasCastTime() ) { auto castPacket = makeZonePacket< Server::FFXIVIpcActorCast >( getId() ); @@ -180,10 +175,26 @@ void Sapphire::Action::Action::onStart() } auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >(); - pScriptMgr->onCastStart( *m_pSource, *this ); + if( !pScriptMgr->onCastStart( *m_pSource, *this ) ) + { + // script not implemented + castInterrupt(); + + if( player ) + { + player->sendUrgent( "Action not implemented, missing script for actionId#{0}", getId() ); + player->setCurrentAction( nullptr ); + } + + return; + } + + // instantly finish cast if there's no cast time + if( !hasCastTime() ) + castFinish(); } -void Sapphire::Action::Action::onInterrupt() +void Sapphire::Action::Action::castInterrupt() { assert( m_pSource ); @@ -201,10 +212,10 @@ void Sapphire::Action::Action::onInterrupt() //player->unsetStateFlag( PlayerStateFlag::Occupied1 ); player->unsetStateFlag( PlayerStateFlag::Casting ); - player->sendDebug( "onInterrupt()" ); + player->sendDebug( "castInterrupt()" ); } - if( isCastedAction() ) + if( hasCastTime() ) { uint8_t interruptEffect = 0; if( m_interruptType == ActionInterruptType::DamageInterrupt ) @@ -222,16 +233,16 @@ void Sapphire::Action::Action::onInterrupt() pScriptMgr->onCastInterrupt( *m_pSource, *this ); } -void Sapphire::Action::Action::onFinish() +void Sapphire::Action::Action::castFinish() { assert( m_pSource ); auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >(); auto pPlayer = m_pSource->getAsPlayer(); - pPlayer->sendDebug( "onFinish()" ); + pPlayer->sendDebug( "castFinish()" ); - if( isCastedAction() ) + if( hasCastTime() ) { /*auto control = ActorControlPacket143( m_pTarget->getId(), ActorControlType::Unk7, 0x219, m_id, m_id, m_id, m_id ); @@ -286,6 +297,8 @@ void Sapphire::Action::Action::buildEffectPackets() void Sapphire::Action::Action::damageTarget( uint32_t potency, Entity::Chara& chara, Common::ActionAspect aspect ) { + // todo: scale potency into damage from stats + Common::EffectEntry entry{}; // todo: handle cases where the action misses/is blocked? @@ -318,6 +331,8 @@ void Sapphire::Action::Action::damageTarget( uint32_t potency, Entity::Chara& ch void Sapphire::Action::Action::healTarget( uint32_t potency, Entity::Chara& chara ) { + // todo: scale potency into healing from stats + Common::EffectEntry entry{}; entry.effectType = Common::ActionEffectType::Heal; diff --git a/src/world/Action/Action.h b/src/world/Action/Action.h index e7518bae..5310388f 100644 --- a/src/world/Action/Action.h +++ b/src/world/Action/Action.h @@ -61,12 +61,7 @@ namespace Sapphire::Action * @brief Tests whether the action is instantly usable or has a cast assoc'd with it * @return true if action has a cast time */ - bool isCastedAction() const; - - /*! - * @brief Starts the cast. Finishes it immediately if there is no cast time (weaponskills). - */ - void start(); + bool hasCastTime() const; void buildEffectPackets(); @@ -84,9 +79,12 @@ namespace Sapphire::Action */ void healTarget( uint32_t potency, Entity::Chara& chara ); - virtual void onStart(); - virtual void onFinish(); - virtual void onInterrupt(); + /*! + * @brief Starts the cast. Finishes it immediately if there is no cast time (weaponskills). + */ + virtual void castStart(); + virtual void castFinish(); + virtual void castInterrupt(); // update action, if returns true, action is done and has to be removed from the actor virtual bool update(); diff --git a/src/world/Manager/ActionMgr.cpp b/src/world/Manager/ActionMgr.cpp index 49a84947..4222e182 100644 --- a/src/world/Manager/ActionMgr.cpp +++ b/src/world/Manager/ActionMgr.cpp @@ -83,22 +83,20 @@ void World::Manager::ActionMgr::bootstrapAction( Entity::Player& player, Data::Action& actionData ) { if( !canPlayerUseAction( player, *currentAction, actionData ) ) - return; - - // instantly cast and finish actions that have no cast time - // not worth adding it to the player - // todo: what do in cases of swiftcast/etc? script callback? - if( !currentAction->isCastedAction() ) { - currentAction->start(); - currentAction->onFinish(); - + // forcefully interrupt the action and reset the cooldown + currentAction->castInterrupt(); return; } - // otherwise, set the action on the player and start it - player.setCurrentAction( currentAction ); - currentAction->start(); + // 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->castStart(); } bool World::Manager::ActionMgr::canPlayerUseAction( Entity::Player& player, diff --git a/src/world/Script/ScriptMgr.cpp b/src/world/Script/ScriptMgr.cpp index 5c67f103..54757080 100644 --- a/src/world/Script/ScriptMgr.cpp +++ b/src/world/Script/ScriptMgr.cpp @@ -303,6 +303,7 @@ bool Sapphire::Scripting::ScriptMgr::onBNpcKill( Entity::Player& player, uint16_ bool Sapphire::Scripting::ScriptMgr::onEObjHit( Sapphire::Entity::Player& player, uint64_t actorId ) { auto pEventMgr = framework()->get< World::Manager::EventMgr >(); + bool didCallScript = false; for( size_t i = 0; i < 30; i++ ) { @@ -315,6 +316,7 @@ bool Sapphire::Scripting::ScriptMgr::onEObjHit( Sapphire::Entity::Player& player auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::EventScript >( questId ); if( script ) { + didCallScript = true; std::string objName = pEventMgr->getEventName( questId ); player.sendDebug( "Calling: {0}.onEObjHit actorId#{1}", objName, actorId ); @@ -323,7 +325,7 @@ bool Sapphire::Scripting::ScriptMgr::onEObjHit( Sapphire::Entity::Player& player } } - return true; + return didCallScript; } bool Sapphire::Scripting::ScriptMgr::onCastFinish( Entity::Chara& sourceActor, Action::Action& currentAction ) @@ -331,8 +333,11 @@ bool Sapphire::Scripting::ScriptMgr::onCastFinish( Entity::Chara& sourceActor, A auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( currentAction.getId() ); if( script ) + { script->onCastFinish( sourceActor, currentAction ); - return true; + return true; + } + return false; } bool Sapphire::Scripting::ScriptMgr::onCastInterrupt( Entity::Chara& sourceActor, Action::Action& currentAction ) @@ -340,8 +345,11 @@ bool Sapphire::Scripting::ScriptMgr::onCastInterrupt( Entity::Chara& sourceActor auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( currentAction.getId() ); if( script ) + { script->onCastInterrupt( sourceActor, currentAction ); - return true; + return true; + } + return false; } bool Sapphire::Scripting::ScriptMgr::onCastStart( Entity::Chara& sourceActor, Action::Action& currentAction ) @@ -349,8 +357,12 @@ bool Sapphire::Scripting::ScriptMgr::onCastStart( Entity::Chara& sourceActor, Ac auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( currentAction.getId() ); if( script ) + { script->onCastStart( sourceActor, currentAction ); - return true; + return true; + } + + return false; } bool Sapphire::Scripting::ScriptMgr::onCharaHit( Entity::Chara& sourceActor, Entity::Chara& hitActor, @@ -359,8 +371,12 @@ bool Sapphire::Scripting::ScriptMgr::onCharaHit( Entity::Chara& sourceActor, Ent auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( currentAction.getId() ); if( script ) + { script->onCharaHit( sourceActor, hitActor, currentAction ); - return true; + return true; + } + + return false; } bool Sapphire::Scripting::ScriptMgr::onStatusReceive( Entity::CharaPtr pActor, uint32_t effectId )