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

244 lines
8.3 KiB
C++
Raw Normal View History

2019-07-25 22:46:10 +10:00
#include "EffectBuilder.h"
#include "EffectResult.h"
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 <Territory/Territory.h>
#include <Util/Util.h>
#include <Util/UtilMath.h>
#include <Logging/Logger.h>
using namespace Sapphire;
using namespace Sapphire::World::Action;
using namespace Sapphire::Network::Packets;
2019-07-26 20:28:01 +10:00
EffectBuilder::EffectBuilder( Entity::CharaPtr source, uint32_t actionId, uint16_t sequence ) :
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_sequence( sequence )
2019-07-25 22:46:10 +10:00
{
}
uint64_t EffectBuilder::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
}
2020-01-05 17:09:27 +09:00
std::shared_ptr< std::vector< EffectResultPtr > > EffectBuilder::getResultList( Entity::CharaPtr& chara )
2019-07-25 22:46:10 +10:00
{
auto it = m_resolvedEffects.find( chara->getId() );
if( it == m_resolvedEffects.end() )
{
// create a new one and return it
2020-01-05 17:09:27 +09:00
auto resultList = std::make_shared< std::vector< EffectResultPtr > >();
2019-07-25 22:46:10 +10:00
2020-01-05 17:09:27 +09:00
m_resolvedEffects[ chara->getId() ] = resultList;
2019-07-25 22:46:10 +10:00
2020-01-05 17:09:27 +09:00
return resultList;
2019-07-25 22:46:10 +10:00
}
return it->second;
}
2020-01-05 20:49:50 +09:00
void EffectBuilder::heal( Entity::CharaPtr& effectTarget, Entity::CharaPtr& healingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
2019-07-25 22:46:10 +10:00
{
2020-01-05 20:49:50 +09:00
auto resultList = getResultList( effectTarget );
2020-01-05 17:09:27 +09:00
assert( resultList );
2019-07-25 22:46:10 +10:00
2020-01-05 20:49:50 +09:00
EffectResultPtr nextResult = make_EffectResult( healingTarget, getResultDelayMs() );
nextResult->heal( amount, severity, flag );
2020-01-05 17:09:27 +09:00
resultList->push_back( std::move( nextResult ) );
}
2020-01-05 20:49:50 +09:00
void EffectBuilder::restoreMP( Entity::CharaPtr& target, Entity::CharaPtr& restoringTarget, uint32_t amount, Common::ActionEffectResultFlag flag )
2020-01-05 17:09:27 +09:00
{
auto resultList = getResultList( target );
assert( resultList );
2020-01-05 20:49:50 +09:00
EffectResultPtr nextResult = make_EffectResult( restoringTarget, getResultDelayMs() ); // restore mp source actor
nextResult->restoreMP( amount, flag );
2020-01-05 17:09:27 +09:00
resultList->push_back( std::move( nextResult ) );
}
2020-01-05 20:49:50 +09:00
void EffectBuilder::damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
2020-01-05 17:09:27 +09:00
{
2020-01-05 20:49:50 +09:00
auto resultList = getResultList( effectTarget );
2020-01-05 17:09:27 +09:00
assert( resultList );
2020-01-05 20:49:50 +09:00
EffectResultPtr nextResult = make_EffectResult( damagingTarget, getResultDelayMs() );
nextResult->damage( amount, severity, flag );
2020-01-05 17:09:27 +09:00
resultList->push_back( std::move( nextResult ) );
}
void EffectBuilder::startCombo( Entity::CharaPtr& target, uint16_t actionId )
{
auto resultList = getResultList( target );
assert( resultList );
2019-07-25 22:46:10 +10:00
2020-01-05 17:09:27 +09:00
EffectResultPtr nextResult = make_EffectResult( target, 0 );
nextResult->startCombo( actionId );
resultList->push_back( std::move( nextResult ) );
}
2020-01-05 20:49:50 +09:00
void EffectBuilder::comboSucceed( Entity::CharaPtr& target )
2020-01-05 17:09:27 +09:00
{
auto resultList = getResultList( target );
assert( resultList );
EffectResultPtr nextResult = make_EffectResult( target, 0 );
2020-01-05 20:49:50 +09:00
nextResult->comboSucceed();
2020-01-05 17:09:27 +09:00
resultList->push_back( std::move( nextResult ) );
2019-07-25 22:46:10 +10:00
}
void EffectBuilder::buildAndSendPackets()
{
2020-01-05 17:09:27 +09:00
auto targetCount = m_resolvedEffects.size();
2019-07-25 23:21:42 +10:00
Logger::debug( "EffectBuilder result: " );
2020-01-05 17:09:27 +09:00
Logger::debug( "Targets afflicted: {}", targetCount );
auto globalSequence = m_sourceChara->getCurrentTerritory()->getNextEffectSequence();
2020-01-05 20:54:49 +09:00
while( !m_resolvedEffects.empty() )
2020-01-05 17:09:27 +09:00
{
auto packet = buildNextEffectPacket( globalSequence );
m_sourceChara->sendToInRangeSet( packet, true );
}
}
std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( uint32_t globalSequence )
{
auto remainingTargetCount = m_resolvedEffects.size();
2019-07-25 22:46:10 +10:00
2020-01-05 17:09:27 +09:00
if( remainingTargetCount > 1 ) // use AoeEffect packets
{
int packetSize = remainingTargetCount <= 8 ? 8 :
( remainingTargetCount <= 16 ? 16 :
( remainingTargetCount <= 24 ? 24 : 32 ) );
using EffectHeader = Server::FFXIVIpcAoeEffect< 8 >; // dummy type to access header part of the packet
FFXIVPacketBasePtr effectPacket = nullptr;
EffectHeader* pHeader;
Common::EffectEntry* pEntry;
uint64_t* pEffectTargetId;
uint16_t* pFlag;
switch( packetSize )
{
case 8:
{
auto p = makeZonePacket< Server::FFXIVIpcAoeEffect8 >( m_sourceChara->getId() );
2020-01-05 20:49:50 +09:00
pHeader = reinterpret_cast< EffectHeader* >( &p->data() );
pEntry = reinterpret_cast< Common::EffectEntry* >( &p->data().effects );
pEffectTargetId = reinterpret_cast< uint64_t* >( &p->data().effectTargetId );
pFlag = reinterpret_cast< uint16_t* >( &p->data().unkFlag );
2020-01-05 17:09:27 +09:00
effectPacket = std::move( p );
break;
}
case 16:
{
auto p = makeZonePacket< Server::FFXIVIpcAoeEffect16 >( m_sourceChara->getId() );
2020-01-05 20:49:50 +09:00
pHeader = reinterpret_cast< EffectHeader* >( &p->data() );
pEntry = reinterpret_cast< Common::EffectEntry* >( &p->data().effects );
pEffectTargetId = reinterpret_cast< uint64_t* >( &p->data().effectTargetId );
pFlag = reinterpret_cast< uint16_t* >( &p->data().unkFlag );
2020-01-05 17:09:27 +09:00
effectPacket = std::move( p );
break;
}
case 24:
{
auto p = makeZonePacket< Server::FFXIVIpcAoeEffect24 >( m_sourceChara->getId() );
2020-01-05 20:49:50 +09:00
pHeader = reinterpret_cast< EffectHeader* >( &p->data() );
pEntry = reinterpret_cast< Common::EffectEntry* >( &p->data().effects );
pEffectTargetId = reinterpret_cast< uint64_t* >( &p->data().effectTargetId );
pFlag = reinterpret_cast< uint16_t* >( &p->data().unkFlag );
2020-01-05 17:09:27 +09:00
effectPacket = std::move( p );
break;
}
case 32:
{
auto p = makeZonePacket< Server::FFXIVIpcAoeEffect32 >( m_sourceChara->getId() );
2020-01-05 20:49:50 +09:00
pHeader = reinterpret_cast< EffectHeader* >( &p->data() );
pEntry = reinterpret_cast< Common::EffectEntry* >( &p->data().effects );
pEffectTargetId = reinterpret_cast< uint64_t* >( &p->data().effectTargetId );
pFlag = reinterpret_cast< uint16_t* >( &p->data().unkFlag );
2020-01-05 17:09:27 +09:00
effectPacket = std::move( p );
break;
}
}
2020-01-05 21:31:54 +09:00
assert( effectPacket );
2020-01-05 17:09:27 +09:00
pHeader->actionId = m_actionId;
pHeader->actionAnimationId = static_cast< uint16_t >( m_actionId );
pHeader->animationTargetId = m_sourceChara->getId();
pHeader->someTargetId = 0xE0000000;
pHeader->rotation = Common::Util::floatToUInt16Rot( m_sourceChara->getRot() );
pHeader->effectDisplayType = Common::ActionEffectDisplayType::ShowActionName;
pHeader->effectCount = static_cast< uint8_t >( remainingTargetCount > packetSize ? packetSize : remainingTargetCount );
pHeader->sourceSequence = m_sequence;
pHeader->globalSequence = globalSequence;
uint8_t targetIndex = 0;
for( auto it = m_resolvedEffects.begin(); it != m_resolvedEffects.end(); )
{
auto resultList = it->second;
2020-01-05 20:54:49 +09:00
assert( !resultList->empty() );
2020-01-05 17:09:27 +09:00
auto firstResult = resultList->data()[ 0 ];
pEffectTargetId[ targetIndex ] = firstResult->getTarget()->getId();
Logger::debug( " - id: {}", pEffectTargetId[ targetIndex ] );
for( auto i = 0; i < resultList->size(); i++ )
{
auto result = resultList->data()[ i ];
pEntry[ targetIndex * 8 + i ] = result->buildEffectEntry();
m_sourceChara->getCurrentTerritory()->addEffectResult( std::move( result ) );
}
resultList->clear();
it = m_resolvedEffects.erase( it );
targetIndex++;
if( targetIndex == packetSize )
break;
}
pFlag[0] = 0x7FFF;
pFlag[1] = 0x7FFF;
pFlag[2] = 0x7FFF;
return effectPacket;
}
else
2019-07-25 22:46:10 +10:00
{
2020-01-05 17:09:27 +09:00
auto resultList = m_resolvedEffects.begin()->second;
2020-01-05 20:49:50 +09:00
assert( !resultList->empty() );
2020-01-05 17:09:27 +09:00
auto firstResult = resultList->data()[ 0 ];
Logger::debug( " - id: {}", firstResult->getTarget()->getId() );
2019-07-25 23:21:42 +10:00
2019-07-26 21:58:13 +10:00
auto seq = m_sourceChara->getCurrentTerritory()->getNextEffectSequence();
2020-01-05 17:09:27 +09:00
auto effectPacket = std::make_shared< Server::EffectPacket >( m_sourceChara->getId(), firstResult->getTarget()->getId(), m_actionId );
2019-07-25 22:46:10 +10:00
effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) );
2019-07-26 21:58:13 +10:00
effectPacket->setSequence( seq, m_sequence );
2019-07-25 22:46:10 +10:00
2020-01-05 17:09:27 +09:00
for( int i = 0; i < resultList->size(); i++ )
{
auto result = resultList->data()[ i ];
effectPacket->addEffect( result->buildEffectEntry() );
m_sourceChara->getCurrentTerritory()->addEffectResult( std::move( result ) );
}
2019-07-25 22:46:10 +10:00
2020-01-05 17:09:27 +09:00
resultList->clear();
2019-07-25 22:46:10 +10:00
2020-01-05 17:09:27 +09:00
m_resolvedEffects.clear();
2020-01-05 17:09:27 +09:00
return effectPacket;
}
2019-07-25 22:46:10 +10:00
}