diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index 513eb8d9..bf14dae8 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -86,7 +86,7 @@ bool Action::Action::init() } auto teriMgr = Common::Service< Manager::TerritoryMgr >::ref(); auto zone = teriMgr.getTerritoryByGuId( m_pSource->getTerritoryId() ); - m_resultId = zone->getNextEffectResultId(); + m_resultId = zone->getNextActionResultId(); m_actionResultBuilder = make_ActionResultBuilder( m_pSource, getId(), m_resultId, m_requestId ); @@ -461,13 +461,9 @@ std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcDamage( auto role = player->getRole(); if( role == Common::Role::RangedMagical || role == Common::Role::Healer ) - { wepDmg = item->getMagicalDmg(); - } else - { wepDmg = item->getPhysicalDmg(); - } } return Math::CalcStats::calcActionDamage( *m_pSource, potency, wepDmg ); @@ -484,13 +480,9 @@ std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcHealing auto role = player->getRole(); if( role == Common::Role::RangedMagical || role == Common::Role::Healer ) - { wepDmg = item->getMagicalDmg(); - } else - { wepDmg = item->getPhysicalDmg(); - } } return Math::CalcStats::calcActionHealing( *m_pSource, potency, wepDmg ); @@ -562,9 +554,7 @@ void Action::Action::buildActionResults() } if( !m_lutEntry.nextCombo.empty() ) // if we have a combo action followup - { m_actionResultBuilder->startCombo( m_pSource, getId() ); // this is on all targets hit - } } } else if( m_lutEntry.curePotency > 0 ) diff --git a/src/world/Action/ActionResult.cpp b/src/world/Action/ActionResult.cpp index ff330525..d12b1945 100644 --- a/src/world/Action/ActionResult.cpp +++ b/src/world/Action/ActionResult.cpp @@ -91,6 +91,9 @@ const Common::CalcResultParam& ActionResult::getCalcResultParam() const void ActionResult::execute() { + if( !m_target ) + return; + switch( m_result.Type ) { case Common::ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP: diff --git a/src/world/Action/ActionResult.h b/src/world/Action/ActionResult.h index 93094f49..fd41403a 100644 --- a/src/world/Action/ActionResult.h +++ b/src/world/Action/ActionResult.h @@ -38,4 +38,6 @@ namespace Sapphire::World::Action Common::CalcResultParam m_result; }; + + using ActionResultList = std::vector< ActionResultPtr >; } \ No newline at end of file diff --git a/src/world/Action/ActionResultBuilder.cpp b/src/world/Action/ActionResultBuilder.cpp index 61859f4d..2cb5d6c0 100644 --- a/src/world/Action/ActionResultBuilder.cpp +++ b/src/world/Action/ActionResultBuilder.cpp @@ -34,25 +34,12 @@ ActionResultBuilder::ActionResultBuilder( Entity::CharaPtr source, uint32_t acti } -uint64_t ActionResultBuilder::getResultDelayMs() -{ - // todo: actually figure this retarded shit out - - return Common::Util::getTimeMs() + 850; -} - void ActionResultBuilder::addResultToActor( Entity::CharaPtr& chara, ActionResultPtr result ) { - auto it = m_actorResultsMap.find( chara->getId() ); + auto it = m_actorResultsMap.find( chara ); if( it == m_actorResultsMap.end() ) { - // create a new one - auto resultList = std::vector< ActionResultPtr >(); - - resultList.push_back( std::move( result ) ); - - m_actorResultsMap[ chara->getId() ] = resultList; - + m_actorResultsMap[ chara ].push_back( std::move( result ) ); return; } @@ -61,21 +48,21 @@ void ActionResultBuilder::addResultToActor( Entity::CharaPtr& chara, ActionResul void ActionResultBuilder::heal( Entity::CharaPtr& effectTarget, Entity::CharaPtr& healingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionResultFlag flag ) { - ActionResultPtr nextResult = make_ActionResult( healingTarget, getResultDelayMs() ); + ActionResultPtr nextResult = make_ActionResult( healingTarget, 0 ); nextResult->heal( amount, severity, flag ); addResultToActor( effectTarget, nextResult ); } void ActionResultBuilder::restoreMP( Entity::CharaPtr& target, Entity::CharaPtr& restoringTarget, uint32_t amount, Common::ActionResultFlag flag ) { - ActionResultPtr nextResult = make_ActionResult( restoringTarget, getResultDelayMs() ); // restore mp source actor + ActionResultPtr nextResult = make_ActionResult( restoringTarget, 0 ); // restore mp source actor nextResult->restoreMP( amount, flag ); addResultToActor( target, nextResult ); } void ActionResultBuilder::damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionResultFlag flag ) { - ActionResultPtr nextResult = make_ActionResult( damagingTarget, getResultDelayMs() ); + ActionResultPtr nextResult = make_ActionResult( damagingTarget, 0 ); nextResult->damage( amount, severity, flag ); addResultToActor( damagingTarget, nextResult ); } @@ -103,7 +90,7 @@ void ActionResultBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t void ActionResultBuilder::mount( Entity::CharaPtr& target, uint16_t mountId ) { - ActionResultPtr nextResult = make_ActionResult( target, getResultDelayMs() ); + ActionResultPtr nextResult = make_ActionResult( target, 0 ); nextResult->mount( mountId ); addResultToActor( target, nextResult ); } @@ -123,106 +110,85 @@ void ActionResultBuilder::sendActionResults( const std::vector< Entity::CharaPtr std::shared_ptr< FFXIVPacketBase > ActionResultBuilder::createActionResultPacket( const std::vector< Entity::CharaPtr >& targetList ) { - auto remainingTargetCount = targetList.size(); + auto targetCount = targetList.size(); auto& taskMgr = Common::Service< World::Manager::TaskMgr >::ref(); auto& teriMgr = Common::Service< Sapphire::World::Manager::TerritoryMgr >::ref(); auto zone = teriMgr.getTerritoryByGuId( m_sourceChara->getTerritoryId() ); - if( remainingTargetCount > 1 ) // use AoeEffect packets + if( targetCount == 0 ) { - auto effectPacket = std::make_shared< EffectPacket >( m_sourceChara->getId(), targetList[ 0 ]->getId(), m_actionId ); - effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) ); - effectPacket->setRequestId( m_requestId ); - effectPacket->setResultId( m_resultId ); + auto actionResult = std::make_shared< EffectPacket1 >( m_sourceChara->getId(), m_sourceChara->getId(), m_actionId ); + actionResult->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) ); + actionResult->setRequestId( m_requestId ); + actionResult->setResultId( m_resultId ); + actionResult->setEffectFlags( Common::ActionEffectDisplayType::HideActionName ); + m_actorResultsMap.clear(); + return actionResult; + } + else if( targetCount > 1 ) // use AoeEffect packets + { + auto actionResult = std::make_shared< EffectPacket >( m_sourceChara->getId(), targetList[ 0 ]->getId(), m_actionId ); + actionResult->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) ); + actionResult->setRequestId( m_requestId ); + actionResult->setResultId( m_resultId ); uint8_t targetIndex = 0; - for( auto it = m_actorResultsMap.begin(); it != m_actorResultsMap.end(); ) + for( auto it = m_actorResultsMap.begin(); it != m_actorResultsMap.end(); ++it ) { // get all effect results for an actor auto actorResultList = it->second; + if( it->first ) + taskMgr.queueTask( World::makeActionIntegrityTask( m_resultId, it->first, actorResultList, 300 ) ); + for( auto& result : actorResultList ) { auto effect = result->getCalcResultParam(); - - // if effect result is a source/caster effect if( result->getTarget() == m_sourceChara ) - effectPacket->addSourceEffect( effect ); + actionResult->addSourceEffect( effect ); else - { - effectPacket->addTargetEffect( effect, result->getTarget()->getId() ); - taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( m_resultId, result->getTarget(), 1000 ) ); - } - - zone->addActionResult( std::move( result ) ); - + actionResult->addTargetEffect( effect, result->getTarget()->getId() ); } - actorResultList.clear(); - it = m_actorResultsMap.erase( it ); + //actorResultList.clear(); + //it = m_actorResultsMap.erase( it ); targetIndex++; if( targetIndex == 15 ) break; } - return effectPacket; + return actionResult; } - else if( remainingTargetCount == 1 ) // use Effect for single target + else // use Effect for single target { + auto actionResult = std::make_shared< EffectPacket1 >( m_sourceChara->getId(), targetList[ 0 ]->getId(), m_actionId ); + actionResult->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) ); + actionResult->setRequestId( m_requestId ); + actionResult->setResultId( m_resultId ); - Logger::debug( " - id: {}", targetList[0]->getId() ); - Logger::debug( "------------------------------------------" ); - - auto effectPacket = std::make_shared< EffectPacket1 >( m_sourceChara->getId(), targetList[ 0 ]->getId(), m_actionId ); - effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) ); - effectPacket->setRequestId( m_requestId ); - effectPacket->setResultId( m_resultId ); - - for( auto it = m_actorResultsMap.begin(); it != m_actorResultsMap.end(); ) + for( auto it = m_actorResultsMap.begin(); it != m_actorResultsMap.end(); ++it ) { // get all effect results for an actor auto actorResultList = it->second; + if( it->first ) + taskMgr.queueTask( World::makeActionIntegrityTask( m_resultId, it->first, actorResultList, 300 ) ); + for( auto& result : actorResultList ) { auto effect = result->getCalcResultParam(); - - // if effect result is a source/caster effect if( result->getTarget() == m_sourceChara ) - effectPacket->addSourceEffect( effect ); + actionResult->addSourceEffect( effect ); else - { - effectPacket->addTargetEffect( effect ); - taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( m_resultId, result->getTarget(), 1000 ) ); - } - - zone->addActionResult( std::move( result ) ); + actionResult->addTargetEffect( effect ); } - actorResultList.clear(); - it = m_actorResultsMap.erase( it ); + //actorResultList.clear(); + //it = m_actorResultsMap.erase( it ); } m_actorResultsMap.clear(); - - return effectPacket; - } - else // nothing is hit, this only happens when using aoe and AoeEffect8 is used on retail - { - auto effectPacket = makeZonePacket< FFXIVIpcActionResult1 >( m_sourceChara->getId() ); - - effectPacket->data().ActionKey = m_actionId; - effectPacket->data().Action = static_cast< uint16_t >( m_actionId ); - effectPacket->data().Target = m_sourceChara->getId(); - effectPacket->data().MainTarget = static_cast< uint64_t >( m_sourceChara->getId() ); - effectPacket->data().DirTarget = Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ); - effectPacket->data().Flag = Common::ActionEffectDisplayType::HideActionName; - effectPacket->data().RequestId = m_requestId; - effectPacket->data().ResultId = m_resultId; - - m_actorResultsMap.clear(); - - return effectPacket; + return actionResult; } } \ No newline at end of file diff --git a/src/world/Action/ActionResultBuilder.h b/src/world/Action/ActionResultBuilder.h index ee3819b3..a258d3d1 100644 --- a/src/world/Action/ActionResultBuilder.h +++ b/src/world/Action/ActionResultBuilder.h @@ -34,8 +34,6 @@ namespace Sapphire::World::Action private: void addResultToActor( Entity::CharaPtr& chara, ActionResultPtr result ); - uint64_t getResultDelayMs(); - Network::Packets::FFXIVPacketBasePtr createActionResultPacket( const std::vector< Entity::CharaPtr >& targetList ); private: @@ -44,7 +42,7 @@ namespace Sapphire::World::Action uint32_t m_resultId; Entity::CharaPtr m_sourceChara; - std::unordered_map< uint32_t, std::vector< ActionResultPtr > > m_actorResultsMap; + std::unordered_map< Entity::CharaPtr, std::vector< ActionResultPtr > > m_actorResultsMap; }; } \ No newline at end of file diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 30b43532..dbf779e6 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -983,7 +983,7 @@ void BNpc::autoAttack( CharaPtr pTarget ) effectEntry.Type = ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP; effectEntry.Arg0 = 3; effectEntry.Arg1 = 7; - auto resultId = pZone->getNextEffectResultId(); + auto resultId = pZone->getNextActionResultId(); effectPacket->setResultId( resultId ); effectPacket->addTargetEffect( effectEntry ); server().queueForPlayers( getInRangePlayerIds(), effectPacket ); @@ -991,7 +991,7 @@ void BNpc::autoAttack( CharaPtr pTarget ) pTarget->takeDamage( static_cast< uint16_t >( damage.first ) ); auto& taskMgr = Common::Service< World::Manager::TaskMgr >::ref(); - taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, pTarget, 500 ) ); + //taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, pTarget, 500 ) ); } } diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index 1318f29e..183e2718 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -504,7 +504,7 @@ void Chara::addStatusEffect( StatusEffect::StatusEffectPtr pEffect ) auto statusEffectAdd = makeZonePacket< FFXIVIpcActionIntegrity >( getId() ); - statusEffectAdd->data().ResultId = pZone->getNextEffectResultId(); + statusEffectAdd->data().ResultId = pZone->getNextActionResultId(); statusEffectAdd->data().Target = pEffect->getTargetActorId(); statusEffectAdd->data().Hp = getHp(); statusEffectAdd->data().Mp = static_cast< uint16_t >( getMp() ); diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 29f86fbf..e9f78550 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1311,7 +1311,7 @@ void Player::autoAttack( CharaPtr pTarget ) if( getClass() == ClassJob::Machinist || getClass() == ClassJob::Bard || getClass() == ClassJob::Archer ) effectPacket->setActionId( 8 ); - auto resultId = pZone->getNextEffectResultId(); + auto resultId = pZone->getNextActionResultId(); effectPacket->setResultId( resultId ); effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) ); effectPacket->addTargetEffect( entry ); @@ -1321,7 +1321,7 @@ void Player::autoAttack( CharaPtr pTarget ) pTarget->takeDamage( static_cast< uint32_t >( damage.first ) ); auto& taskMgr = Common::Service< TaskMgr >::ref(); - taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, pTarget, 500 ) ); + //taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, pTarget, 500 ) ); } diff --git a/src/world/Manager/DebugCommandMgr.cpp b/src/world/Manager/DebugCommandMgr.cpp index 3c512ad9..7dcbe84c 100644 --- a/src/world/Manager/DebugCommandMgr.cpp +++ b/src/world/Manager/DebugCommandMgr.cpp @@ -538,7 +538,7 @@ void DebugCommandMgr::add( char* data, Entity::Player& player, std::shared_ptr< entry.Arg0 = static_cast< uint8_t >( Common::ActionHitSeverityType::NormalDamage ); effectPacket->addTargetEffect( entry, static_cast< uint64_t >( player.getId() ) ); - effectPacket->setResultId( pCurrentZone->getNextEffectResultId() ); + effectPacket->setResultId( pCurrentZone->getNextActionResultId() ); server().queueForPlayer( player.getCharacterId(), effectPacket ); } diff --git a/src/world/Manager/TaskMgr.cpp b/src/world/Manager/TaskMgr.cpp index b3d3eebe..b17e79f2 100644 --- a/src/world/Manager/TaskMgr.cpp +++ b/src/world/Manager/TaskMgr.cpp @@ -9,27 +9,32 @@ using namespace Sapphire::World; void TaskMgr::update( uint64_t tickCount ) { - - for( auto it = m_taskList.begin(); it != m_taskList.end(); ) + std::vector< TaskPtr > tmpTaskList; + for( const auto& pTask : m_taskList ) { - auto pTask = *it; // is the task ready for execution? if( ( tickCount - pTask->getQueueTimeMs() ) >= pTask->getDelayTimeMs() ) { Logger::info( "[TaskMgr] " + pTask->toString() ); pTask->execute(); - it = m_taskList.erase( it ); } else - ++it; + tmpTaskList.push_back( pTask ); } + m_taskList = tmpTaskList; m_lastTick = tickCount; + while( !m_deferredTasks.empty() ) + { + auto pTask = m_deferredTasks.front(); + m_deferredTasks.pop(); + m_taskList.push_back( pTask ); + } } void TaskMgr::queueTask( const TaskPtr& pTask ) { pTask->onQueue(); - m_taskList.push_back( pTask ); + m_deferredTasks.push( pTask ); } diff --git a/src/world/Manager/TaskMgr.h b/src/world/Manager/TaskMgr.h index c4325489..a52371d7 100644 --- a/src/world/Manager/TaskMgr.h +++ b/src/world/Manager/TaskMgr.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -45,6 +46,7 @@ namespace Sapphire::World::Manager private: uint64_t m_lastTick{}; std::vector< TaskPtr > m_taskList; + std::queue< TaskPtr > m_deferredTasks; }; diff --git a/src/world/Task/ActionIntegrityTask.cpp b/src/world/Task/ActionIntegrityTask.cpp index f8f8a1b4..ce3c8241 100644 --- a/src/world/Task/ActionIntegrityTask.cpp +++ b/src/world/Task/ActionIntegrityTask.cpp @@ -14,10 +14,12 @@ using namespace Sapphire::World::Manager; using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets::WorldPackets::Server; -ActionIntegrityTask::ActionIntegrityTask( uint32_t resultId, Entity::CharaPtr pTarget, uint64_t delayTime ) : Task( delayTime ) +ActionIntegrityTask::ActionIntegrityTask( uint32_t resultId, Entity::CharaPtr pTarget, Action::ActionResultList& results, uint64_t delayTime ) : Task( delayTime ) { + Logger::debug( "Constructor called {} {} {}", resultId, pTarget->getId(), results.size() ); m_resultId = resultId; m_pTarget = std::move( pTarget ); + m_results = results; } void ActionIntegrityTask::onQueue() @@ -27,6 +29,9 @@ void ActionIntegrityTask::onQueue() void ActionIntegrityTask::execute() { + if( !m_pTarget ) + return; + auto& server = Common::Service< WorldServer >::ref(); auto inRangePlayers = m_pTarget->getInRangePlayerIds( true ); @@ -34,6 +39,12 @@ void ActionIntegrityTask::execute() if( inRangePlayers.empty() ) return; + for( auto& actionResult : m_results ) + { + if( actionResult && actionResult->getTarget() && actionResult->getTarget()->isAlive() ) + actionResult->execute(); + } + auto integrityPacket = makeZonePacket< FFXIVIpcActionIntegrity >( 0 ); auto& data = integrityPacket->data(); integrityPacket->setSourceActor( m_pTarget->getId() ); @@ -51,7 +62,7 @@ void ActionIntegrityTask::execute() std::string ActionIntegrityTask::toString() { - return fmt::format( "ActionIntegrityTask: ResultId#{}, TargetId#{}, ElapsedTimeMs: {}", m_resultId, m_pTarget->getId(), getDelayTimeMs() ); + return fmt::format( "ActionIntegrityTask: ResultId#{}, TargetId#{}, ElapsedTimeMs: {}", m_resultId, m_pTarget ? m_pTarget->getId() : 0, getDelayTimeMs() ); } diff --git a/src/world/Task/ActionIntegrityTask.h b/src/world/Task/ActionIntegrityTask.h index 0671c4a0..b0c2812f 100644 --- a/src/world/Task/ActionIntegrityTask.h +++ b/src/world/Task/ActionIntegrityTask.h @@ -4,6 +4,7 @@ #include #include #include "Task.h" +#include namespace Sapphire::World { @@ -11,7 +12,7 @@ namespace Sapphire::World class ActionIntegrityTask : public Task { public: - ActionIntegrityTask( uint32_t resultId, Entity::CharaPtr pTarget, uint64_t delayTime ); + ActionIntegrityTask( uint32_t resultId, Entity::CharaPtr pTarget, Action::ActionResultList& results, uint64_t delayTime ); void onQueue() override; void execute() override; @@ -20,6 +21,7 @@ public: private: uint32_t m_resultId; Entity::CharaPtr m_pTarget; + Action::ActionResultList m_results; }; template< typename... Args > diff --git a/src/world/Territory/Territory.cpp b/src/world/Territory/Territory.cpp index 71d7a421..375c7071 100644 --- a/src/world/Territory/Territory.cpp +++ b/src/world/Territory/Territory.cpp @@ -466,8 +466,6 @@ bool Territory::update( uint64_t tickCount ) updateSessions( tickCount, changedWeather ); onUpdate( tickCount ); - processActionResults( tickCount ); - if( !m_playerMap.empty() ) m_lastActivityTime = tickCount; @@ -824,7 +822,7 @@ void Territory::updateSpawnPoints() } } -uint32_t Territory::getNextEffectResultId() +uint32_t Territory::getNextActionResultId() { return m_effectCounter++; } @@ -875,30 +873,6 @@ std::shared_ptr< World::Navi::NaviProvider > Territory::getNaviProvider() return m_pNaviProvider; } -void Territory::addActionResult( World::Action::ActionResultPtr result ) -{ - m_actionResults.emplace_back( std::move( result ) ); -} - -void Territory::processActionResults( uint64_t tickCount ) -{ - // todo: move this to generic territory/instance delay wrapper cause it might be useful scheduling other things - for( auto it = m_actionResults.begin(); it != m_actionResults.end(); ) - { - auto effect = *it; - - if( tickCount < effect->getDelay() ) - { - ++it; - continue; - } - - effect->execute(); - - it = m_actionResults.erase( it ); - } -} - bool Territory::loadBNpcs() { auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); diff --git a/src/world/Territory/Territory.h b/src/world/Territory/Territory.h index d078dba4..d6b4f89c 100644 --- a/src/world/Territory/Territory.h +++ b/src/world/Territory/Territory.h @@ -72,8 +72,6 @@ namespace Sapphire uint32_t m_effectCounter{}; std::shared_ptr< World::Navi::NaviProvider > m_pNaviProvider; - std::vector< World::Action::ActionResultPtr > m_actionResults; - Common::TerritoryIdent m_ident; float m_inRangeDistance; @@ -194,13 +192,9 @@ namespace Sapphire void updateSpawnPoints(); - uint32_t getNextEffectResultId(); + uint32_t getNextActionResultId(); std::shared_ptr< World::Navi::NaviProvider > getNaviProvider(); - - void addActionResult( World::Action::ActionResultPtr result ); - - void processActionResults( uint64_t tickCount ); }; }