1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-27 22:57:45 +00:00
sapphire/src/world/Action/ActionResultBuilder.cpp

228 lines
7.7 KiB
C++
Raw Normal View History

#include "ActionResultBuilder.h"
#include "ActionResult.h"
2019-07-25 22:46:10 +10:00
2019-07-26 20:28:01 +10:00
#include <Actor/Player.h>
2019-07-25 22:46:10 +10:00
#include <Network/PacketWrappers/EffectPacket.h>
#include <Network/PacketWrappers/EffectPacket1.h>
2019-07-25 22:46:10 +10:00
#include <Territory/Territory.h>
#include <Util/Util.h>
#include <Util/UtilMath.h>
#include <Logging/Logger.h>
#include <Manager/TerritoryMgr.h>
2023-02-17 22:46:02 +01:00
#include <Manager/MgrUtil.h>
#include <Service.h>
2019-07-25 22:46:10 +10:00
#include <Manager/TaskMgr.h>
#include <Task/ActionIntegrityTask.h>
2019-07-25 22:46:10 +10:00
using namespace Sapphire;
using namespace Sapphire::World::Action;
2023-02-17 22:46:02 +01:00
using namespace Sapphire::World::Manager;
2019-07-25 22:46:10 +10:00
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets::Server;
2019-07-25 22:46:10 +10:00
ActionResultBuilder::ActionResultBuilder( Entity::CharaPtr source, uint32_t actionId, uint32_t resultId, uint16_t requestId ) :
2019-07-25 22:46:10 +10:00
m_sourceChara( std::move( source ) ),
2019-07-26 20:28:01 +10:00
m_actionId( actionId ),
m_resultId( resultId ),
m_requestId( requestId )
2019-07-25 22:46:10 +10:00
{
}
uint64_t ActionResultBuilder::getResultDelayMs()
2019-07-25 22:46:10 +10:00
{
// todo: actually figure this retarded shit out
return Common::Util::getTimeMs() + 850;
2019-07-25 22:46:10 +10:00
}
void ActionResultBuilder::addResultToActor( Entity::CharaPtr& chara, ActionResultPtr result )
2019-07-25 22:46:10 +10:00
{
auto it = m_actorResultsMap.find( chara->getId() );
if( it == m_actorResultsMap.end() )
2019-07-25 22:46:10 +10:00
{
2020-01-06 17:52:45 +09:00
// create a new one
auto resultList = std::vector< ActionResultPtr >();
2019-07-25 22:46:10 +10:00
resultList.push_back( std::move( result ) );
2019-07-25 22:46:10 +10:00
m_actorResultsMap[ chara->getId() ] = resultList;
2020-01-06 17:52:45 +09:00
return;
2019-07-25 22:46:10 +10:00
}
it->second.push_back( std::move( result ) );
2019-07-25 22:46:10 +10:00
}
void ActionResultBuilder::heal( Entity::CharaPtr& effectTarget, Entity::CharaPtr& healingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionResultFlag flag )
2019-07-25 22:46:10 +10:00
{
ActionResultPtr nextResult = make_ActionResult( healingTarget, getResultDelayMs() );
2020-01-05 20:49:50 +09:00
nextResult->heal( amount, severity, flag );
addResultToActor( effectTarget, nextResult );
2020-01-05 17:09:27 +09:00
}
void ActionResultBuilder::restoreMP( Entity::CharaPtr& target, Entity::CharaPtr& restoringTarget, uint32_t amount, Common::ActionResultFlag flag )
2020-01-05 17:09:27 +09:00
{
ActionResultPtr nextResult = make_ActionResult( restoringTarget, getResultDelayMs() ); // restore mp source actor
2020-01-05 20:49:50 +09:00
nextResult->restoreMP( amount, flag );
addResultToActor( target, nextResult );
2020-01-05 17:09:27 +09:00
}
void ActionResultBuilder::damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionResultFlag flag )
2020-01-05 17:09:27 +09:00
{
ActionResultPtr nextResult = make_ActionResult( damagingTarget, getResultDelayMs() );
2020-01-05 20:49:50 +09:00
nextResult->damage( amount, severity, flag );
addResultToActor( damagingTarget, nextResult );
2020-01-05 17:09:27 +09:00
}
void ActionResultBuilder::startCombo( Entity::CharaPtr& target, uint16_t actionId )
2020-01-05 17:09:27 +09:00
{
ActionResultPtr nextResult = make_ActionResult( target, 0 );
2020-01-05 17:09:27 +09:00
nextResult->startCombo( actionId );
addResultToActor( target, nextResult );
2020-01-05 17:09:27 +09:00
}
void ActionResultBuilder::comboSucceed( Entity::CharaPtr& target )
2020-01-05 17:09:27 +09:00
{
ActionResultPtr nextResult = make_ActionResult( target, 0 );
2020-01-05 20:49:50 +09:00
nextResult->comboSucceed();
addResultToActor( target, nextResult );
2019-07-25 22:46:10 +10:00
}
void ActionResultBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param )
2020-01-06 19:25:01 +09:00
{
ActionResultPtr nextResult = make_ActionResult( target, 0 );
2020-01-06 19:25:01 +09:00
nextResult->applyStatusEffect( statusId, param );
addResultToActor( target, nextResult );
2020-01-06 19:25:01 +09:00
}
void ActionResultBuilder::mount( Entity::CharaPtr& target, uint16_t mountId )
2020-01-23 22:36:01 +09:00
{
ActionResultPtr nextResult = make_ActionResult( target, getResultDelayMs() );
2020-01-23 22:36:01 +09:00
nextResult->mount( mountId );
addResultToActor( target, nextResult );
2020-01-23 22:36:01 +09:00
}
void ActionResultBuilder::sendActionResults( const std::vector< Entity::CharaPtr >& targetList )
2019-07-25 22:46:10 +10:00
{
2019-07-25 23:21:42 +10:00
Logger::debug( "EffectBuilder result: " );
Logger::debug( "Targets afflicted: {}", targetList.size() );
2020-01-05 17:09:27 +09:00
2020-01-06 04:29:45 +09:00
do // we want to send at least one packet even nothing is hit so other players can see
2020-01-05 17:09:27 +09:00
{
auto packet = createActionResultPacket( targetList );
2023-02-17 22:46:02 +01:00
server().queueForPlayers( m_sourceChara->getInRangePlayerIds( true ), packet );
2020-01-05 17:09:27 +09:00
}
while( !m_actorResultsMap.empty() );
2020-01-05 17:09:27 +09:00
}
std::shared_ptr< FFXIVPacketBase > ActionResultBuilder::createActionResultPacket( const std::vector< Entity::CharaPtr >& targetList )
2020-01-05 17:09:27 +09:00
{
auto remainingTargetCount = 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() );
2020-01-05 17:09:27 +09:00
if( remainingTargetCount > 1 ) // use AoeEffect packets
{
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 );
2020-01-05 17:09:27 +09:00
uint8_t targetIndex = 0;
for( auto it = m_actorResultsMap.begin(); it != m_actorResultsMap.end(); )
2020-01-05 17:09:27 +09:00
{
// get all effect results for an actor
auto actorResultList = it->second;
2020-01-05 17:09:27 +09:00
for( auto& result : actorResultList )
2020-01-05 17:09:27 +09:00
{
auto effect = result->getCalcResultParam();
// if effect result is a source/caster effect
if( result->getTarget() == m_sourceChara )
effectPacket->addSourceEffect( effect );
else
{
effectPacket->addTargetEffect( effect, result->getTarget()->getId() );
taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( m_resultId, result->getTarget(), 1000 ) );
}
zone->addActionResult( std::move( result ) );
2020-01-05 17:09:27 +09:00
}
actorResultList.clear();
it = m_actorResultsMap.erase( it );
2020-01-05 17:09:27 +09:00
targetIndex++;
if( targetIndex == 15 )
2020-01-05 17:09:27 +09:00
break;
}
return effectPacket;
2020-01-05 17:09:27 +09:00
}
else if( remainingTargetCount == 1 ) // use Effect for single target
2019-07-25 22:46:10 +10:00
{
Logger::debug( " - id: {}", targetList[0]->getId() );
Logger::debug( "------------------------------------------" );
2019-07-26 21:58:13 +10:00
auto effectPacket = std::make_shared< EffectPacket1 >( m_sourceChara->getId(), targetList[ 0 ]->getId(), m_actionId );
2019-07-25 22:46:10 +10:00
effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) );
effectPacket->setRequestId( m_requestId );
effectPacket->setResultId( m_resultId );
2019-07-25 22:46:10 +10:00
for( auto it = m_actorResultsMap.begin(); it != m_actorResultsMap.end(); )
2020-01-05 17:09:27 +09:00
{
// get all effect results for an actor
auto actorResultList = it->second;
2019-07-25 22:46:10 +10:00
for( auto& result : actorResultList )
{
auto effect = result->getCalcResultParam();
// if effect result is a source/caster effect
if( result->getTarget() == m_sourceChara )
effectPacket->addSourceEffect( effect );
else
{
effectPacket->addTargetEffect( effect );
taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( m_resultId, result->getTarget(), 1000 ) );
}
zone->addActionResult( std::move( result ) );
}
2019-07-25 22:46:10 +10:00
actorResultList.clear();
it = m_actorResultsMap.erase( it );
}
m_actorResultsMap.clear();
2020-01-06 04:29:45 +09:00
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;
2020-01-06 04:29:45 +09:00
m_actorResultsMap.clear();
2020-01-05 17:09:27 +09:00
return effectPacket;
}
2019-07-25 22:46:10 +10:00
}