1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-27 14:57:44 +00:00

slight effect rework; support multiple ct/tg per action for both aoe and singletarget; fix several inconsistencies with effect packets;

This commit is contained in:
Alice Ogeda 2022-01-10 19:31:21 -03:00
parent 3b02afe99b
commit 3d5bcc7d67
9 changed files with 140 additions and 103 deletions

View file

@ -106,10 +106,11 @@ bool Action::Action::init()
case Common::ClassJob::Bard: case Common::ClassJob::Bard:
case Common::ClassJob::Archer: case Common::ClassJob::Archer:
m_range = 25; m_range = 25;
break;
// anything that isnt ranged // anything that isnt ranged
default: default:
m_range = 3; m_range = 3;
break;
} }
} }
@ -431,7 +432,7 @@ void Action::Action::execute()
// set currently casted action as the combo action if it interrupts a combo // set currently casted action as the combo action if it interrupts a combo
// ignore it otherwise (ogcds, etc.) // ignore it otherwise (ogcds, etc.)
if( !m_actionData->data().ComboContinue ) if( m_actionData->data().ComboContinue )
{ {
// potential combo starter or correct combo from last action, must hit something to progress combo // potential combo starter or correct combo from last action, must hit something to progress combo
if( !m_hitActors.empty() && ( !isComboAction() || isCorrectCombo() ) ) if( !m_hitActors.empty() && ( !isComboAction() || isCorrectCombo() ) )
@ -512,7 +513,7 @@ void Action::Action::buildEffects()
if( !hasLutEntry || m_hitActors.empty() ) if( !hasLutEntry || m_hitActors.empty() )
{ {
// send any effect packet added by script or an empty one just to play animation for other players // send any effect packet added by script or an empty one just to play animation for other players
m_effectBuilder->buildAndSendPackets(); m_effectBuilder->buildAndSendPackets( m_hitActors );
return; return;
} }
@ -533,14 +534,14 @@ void Action::Action::buildEffects()
if( m_lutEntry.potency > 0 ) if( m_lutEntry.potency > 0 )
{ {
auto dmg = calcDamage( isCorrectCombo() ? m_lutEntry.comboPotency : m_lutEntry.potency ); auto dmg = calcDamage( isCorrectCombo() ? m_lutEntry.comboPotency : m_lutEntry.potency );
m_effectBuilder->damage( actor, actor, dmg.first, dmg.second ); m_effectBuilder->damage( m_pSource, actor, dmg.first, dmg.second );
if( dmg.first > 0 ) if( dmg.first > 0 )
actor->onActionHostile( m_pSource ); actor->onActionHostile( m_pSource );
if( isCorrectCombo() && shouldApplyComboSucceedEffect ) if( isCorrectCombo() && shouldApplyComboSucceedEffect )
{ {
m_effectBuilder->comboSucceed( actor ); m_effectBuilder->comboSucceed( m_pSource );
shouldApplyComboSucceedEffect = false; shouldApplyComboSucceedEffect = false;
} }
@ -558,9 +559,10 @@ void Action::Action::buildEffects()
shouldRestoreMP = false; shouldRestoreMP = false;
} }
if ( !m_actionData->data().ComboContinue ) // we need something like m_actionData->hasNextComboAction if( m_actionData->data().ComboContinue ) // we need something like m_actionData->hasNextComboAction
{ {
m_effectBuilder->startCombo( actor, getId() ); // this is on all targets hit m_effectBuilder->startCombo( m_pSource, getId() ); // this is on all targets hit
m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() );
} }
} }
} }
@ -582,7 +584,7 @@ void Action::Action::buildEffects()
} }
} }
m_effectBuilder->buildAndSendPackets(); m_effectBuilder->buildAndSendPackets( m_hitActors );
// TODO: disabled, reset kills our queued actions // TODO: disabled, reset kills our queued actions
// at this point we're done with it and no longer need it // at this point we're done with it and no longer need it

View file

@ -33,159 +33,169 @@ uint64_t EffectBuilder::getResultDelayMs()
return Common::Util::getTimeMs() + 850; return Common::Util::getTimeMs() + 850;
} }
void EffectBuilder::moveToResultList( Entity::CharaPtr& chara, EffectResultPtr result ) void EffectBuilder::addResultToActor( Entity::CharaPtr& chara, EffectResultPtr result )
{ {
auto it = m_resolvedEffects.find( chara->getId() ); auto it = m_actorEffectsMap.find( chara->getId() );
if( it == m_resolvedEffects.end() ) if( it == m_actorEffectsMap.end() )
{ {
// create a new one // create a new one
auto resultList = std::make_shared< std::vector< EffectResultPtr > >(); auto resultList = std::vector< EffectResultPtr >();
m_resolvedEffects[ chara->getId() ] = resultList; resultList.push_back( std::move( result ) );
resultList->push_back( std::move( result ) ); m_actorEffectsMap[ chara->getId() ] = resultList;
return; return;
} }
it->second->push_back( std::move( result ) ); it->second.push_back( std::move( result ) );
} }
void EffectBuilder::heal( Entity::CharaPtr& effectTarget, Entity::CharaPtr& healingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag ) void EffectBuilder::heal( Entity::CharaPtr& effectTarget, Entity::CharaPtr& healingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
{ {
EffectResultPtr nextResult = make_EffectResult( healingTarget, getResultDelayMs() ); EffectResultPtr nextResult = make_EffectResult( healingTarget, getResultDelayMs() );
nextResult->heal( amount, severity, flag ); nextResult->heal( amount, severity, flag );
moveToResultList( effectTarget, nextResult ); addResultToActor( effectTarget, nextResult );
} }
void EffectBuilder::restoreMP( Entity::CharaPtr& target, Entity::CharaPtr& restoringTarget, uint32_t amount, Common::ActionEffectResultFlag flag ) void EffectBuilder::restoreMP( Entity::CharaPtr& target, Entity::CharaPtr& restoringTarget, uint32_t amount, Common::ActionEffectResultFlag flag )
{ {
EffectResultPtr nextResult = make_EffectResult( restoringTarget, getResultDelayMs() ); // restore mp source actor EffectResultPtr nextResult = make_EffectResult( restoringTarget, getResultDelayMs() ); // restore mp source actor
nextResult->restoreMP( amount, flag ); nextResult->restoreMP( amount, flag );
moveToResultList( target, nextResult ); addResultToActor( target, nextResult );
} }
void EffectBuilder::damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag ) void EffectBuilder::damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
{ {
EffectResultPtr nextResult = make_EffectResult( damagingTarget, getResultDelayMs() ); EffectResultPtr nextResult = make_EffectResult( damagingTarget, getResultDelayMs() );
nextResult->damage( amount, severity, flag ); nextResult->damage( amount, severity, flag );
moveToResultList( effectTarget, nextResult ); addResultToActor( damagingTarget, nextResult );
} }
void EffectBuilder::startCombo( Entity::CharaPtr& target, uint16_t actionId ) void EffectBuilder::startCombo( Entity::CharaPtr& target, uint16_t actionId )
{ {
EffectResultPtr nextResult = make_EffectResult( target, 0 ); EffectResultPtr nextResult = make_EffectResult( target, 0 );
nextResult->startCombo( actionId ); nextResult->startCombo( actionId );
moveToResultList( target, nextResult ); addResultToActor( target, nextResult );
} }
void EffectBuilder::comboSucceed( Entity::CharaPtr& target ) void EffectBuilder::comboSucceed( Entity::CharaPtr& target )
{ {
EffectResultPtr nextResult = make_EffectResult( target, 0 ); EffectResultPtr nextResult = make_EffectResult( target, 0 );
nextResult->comboSucceed(); nextResult->comboSucceed();
moveToResultList( target, nextResult ); addResultToActor( target, nextResult );
} }
void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param ) void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param )
{ {
EffectResultPtr nextResult = make_EffectResult( target, 0 ); EffectResultPtr nextResult = make_EffectResult( target, 0 );
nextResult->applyStatusEffect( statusId, param ); nextResult->applyStatusEffect( statusId, param );
moveToResultList( target, nextResult ); addResultToActor( target, nextResult );
} }
void EffectBuilder::mount( Entity::CharaPtr& target, uint16_t mountId ) void EffectBuilder::mount( Entity::CharaPtr& target, uint16_t mountId )
{ {
EffectResultPtr nextResult = make_EffectResult( target, getResultDelayMs() ); EffectResultPtr nextResult = make_EffectResult( target, getResultDelayMs() );
nextResult->mount( mountId ); nextResult->mount( mountId );
moveToResultList( target, nextResult ); addResultToActor( target, nextResult );
} }
void EffectBuilder::buildAndSendPackets() void EffectBuilder::buildAndSendPackets( const std::vector< Entity::CharaPtr >& targetList )
{ {
auto targetCount = m_resolvedEffects.size();
Logger::debug( "EffectBuilder result: " ); Logger::debug( "EffectBuilder result: " );
Logger::debug( "Targets afflicted: {}", targetCount ); Logger::debug( "Targets afflicted: {}", targetList.size() );
auto globalSequence = m_sourceChara->getCurrentTerritory()->getNextEffectSequence();
do // we want to send at least one packet even nothing is hit so other players can see do // we want to send at least one packet even nothing is hit so other players can see
{ {
auto packet = buildNextEffectPacket( globalSequence ); auto packet = buildNextEffectPacket( targetList );
m_sourceChara->sendToInRangeSet( packet, true ); m_sourceChara->sendToInRangeSet( packet, true );
} }
while( !m_resolvedEffects.empty() ); while( !m_actorEffectsMap.empty() );
} }
std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( uint32_t globalSequence ) std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( const std::vector< Entity::CharaPtr >& targetList )
{ {
auto remainingTargetCount = m_resolvedEffects.size(); auto remainingTargetCount = targetList.size();
auto globalSequence = m_sourceChara->getCurrentTerritory()->getNextEffectSequence();
if( remainingTargetCount > 1 ) // use AoeEffect packets if( remainingTargetCount > 1 ) // use AoeEffect packets
{ {
auto effectResult = makeZonePacket< FFXIVIpcActionResult >( m_sourceChara->getId() ); auto effectPacket = std::make_shared< EffectPacket >( m_sourceChara->getId(), m_actionId );
Common::CalcResultParam* pEntry; effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) );
uint64_t* pEffectTargetId; effectPacket->setSequence( globalSequence, m_sequence );
effectPacket->setTargetActor( targetList[ 0 ]->getId() );
effectResult->data().ActionKey = m_actionId;
effectResult->data().ActionKind = 1;
effectResult->data().Action = static_cast< uint16_t >( m_actionId );
effectResult->data().MainTarget = m_sourceChara->getId();
effectResult->data().DirTarget = Common::Util::floatToUInt16Rot( m_sourceChara->getRot() );
effectResult->data().Flag = Common::ActionEffectDisplayType::ShowActionName;
effectResult->data().TargetCount = static_cast< uint8_t >( remainingTargetCount );
effectResult->data().RequestId = m_sequence;
effectResult->data().ResultId = globalSequence;
uint8_t targetIndex = 0; uint8_t targetIndex = 0;
for( auto it = m_resolvedEffects.begin(); it != m_resolvedEffects.end(); ) for( auto it = m_actorEffectsMap.begin(); it != m_actorEffectsMap.end(); )
{ {
auto resultList = it->second; // get all effect results for an actor
assert( !resultList->empty() ); auto actorResultList = it->second;
auto firstResult = resultList->data()[ 0 ];
pEffectTargetId[ targetIndex ] = firstResult->getTarget()->getId();
Logger::debug( " - id: {}", pEffectTargetId[ targetIndex ] );
for( auto i = 0; i < resultList->size(); i++ ) for( auto i = 0; i < actorResultList.size(); ++i )
{ {
auto result = resultList->data()[ i ]; auto result = actorResultList.data()[ i ];
pEntry[ targetIndex * 8 + i ] = result->buildEffectEntry(); auto effect = result->buildEffectEntry();
// if effect result is a source/caster effect
if( result->getTarget() == m_sourceChara )
{
effectPacket->addSourceEffect( effect );
}
else
{
effectPacket->addTargetEffect( effect, result->getTarget()->getId() );
}
m_sourceChara->getCurrentTerritory()->addEffectResult( std::move( result ) ); m_sourceChara->getCurrentTerritory()->addEffectResult( std::move( result ) );
} }
resultList->clear();
it = m_resolvedEffects.erase( it );
actorResultList.clear();
it = m_actorEffectsMap.erase( it );
targetIndex++; targetIndex++;
if( targetIndex == 15 ) if( targetIndex == 15 )
break; break;
} }
return effectResult; return effectPacket;
} }
else if( remainingTargetCount == 1 ) // use Effect for single target else if( remainingTargetCount == 1 ) // use Effect for single target
{ {
auto resultList = m_resolvedEffects.begin()->second; Logger::debug( " - id: {}", targetList[0]->getId() );
assert( !resultList->empty() ); Logger::debug( "------------------------------------------" );
auto firstResult = resultList->data()[ 0 ];
Logger::debug( " - id: {}", firstResult->getTarget()->getId() );
auto seq = m_sourceChara->getCurrentTerritory()->getNextEffectSequence(); auto effectPacket = std::make_shared< EffectPacket1 >( m_sourceChara->getId(), targetList[ 0 ]->getId(), m_actionId );
auto effectPacket = std::make_shared< EffectPacket1 >( m_sourceChara->getId(), firstResult->getTarget()->getId(), m_actionId );
effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) ); effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) );
effectPacket->setSequence( seq, m_sequence ); effectPacket->setSequence( globalSequence, m_sequence );
for( int i = 0; i < resultList->size(); i++ ) for( auto it = m_actorEffectsMap.begin(); it != m_actorEffectsMap.end(); )
{ {
auto result = resultList->data()[ i ]; // get all effect results for an actor
effectPacket->addTargetEffect( result->buildEffectEntry() ); auto actorResultList = it->second;
for( auto i = 0; i < actorResultList.size(); ++i )
{
auto result = actorResultList.data()[ i ];
auto effect = result->buildEffectEntry();
// if effect result is a source/caster effect
if( result->getTarget() == m_sourceChara )
{
effectPacket->addSourceEffect( effect );
}
else
{
effectPacket->addTargetEffect( effect );
}
m_sourceChara->getCurrentTerritory()->addEffectResult( std::move( result ) ); m_sourceChara->getCurrentTerritory()->addEffectResult( std::move( result ) );
} }
resultList->clear(); actorResultList.clear();
it = m_actorEffectsMap.erase( it );
}
m_resolvedEffects.clear(); m_actorEffectsMap.clear();
return effectPacket; return effectPacket;
} }
@ -202,6 +212,8 @@ std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( uint32_
effectPacket->data().RequestId = m_sequence; effectPacket->data().RequestId = m_sequence;
effectPacket->data().ResultId = globalSequence; effectPacket->data().ResultId = globalSequence;
m_actorEffectsMap.clear();
return effectPacket; return effectPacket;
} }
} }

View file

@ -29,22 +29,21 @@ namespace Sapphire::World::Action
void mount( Entity::CharaPtr& target, uint16_t mountId ); void mount( Entity::CharaPtr& target, uint16_t mountId );
void buildAndSendPackets(); void buildAndSendPackets( const std::vector< Entity::CharaPtr >& targetList );
private: private:
void moveToResultList( Entity::CharaPtr& chara, EffectResultPtr result ); void addResultToActor( Entity::CharaPtr& chara, EffectResultPtr result );
uint64_t getResultDelayMs(); uint64_t getResultDelayMs();
std::shared_ptr< Sapphire::Network::Packets::FFXIVPacketBase > buildNextEffectPacket( uint32_t globalSequence ); std::shared_ptr< Sapphire::Network::Packets::FFXIVPacketBase > buildNextEffectPacket( const std::vector< Entity::CharaPtr >& targetList );
private: private:
uint32_t m_actionId; uint32_t m_actionId;
uint16_t m_sequence; uint16_t m_sequence;
Entity::CharaPtr m_sourceChara; Entity::CharaPtr m_sourceChara;
std::unordered_map< uint32_t, std::shared_ptr< std::vector< EffectResultPtr > > > m_resolvedEffects; std::unordered_map< uint32_t, std::vector< EffectResultPtr > > m_actorEffectsMap;
}; };
} }

View file

@ -65,11 +65,11 @@ void ItemAction::handleVFXItem()
effect.Type = Common::ActionEffectType::CALC_RESULT_TYPE_CHECK_BARRIER; effect.Type = Common::ActionEffectType::CALC_RESULT_TYPE_CHECK_BARRIER;
effect.Value = m_itemAction->data().Calcu0Arg[ 0 ]; effect.Value = m_itemAction->data().Calcu0Arg[ 0 ];
auto effectPacket = std::make_shared< EffectPacket >( getSourceChara()->getId(), getSourceChara()->getId(), getId() ); auto effectPacket = std::make_shared< EffectPacket >( getSourceChara()->getId(), getId() );
effectPacket->setTargetActor( getSourceChara()->getId() ); effectPacket->setTargetActor( getSourceChara()->getId() );
effectPacket->setAnimationId( Common::ItemActionType::ItemActionVFX ); effectPacket->setAnimationId( Common::ItemActionType::ItemActionVFX );
effectPacket->setDisplayType( Common::ActionEffectDisplayType::ShowItemName ); effectPacket->setDisplayType( Common::ActionEffectDisplayType::ShowItemName );
effectPacket->addEffect( effect, static_cast< uint64_t >( getSourceChara()->getId() ) ); effectPacket->addTargetEffect( effect, static_cast< uint64_t >( getSourceChara()->getId() ) );
m_pSource->sendToInRangeSet( effectPacket, true ); m_pSource->sendToInRangeSet( effectPacket, true );
} }

View file

@ -74,5 +74,5 @@ void MountAction::execute()
m_pSource->getAsPlayer()->unsetStateFlag( Common::PlayerStateFlag::Casting ); m_pSource->getAsPlayer()->unsetStateFlag( Common::PlayerStateFlag::Casting );
m_effectBuilder->mount( m_pSource, m_mountId ); m_effectBuilder->mount( m_pSource, m_mountId );
m_effectBuilder->buildAndSendPackets(); m_effectBuilder->buildAndSendPackets( { m_pSource } );
} }

View file

@ -16,7 +16,7 @@
#include "Network/PacketWrappers/ActorControlSelfPacket.h" #include "Network/PacketWrappers/ActorControlSelfPacket.h"
#include "Network/PacketWrappers/ActorControlTargetPacket.h" #include "Network/PacketWrappers/ActorControlTargetPacket.h"
#include "Network/PacketWrappers/UpdateHpMpTpPacket.h" #include "Network/PacketWrappers/UpdateHpMpTpPacket.h"
#include "Network/PacketWrappers/EffectPacket.h" #include "Network/PacketWrappers/EffectPacket1.h"
#include "StatusEffect/StatusEffect.h" #include "StatusEffect/StatusEffect.h"
#include "Action/Action.h" #include "Action/Action.h"
@ -483,7 +483,6 @@ Will have to be extended for ranged attacks.
*/ */
void Sapphire::Entity::Chara::autoAttack( CharaPtr pTarget ) void Sapphire::Entity::Chara::autoAttack( CharaPtr pTarget )
{ {
uint64_t tick = Util::getTimeMs(); uint64_t tick = Util::getTimeMs();
// todo: this needs to use the auto attack delay for the equipped weapon // todo: this needs to use the auto attack delay for the equipped weapon
@ -495,19 +494,19 @@ void Sapphire::Entity::Chara::autoAttack( CharaPtr pTarget )
auto damage = static_cast< uint16_t >( 10 + rand() % 12 ); auto damage = static_cast< uint16_t >( 10 + rand() % 12 );
auto effectPacket = std::make_shared< EffectPacket >( getId(), pTarget->getId(), 7 ); auto effectPacket = std::make_shared< EffectPacket1 >( getId(), pTarget->getId(), 7 );
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) ); effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
Common::CalcResultParam effectEntry{}; Common::CalcResultParam effectEntry{};
effectEntry.Value = static_cast< int16_t >( damage ); effectEntry.Value = static_cast< int16_t >( damage );
effectEntry.Type = ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP; effectEntry.Type = ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP;
effectEntry.Arg0 = static_cast< uint8_t >( ActionHitSeverityType::NormalDamage ); effectEntry.Arg0 = static_cast< uint8_t >( ActionHitSeverityType::NormalDamage );
effectEntry.Arg2 = 0x71; effectEntry.Arg2 = 0x71;
effectPacket->addEffect( effectEntry, static_cast< uint64_t >( pTarget->getId() ) ); effectPacket->addTargetEffect( effectEntry );
sendToInRangeSet( effectPacket ); sendToInRangeSet( effectPacket );
pTarget->takeDamage( damage ); pTarget->takeDamage( damage );
} }
} }

View file

@ -492,15 +492,16 @@ void Sapphire::World::Manager::DebugCommandMgr::add( char* data, Entity::Player&
uint16_t param1; uint16_t param1;
sscanf( params.c_str(), "%hu", &param1 ); sscanf( params.c_str(), "%hu", &param1 );
auto effectPacket = std::make_shared< EffectPacket >( player.getId(), player.getTargetId(), param1 ); auto effectPacket = std::make_shared< EffectPacket >( player.getId(), param1 );
effectPacket->setRotation( Common::Util::floatToUInt16Rot( player.getRot() ) ); effectPacket->setRotation( Common::Util::floatToUInt16Rot( player.getRot() ) );
effectPacket->setTargetActor( player.getTargetId() );
Common::CalcResultParam entry{}; Common::CalcResultParam entry{};
entry.Value = static_cast< int16_t >( param1 ); entry.Value = static_cast< int16_t >( param1 );
entry.Type = Common::ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP; entry.Type = Common::ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP;
entry.Arg0 = static_cast< uint8_t >( Common::ActionHitSeverityType::NormalDamage ); entry.Arg0 = static_cast< uint8_t >( Common::ActionHitSeverityType::NormalDamage );
effectPacket->addEffect( entry, static_cast< uint64_t >( player.getId() ) ); effectPacket->addTargetEffect( entry, static_cast< uint64_t >( player.getId() ) );
auto sequence = player.getCurrentTerritory()->getNextEffectSequence(); auto sequence = player.getCurrentTerritory()->getNextEffectSequence();
effectPacket->setSequence( sequence ); effectPacket->setSequence( sequence );

View file

@ -14,31 +14,51 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
class EffectPacket : public ZoneChannelPacket< FFXIVIpcActionResult > class EffectPacket : public ZoneChannelPacket< FFXIVIpcActionResult >
{ {
public: public:
EffectPacket( uint64_t sourceId, uint32_t targetId, uint32_t actionId ) : EffectPacket( uint64_t sourceId, uint32_t actionId ) :
ZoneChannelPacket< FFXIVIpcActionResult >( static_cast< uint32_t >( sourceId ), targetId ) ZoneChannelPacket< FFXIVIpcActionResult >( static_cast< uint32_t >( sourceId ) )
{ {
m_data.Flag = 0; m_data.Flag = 0;
m_data.ActionKey = actionId; m_data.ActionKey = actionId;
m_data.Action = static_cast< uint16_t >( actionId ); m_data.Action = static_cast< uint16_t >( actionId );
m_data.ActionKind = 1; m_data.ActionKind = 1;
m_data.LockTime = 0.6f; m_data.MainTarget = Common::INVALID_GAME_OBJECT_ID;
m_data.MainTarget = static_cast< uint64_t >( targetId ); m_data.BallistaEntityId = Common::INVALID_GAME_OBJECT_ID;
m_data.ActionArg = Common::ActionEffectDisplayType::ShowActionName; m_data.LockTime = 0.6f;
m_data.TargetCount = 0;
std::memset( m_data.CalcResult, 0, sizeof( Common::CalcResult ) * 16 ); std::memset( m_data.CalcResult, 0, sizeof( Common::CalcResult ) * 16 );
} }
void addEffect( const Common::CalcResultParam& effect, uint64_t targetId = Common::INVALID_GAME_OBJECT_ID64 ) void addTargetEffect( const Common::CalcResultParam& effect, uint64_t targetId = Common::INVALID_GAME_OBJECT_ID64 )
{ {
assert( m_data.TargetCount <= 15 ); std::memcpy( &m_data.CalcResult[ m_data.TargetCount ].CalcResultTg[ m_targetEffectCount++ ], &effect, sizeof( Common::CalcResultParam ) );
// iterate and see if we already have this target added
bool targetAlreadyAdded = false;
for( int i = 0; i < sizeof( m_data.Target ) / sizeof( uint64_t ); ++i )
{
if( m_data.Target[ i ] == targetId )
{
targetAlreadyAdded = true;
break;
}
}
std::memcpy( &m_data.CalcResult[ m_data.TargetCount ].CalcResultTg, &effect, sizeof( Common::CalcResultParam ) );
m_data.Target[ m_data.TargetCount ] = targetId; m_data.Target[ m_data.TargetCount ] = targetId;
if( !targetAlreadyAdded )
m_data.TargetCount++; m_data.TargetCount++;
} }
void addSourceEffect( const Common::CalcResultParam& effect )
{
// we associate the source effect with the current target index set
std::memcpy( &m_data.CalcResult[ m_data.TargetCount - 1 ].CalcResultCt[ m_sourceEffectCount++ ], &effect, sizeof( Common::CalcResultParam ) );
}
void setAnimationId( uint16_t animationId ) void setAnimationId( uint16_t animationId )
{ {
m_data.Action = animationId; m_data.Action = animationId;
@ -71,6 +91,9 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
m_data.RequestId = static_cast< uint32_t >( sourceSequence ); m_data.RequestId = static_cast< uint32_t >( sourceSequence );
m_data.ResultId = static_cast< uint32_t>( sequence ); m_data.ResultId = static_cast< uint32_t>( sequence );
} }
private:
uint8_t m_targetEffectCount{ 0 };
uint8_t m_sourceEffectCount{ 0 };
}; };
} }

View file

@ -12,9 +12,6 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
class EffectPacket1 : public ZoneChannelPacket< FFXIVIpcActionResult1 > class EffectPacket1 : public ZoneChannelPacket< FFXIVIpcActionResult1 >
{ {
private:
uint8_t m_targetEffectCount{0};
uint8_t m_sourceEffectCount{0};
public: public:
EffectPacket1( uint64_t sourceId, uint32_t targetId, uint32_t actionId ) : EffectPacket1( uint64_t sourceId, uint32_t targetId, uint32_t actionId ) :
ZoneChannelPacket< FFXIVIpcActionResult1 >( static_cast< uint32_t >( sourceId ), targetId ) ZoneChannelPacket< FFXIVIpcActionResult1 >( static_cast< uint32_t >( sourceId ), targetId )
@ -76,6 +73,10 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
m_data.RequestId = static_cast< uint32_t >( sourceSequence ); m_data.RequestId = static_cast< uint32_t >( sourceSequence );
m_data.ResultId = static_cast< uint32_t>( sequence ); m_data.ResultId = static_cast< uint32_t>( sequence );
} }
private:
uint8_t m_targetEffectCount{ 0 };
uint8_t m_sourceEffectCount{ 0 };
}; };
} }