diff --git a/src/common/Common.h b/src/common/Common.h index e86bed63..ed59e820 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -630,7 +630,7 @@ namespace Sapphire::Common * @param value The actionid that starts/continues the combo. eg, 3617 will start a spinning slash and/or syphon strike combo */ StartActionCombo = 28, - ComboVisualEffect = 29, + ComboSucceed = 29, Knockback = 33, Mount = 38, VFX = 59, // links to VFX sheet @@ -646,6 +646,12 @@ namespace Sapphire::Common CritDirectHitDamage = 3 }; + enum class ActionEffectResultFlag : uint8_t + { + None = 0, + EffectOnSource = 0x80, + }; + enum ItemActionType : uint16_t { ItemActionVFX = 852, diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index 668b3634..867ada28 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -1,4 +1,5 @@ #include "Action.h" +#include "EffectBuilder.h" #include @@ -463,38 +464,38 @@ void Action::Action::buildEffects() // when aoe, these effects are in the target whatever is hit first bool shouldRestoreMP = true; - bool shouldShowComboEffect = true; + bool shouldApplyComboSucceedEffect = true; for( auto& actor : m_hitActors ) { if( m_lutEntry.potency > 0 ) { auto dmg = calcDamage( isCorrectCombo() ? m_lutEntry.comboPotency : m_lutEntry.potency ); - m_effectBuilder->damageTarget( actor, dmg.first, dmg.second ); + m_effectBuilder->damage( actor, actor, dmg.first, dmg.second ); if( dmg.first > 0 ) actor->onActionHostile( m_pSource ); - if( isCorrectCombo() && shouldShowComboEffect ) + if( isCorrectCombo() && shouldApplyComboSucceedEffect ) { - m_effectBuilder->comboVisualEffect( actor ); - shouldShowComboEffect = false; + m_effectBuilder->comboSucceed( actor ); + shouldApplyComboSucceedEffect = false; } if( !isComboAction() || isCorrectCombo() ) { if( m_lutEntry.curePotency > 0 ) // actions with self heal { - m_effectBuilder->selfHeal( actor, m_pSource, m_lutEntry.curePotency ); + m_effectBuilder->heal( actor, m_pSource, m_lutEntry.curePotency, Common::ActionHitSeverityType::NormalHeal, Common::ActionEffectResultFlag::EffectOnSource ); } if( m_lutEntry.restoreMPPercentage > 0 && shouldRestoreMP ) { - m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.restoreMPPercentage / 100 ); + m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.restoreMPPercentage / 100, Common::ActionEffectResultFlag::EffectOnSource ); shouldRestoreMP = false; } - if( !m_actionData->preservesCombo ) // we need something like m_actionData->hasNextComboAction + if ( !m_actionData->preservesCombo ) // we need something like m_actionData->hasNextComboAction { m_effectBuilder->startCombo( actor, getId() ); // this is on all targets hit } @@ -503,18 +504,17 @@ void Action::Action::buildEffects() else if( m_lutEntry.curePotency > 0 ) { // todo: calcHealing() - m_effectBuilder->healTarget( actor, m_lutEntry.curePotency ); + m_effectBuilder->heal( actor, actor, m_lutEntry.curePotency ); if( m_lutEntry.restoreMPPercentage > 0 && shouldRestoreMP ) { - // always restore caster mp I don't think there are any actions that can restore target MP post 5.0 - m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.restoreMPPercentage / 100 ); + m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.restoreMPPercentage / 100, Common::ActionEffectResultFlag::EffectOnSource ); shouldRestoreMP = false; } } else if( m_lutEntry.restoreMPPercentage > 0 && shouldRestoreMP ) { - m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.restoreMPPercentage / 100 ); + m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.restoreMPPercentage / 100, Common::ActionEffectResultFlag::EffectOnSource ); shouldRestoreMP = false; } } @@ -755,13 +755,13 @@ bool Action::Action::preFilterActor( Sapphire::Entity::Actor& actor ) const if( kind != ObjKind::BattleNpc && kind != ObjKind::Player ) return false; - if( m_lutEntry.potency > 0 && chara == m_pSource ) + if( m_lutEntry.potency > 0 && chara->getId() == m_pSource->getId() ) { // damage action shouldn't hit self return false; } - if ( ( m_lutEntry.potency > 0 || m_lutEntry.curePotency > 0 ) && !chara->isAlive() ) + if( ( m_lutEntry.potency > 0 || m_lutEntry.curePotency > 0 ) && !chara->isAlive() ) { // can't deal damage or heal a dead entity return false; diff --git a/src/world/Action/EffectBuilder.cpp b/src/world/Action/EffectBuilder.cpp index 34eb0e6d..41612c79 100644 --- a/src/world/Action/EffectBuilder.cpp +++ b/src/world/Action/EffectBuilder.cpp @@ -47,63 +47,53 @@ std::shared_ptr< std::vector< EffectResultPtr > > EffectBuilder::getResultList( return it->second; } -void EffectBuilder::healTarget( Entity::CharaPtr& target, uint32_t amount, Common::ActionHitSeverityType severity ) +void EffectBuilder::heal( Entity::CharaPtr& effectTarget, Entity::CharaPtr& healingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag ) { - auto resultList = getResultList( target ); + auto resultList = getResultList( effectTarget ); assert( resultList ); - EffectResultPtr nextResult = make_EffectResult( target, getResultDelayMs() ); - nextResult->heal( amount, severity, false ); + EffectResultPtr nextResult = make_EffectResult( healingTarget, getResultDelayMs() ); + nextResult->heal( amount, severity, flag ); resultList->push_back( std::move( nextResult ) ); } -void EffectBuilder::selfHeal( Entity::CharaPtr& target, Entity::CharaPtr& source, uint32_t amount, Common::ActionHitSeverityType severity ) +void EffectBuilder::restoreMP( Entity::CharaPtr& target, Entity::CharaPtr& restoringTarget, uint32_t amount, Common::ActionEffectResultFlag flag ) { auto resultList = getResultList( target ); assert( resultList ); - EffectResultPtr nextResult = make_EffectResult( source, getResultDelayMs() ); // heal the source actor - nextResult->heal( amount, severity, true ); + EffectResultPtr nextResult = make_EffectResult( restoringTarget, getResultDelayMs() ); // restore mp source actor + nextResult->restoreMP( amount, flag ); resultList->push_back( std::move( nextResult ) ); } -void EffectBuilder::restoreMP( Entity::CharaPtr& target, Entity::CharaPtr& source, uint32_t amount ) +void EffectBuilder::damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag ) { - auto resultList = getResultList( target ); + auto resultList = getResultList( effectTarget ); assert( resultList ); - EffectResultPtr nextResult = make_EffectResult( source, getResultDelayMs() ); // restore mp source actor - nextResult->restoreMP( amount ); - resultList->push_back( std::move( nextResult ) ); -} - -void EffectBuilder::damageTarget( Entity::CharaPtr& target, uint32_t amount, Common::ActionHitSeverityType severity ) -{ - auto resultList = getResultList( target ); - assert( resultList ); - - EffectResultPtr nextResult = make_EffectResult( target, getResultDelayMs() ); - nextResult->damage( amount, severity ); + EffectResultPtr nextResult = make_EffectResult( damagingTarget, getResultDelayMs() ); + nextResult->damage( amount, severity, flag ); resultList->push_back( std::move( nextResult ) ); } void EffectBuilder::startCombo( Entity::CharaPtr& target, uint16_t actionId ) { auto resultList = getResultList( target ); - assert( resultList ); + assert( resultList ); EffectResultPtr nextResult = make_EffectResult( target, 0 ); nextResult->startCombo( actionId ); resultList->push_back( std::move( nextResult ) ); } -void EffectBuilder::comboVisualEffect( Entity::CharaPtr& target ) +void EffectBuilder::comboSucceed( Entity::CharaPtr& target ) { auto resultList = getResultList( target ); - assert( resultList ); + assert( resultList ); EffectResultPtr nextResult = make_EffectResult( target, 0 ); - nextResult->comboVisualEffect(); + nextResult->comboSucceed(); resultList->push_back( std::move( nextResult ) ); } @@ -125,7 +115,7 @@ void EffectBuilder::buildAndSendPackets() auto globalSequence = m_sourceChara->getCurrentTerritory()->getNextEffectSequence(); - while( m_resolvedEffects.size() > 0 ) + while( !m_resolvedEffects.empty() ) { auto packet = buildNextEffectPacket( globalSequence ); m_sourceChara->sendToInRangeSet( packet, true ); @@ -154,47 +144,46 @@ std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( uint32_ case 8: { auto p = makeZonePacket< Server::FFXIVIpcAoeEffect8 >( m_sourceChara->getId() ); - pHeader = ( EffectHeader* )( &( p->data() ) ); - pEntry = ( Common::EffectEntry* )( &( p->data().effects ) ); - pEffectTargetId = ( uint64_t* )( &( p->data().effectTargetId ) ); - pFlag = ( uint16_t* )( &( p->data().unkFlag ) ); + 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 ); effectPacket = std::move( p ); break; } case 16: { auto p = makeZonePacket< Server::FFXIVIpcAoeEffect16 >( m_sourceChara->getId() ); - pHeader = ( EffectHeader* )( &( p->data() ) ); - pEntry = ( Common::EffectEntry* )( &( p->data().effects ) ); - pEffectTargetId = ( uint64_t* )( &( p->data().effectTargetId ) ); - pFlag = ( uint16_t* )( &( p->data().unkFlag ) ); + 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 ); effectPacket = std::move( p ); break; } case 24: { auto p = makeZonePacket< Server::FFXIVIpcAoeEffect24 >( m_sourceChara->getId() ); - pHeader = ( EffectHeader* )( &( p->data() ) ); - pEntry = ( Common::EffectEntry* )( &( p->data().effects ) ); - pEffectTargetId = ( uint64_t* )( &( p->data().effectTargetId ) ); - pFlag = ( uint16_t* )( &( p->data().unkFlag ) ); + 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 ); effectPacket = std::move( p ); break; } case 32: { auto p = makeZonePacket< Server::FFXIVIpcAoeEffect32 >( m_sourceChara->getId() ); - pHeader = ( EffectHeader* )( &( p->data() ) ); - pEntry = ( Common::EffectEntry* )( &( p->data().effects ) ); - pEffectTargetId = ( uint64_t* )( &( p->data().effectTargetId ) ); - pFlag = ( uint16_t* )( &( p->data().unkFlag ) ); + 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 ); effectPacket = std::move( p ); break; } } - assert( effectPacket != nullptr ); + assert( effectPacket ); - pHeader->actionAnimationId = m_sourceChara->getId(); pHeader->actionId = m_actionId; pHeader->actionAnimationId = static_cast< uint16_t >( m_actionId ); pHeader->animationTargetId = m_sourceChara->getId(); @@ -209,7 +198,7 @@ std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( uint32_ for( auto it = m_resolvedEffects.begin(); it != m_resolvedEffects.end(); ) { auto resultList = it->second; - assert( resultList->size() > 0 ); + assert( !resultList->empty() ); auto firstResult = resultList->data()[ 0 ]; pEffectTargetId[ targetIndex ] = firstResult->getTarget()->getId(); Logger::debug( " - id: {}", pEffectTargetId[ targetIndex ] ); @@ -239,7 +228,7 @@ std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( uint32_ else { auto resultList = m_resolvedEffects.begin()->second; - assert( resultList->size() > 0 ); + assert( !resultList->empty() ); auto firstResult = resultList->data()[ 0 ]; Logger::debug( " - id: {}", firstResult->getTarget()->getId() ); diff --git a/src/world/Action/EffectBuilder.h b/src/world/Action/EffectBuilder.h index 69260e71..d787f044 100644 --- a/src/world/Action/EffectBuilder.h +++ b/src/world/Action/EffectBuilder.h @@ -11,21 +11,20 @@ namespace Sapphire::World::Action public: EffectBuilder( Entity::CharaPtr source, uint32_t actionId, uint16_t sequence ); + void heal( Entity::CharaPtr& effectTarget, Entity::CharaPtr& healingTarget, uint32_t amount, + Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalHeal, + Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None); - void healTarget( Entity::CharaPtr& target, uint32_t amount, - Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalHeal ); + void restoreMP( Entity::CharaPtr& effectTarget, Entity::CharaPtr& restoringTarget, uint32_t amount, + Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None); - void selfHeal( Entity::CharaPtr& target, Entity::CharaPtr& source, uint32_t amount, - Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalHeal ); - - void restoreMP( Entity::CharaPtr& target, Entity::CharaPtr& source, uint32_t amount ); - - void damageTarget( Entity::CharaPtr& target, uint32_t amount, - Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalDamage ); + void damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, + Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalDamage, + Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None); void startCombo( Entity::CharaPtr& target, uint16_t actionId ); - void comboVisualEffect( Entity::CharaPtr& target ); + void comboSucceed( Entity::CharaPtr& target ); void applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param ); diff --git a/src/world/Action/EffectResult.cpp b/src/world/Action/EffectResult.cpp index fda9a0e9..9525a361 100644 --- a/src/world/Action/EffectResult.cpp +++ b/src/world/Action/EffectResult.cpp @@ -15,7 +15,7 @@ EffectResult::EffectResult( Entity::CharaPtr target, uint64_t runAfter ) : m_severity( Common::ActionHitSeverityType::NormalDamage ), m_type( Common::ActionEffectType::Nothing ), m_param( 0 ), - m_flag( 0 ) + m_flag( Common::ActionEffectResultFlag::None ) { } @@ -35,27 +35,28 @@ uint64_t EffectResult::getDelay() return m_delayMs; } -void EffectResult::damage( uint32_t amount, Common::ActionHitSeverityType severity ) +void EffectResult::damage( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag ) { m_severity = severity; m_value = amount; + m_flag = flag; m_type = Common::ActionEffectType::Damage; } -void EffectResult::heal( uint32_t amount, Sapphire::Common::ActionHitSeverityType severity, bool isSelfHeal ) +void EffectResult::heal( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag ) { m_severity = severity; m_value = amount; - m_flag = isSelfHeal ? 0x80 : 0; // flag == 0x80 displays healing text at source actor + m_flag = flag; m_type = Common::ActionEffectType::Heal; } -void EffectResult::restoreMP( uint32_t amount ) +void EffectResult::restoreMP( uint32_t amount, Common::ActionEffectResultFlag flag ) { m_value = amount; - m_flag = 0x80; + m_flag = flag; m_type = Common::ActionEffectType::MpGain; } @@ -63,14 +64,15 @@ void EffectResult::restoreMP( uint32_t amount ) void EffectResult::startCombo( uint16_t actionId ) { m_value = actionId; - m_flag = 0x80; + m_flag = Common::ActionEffectResultFlag::EffectOnSource; m_type = Common::ActionEffectType::StartActionCombo; } -void EffectResult::comboVisualEffect() +void EffectResult::comboSucceed() { - m_type = Common::ActionEffectType::ComboVisualEffect; + // no EffectOnSource flag on this + m_type = Common::ActionEffectType::ComboSucceed; } void EffectResult::applyStatusEffect( uint16_t statusId, uint8_t param ) @@ -90,7 +92,7 @@ Common::EffectEntry EffectResult::buildEffectEntry() const entry.hitSeverity = m_severity; entry.effectType = m_type; entry.param = m_param; - entry.flags = m_flag; + entry.flags = static_cast< uint8_t >( m_flag ); return entry; } diff --git a/src/world/Action/EffectResult.h b/src/world/Action/EffectResult.h index 149d2860..ebb617c2 100644 --- a/src/world/Action/EffectResult.h +++ b/src/world/Action/EffectResult.h @@ -15,11 +15,11 @@ namespace Sapphire::World::Action public: explicit EffectResult( Entity::CharaPtr target, uint64_t delayMs ); - void damage( uint32_t amount, Common::ActionHitSeverityType severity ); - void heal( uint32_t amount, Common::ActionHitSeverityType severity, bool isSelfHeal ); - void restoreMP( uint32_t amount ); + void damage( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); + void heal( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); + void restoreMP( uint32_t amount, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); void startCombo( uint16_t actionId ); - void comboVisualEffect(); + void comboSucceed(); void applyStatusEffect( uint16_t statusId, uint8_t param ); Entity::CharaPtr getTarget() const; @@ -42,7 +42,7 @@ namespace Sapphire::World::Action uint32_t m_value; uint8_t m_param; - uint8_t m_flag; + Common::ActionEffectResultFlag m_flag; }; } diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index f7c5aaaf..797d9edd 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -2152,8 +2152,7 @@ bool Sapphire::Entity::Player::hasQueuedAction() const void Sapphire::Entity::Player::setQueuedAction( Sapphire::World::Action::ActionPtr pAction ) { - m_pQueuedAction = nullptr; // overwrite whatever is already there - m_pQueuedAction = std::move( pAction ); + m_pQueuedAction = std::move( pAction ); // overwrite previous queued action if any } bool Sapphire::Entity::Player::checkAction() @@ -2183,4 +2182,4 @@ bool Sapphire::Entity::Player::checkAction() } return true; -} \ No newline at end of file +}