From bb4aab0acc46180aacc31b21181c4fa07b40e2de Mon Sep 17 00:00:00 2001 From: collett Date: Tue, 14 Jan 2020 22:34:19 +0900 Subject: [PATCH 1/3] let caller decide effect delay time --- src/world/Action/Action.cpp | 4 ++-- src/world/Action/EffectBuilder.cpp | 27 ++++++++++----------------- src/world/Action/EffectBuilder.h | 14 ++++++-------- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index 32d52a85..530af0cc 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -541,14 +541,14 @@ void Action::Action::buildEffects() if( m_lutEntry.targetStatus != 0 ) { if( !isComboAction() || isCorrectCombo() ) - m_effectBuilder->applyStatusEffect( actor, m_pSource, m_lutEntry.targetStatus, m_lutEntry.targetStatusDuration, m_lutEntry.targetStatusParam ); + m_effectBuilder->applyStatusEffect( actor, m_pSource, m_lutEntry.targetStatus, m_lutEntry.targetStatusDuration, m_lutEntry.targetStatusParam, 500 ); } } if( m_lutEntry.selfStatus != 0 ) { if( !isComboAction() || isCorrectCombo() ) - m_effectBuilder->applyStatusEffect( m_pSource, m_pSource, m_lutEntry.selfStatus, m_lutEntry.selfStatusDuration, m_lutEntry.selfStatusParam ); + m_effectBuilder->applyStatusEffect( m_pSource, m_pSource, m_lutEntry.selfStatus, m_lutEntry.selfStatusDuration, m_lutEntry.selfStatusParam, 500 ); } m_effectBuilder->buildAndSendPackets( getAnimationLock() ); diff --git a/src/world/Action/EffectBuilder.cpp b/src/world/Action/EffectBuilder.cpp index 81dc218b..35eea3d1 100644 --- a/src/world/Action/EffectBuilder.cpp +++ b/src/world/Action/EffectBuilder.cpp @@ -24,13 +24,6 @@ EffectBuilder::EffectBuilder( Entity::CharaPtr source, uint32_t actionId, uint16 } -uint64_t EffectBuilder::getResultDelayMs() -{ - // todo: actually figure this retarded shit out - - return Common::Util::getTimeMs() + 600; -} - void EffectBuilder::moveToResultList( Entity::CharaPtr& chara, EffectResultPtr result ) { auto it = m_resolvedEffects.find( chara->getId() ); @@ -49,23 +42,23 @@ void EffectBuilder::moveToResultList( Entity::CharaPtr& chara, EffectResultPtr r 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, uint64_t resultDelayMs ) { - EffectResultPtr nextResult = make_EffectResult( healingTarget, nullptr, getResultDelayMs() ); + EffectResultPtr nextResult = make_EffectResult( healingTarget, nullptr, Common::Util::getTimeMs() + resultDelayMs ); nextResult->heal( amount, severity, flag ); moveToResultList( 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, uint64_t resultDelayMs ) { - EffectResultPtr nextResult = make_EffectResult( restoringTarget, nullptr, getResultDelayMs() ); // restore mp source actor + EffectResultPtr nextResult = make_EffectResult( restoringTarget, nullptr, Common::Util::getTimeMs() + resultDelayMs ); nextResult->restoreMP( amount, flag ); moveToResultList( 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, uint64_t resultDelayMs ) { - EffectResultPtr nextResult = make_EffectResult( damagingTarget, nullptr, getResultDelayMs() ); + EffectResultPtr nextResult = make_EffectResult( damagingTarget, nullptr, Common::Util::getTimeMs() + resultDelayMs ); nextResult->damage( amount, severity, flag ); moveToResultList( effectTarget, nextResult ); } @@ -84,16 +77,16 @@ void EffectBuilder::comboSucceed( Entity::CharaPtr& target ) moveToResultList( target, nextResult ); } -void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, uint16_t statusId, uint32_t duration, uint8_t param ) +void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, uint16_t statusId, uint32_t duration, uint8_t param, uint64_t resultDelayMs ) { - EffectResultPtr nextResult = make_EffectResult( target, source, getResultDelayMs() ); + EffectResultPtr nextResult = make_EffectResult( target, source, Common::Util::getTimeMs() + resultDelayMs ); nextResult->applyStatusEffect( statusId, duration, param ); moveToResultList( target, nextResult ); } -void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, StatusEffect::StatusEffectPtr pStatusEffect ) +void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, StatusEffect::StatusEffectPtr pStatusEffect, uint64_t resultDelayMs ) { - EffectResultPtr nextResult = make_EffectResult( target, source, getResultDelayMs() ); + EffectResultPtr nextResult = make_EffectResult( target, source, Common::Util::getTimeMs() + resultDelayMs ); nextResult->applyStatusEffect( pStatusEffect ); moveToResultList( target, nextResult ); } diff --git a/src/world/Action/EffectBuilder.h b/src/world/Action/EffectBuilder.h index c376756f..aa0e0c41 100644 --- a/src/world/Action/EffectBuilder.h +++ b/src/world/Action/EffectBuilder.h @@ -13,21 +13,21 @@ namespace Sapphire::World::Action void heal( Entity::CharaPtr& effectTarget, Entity::CharaPtr& healingTarget, uint32_t amount, Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalHeal, - Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None); + Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None, uint64_t resultDelayMs = 600 ); void restoreMP( Entity::CharaPtr& effectTarget, Entity::CharaPtr& restoringTarget, uint32_t amount, - Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None); + Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None, uint64_t resultDelayMs = 600 ); void damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalDamage, - Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None); - + Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None, uint64_t resultDelayMs = 600 ); + void startCombo( Entity::CharaPtr& target, uint16_t actionId ); void comboSucceed( Entity::CharaPtr& target ); - void applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, uint16_t statusId, uint32_t duration, uint8_t param ); - void applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, StatusEffect::StatusEffectPtr pStatusEffect ); + void applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, uint16_t statusId, uint32_t duration, uint8_t param, uint64_t resultDelayMs = 600 ); + void applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, StatusEffect::StatusEffectPtr pStatusEffect, uint64_t resultDelayMs = 600 ); void statusNoEffect( Entity::CharaPtr& target, uint16_t statusId ); @@ -36,8 +36,6 @@ namespace Sapphire::World::Action private: void moveToResultList( Entity::CharaPtr& chara, EffectResultPtr result ); - uint64_t getResultDelayMs(); - std::shared_ptr< Sapphire::Network::Packets::FFXIVPacketBase > buildNextEffectPacket( uint32_t globalSequence, float animationLock ); private: From a8242fcf87d848f7388dba96d13f8618902f20cd Mon Sep 17 00:00:00 2001 From: collett Date: Tue, 14 Jan 2020 23:24:06 +0900 Subject: [PATCH 2/3] Implement swiftcast. --- src/common/Common.h | 1 + src/world/Action/ActionLutData.cpp | 3 ++ src/world/Actor/Chara.cpp | 2 +- src/world/Manager/ActionMgr.cpp | 7 ++++ src/world/StatusEffect/StatusEffect.cpp | 45 ++++++++++++++++++++++++- src/world/StatusEffect/StatusEffect.h | 5 +++ 6 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/common/Common.h b/src/common/Common.h index e258b3aa..0135c030 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -1039,6 +1039,7 @@ namespace Sapphire::Common Shield = 10, MPRestore = 11, Haste = 12, + InstantCast = 13, }; enum class ActionTypeFilter : int32_t diff --git a/src/world/Action/ActionLutData.cpp b/src/world/Action/ActionLutData.cpp index 4b44b5e3..96313c15 100644 --- a/src/world/Action/ActionLutData.cpp +++ b/src/world/Action/ActionLutData.cpp @@ -3511,4 +3511,7 @@ ActionLut::StatusEffectTable ActionLut::m_statusEffectTable = //Presence of Mind, 神速魔: Haste, 20% { 157, { 12, 20, 0, 0, 0 } }, + //Swiftcast, 迅速魔: InstantCast, 1 casts + { 167, { 13, 1, 0, 0, 0 } }, + }; diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index da3bff35..6bd8c039 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -722,7 +722,7 @@ void Sapphire::Entity::Chara::updateStatusEffects() uint32_t duration = effect->getDuration(); uint32_t tickRate = effect->getTickRate(); - if( duration > 0 && ( currentTimeMs - startTime ) > duration ) + if( effect->isMarkedToRemove() || ( duration > 0 && ( currentTimeMs - startTime ) > duration ) ) { // remove status effect removeStatusEffect( effectIndex, true, true ); diff --git a/src/world/Manager/ActionMgr.cpp b/src/world/Manager/ActionMgr.cpp index 2356d7b3..f5a7303e 100644 --- a/src/world/Manager/ActionMgr.cpp +++ b/src/world/Manager/ActionMgr.cpp @@ -5,6 +5,8 @@ #include "Script/ScriptMgr.h" #include "Actor/Player.h" +#include "StatusEffect/StatusEffect.h" + #include #include "Framework.h" @@ -89,6 +91,11 @@ void World::Manager::ActionMgr::bootstrapAction( Entity::Player& player, return; } + for( const auto& statusIt : player.getStatusEffectMap() ) + { + statusIt.second->onBeforeActionStart( currentAction ); + } + if( player.getCurrentAction() ) { player.sendDebug( "Skill queued: {0}", currentAction->getId() ); diff --git a/src/world/StatusEffect/StatusEffect.cpp b/src/world/StatusEffect/StatusEffect.cpp index 30ae2125..3392c331 100644 --- a/src/world/StatusEffect/StatusEffect.cpp +++ b/src/world/StatusEffect/StatusEffect.cpp @@ -9,6 +9,8 @@ #include "Actor/Chara.h" #include "Actor/Actor.h" +#include "Action/Action.h" + #include "Script/ScriptMgr.h" #include "Math/CalcStats.h" @@ -32,7 +34,8 @@ Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPt m_pFw( pFw ), m_value( 0 ), m_cachedSourceCrit( 0 ), - m_cachedSourceCritBonus( 0 ) + m_cachedSourceCritBonus( 0 ), + m_markToRemove( false ) { auto pExdData = m_pFw->get< Data::ExdDataGenerated >(); auto entry = pExdData->get< Sapphire::Data::Status >( id ); @@ -262,4 +265,44 @@ const Sapphire::World::Action::StatusEffectEntry& Sapphire::StatusEffect::Status void Sapphire::StatusEffect::StatusEffect::replaceEffectEntry( Sapphire::World::Action::StatusEffectEntry entryOverride ) { m_effectEntry = entryOverride; +} + +void Sapphire::StatusEffect::StatusEffect::onBeforeActionStart( Sapphire::World::Action::ActionPtr action ) +{ + // todo: add script function for this if needed + //auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >(); + //pScriptMgr->onBeforeActionStart( m_targetActor, *this ); + + switch( static_cast< Common::StatusEffectType >( m_effectEntry.effectType ) ) + { + case Common::StatusEffectType::InstantCast: + { + if( !action->hasCastTime() ) + return; + // value1: remaining uses + // value2-4: affected action ids, or all actions if value2 is 0 + if( m_effectEntry.effectValue2 != 0 ) + { + if( action->getId() != m_effectEntry.effectValue2 && + action->getId() != m_effectEntry.effectValue3 && + action->getId() != m_effectEntry.effectValue4 ) + return; + } + if( m_effectEntry.effectValue1 > 0 ) + { + m_effectEntry.effectValue1--; + if( m_effectEntry.effectValue1 == 0 ) + { + m_markToRemove = true; + } + action->setCastTime( 0 ); + } + break; + } + } +} + +bool Sapphire::StatusEffect::StatusEffect::isMarkedToRemove() +{ + return m_markToRemove; } \ No newline at end of file diff --git a/src/world/StatusEffect/StatusEffect.h b/src/world/StatusEffect/StatusEffect.h index 70a9cd0d..a297094e 100644 --- a/src/world/StatusEffect/StatusEffect.h +++ b/src/world/StatusEffect/StatusEffect.h @@ -19,6 +19,8 @@ public: void onTick(); + void onBeforeActionStart( World::Action::ActionPtr action ); + void applyStatus(); void removeStatus(); @@ -53,6 +55,8 @@ public: void replaceEffectEntry( Sapphire::World::Action::StatusEffectEntry entryOverride ); + bool isMarkedToRemove(); + private: uint32_t m_id; Entity::CharaPtr m_sourceActor; @@ -69,6 +73,7 @@ private: uint32_t m_value; float m_cachedSourceCrit; float m_cachedSourceCritBonus; + bool m_markToRemove; }; } From e677ee5ef8c00b01c3b8ad65c40271437237b3e1 Mon Sep 17 00:00:00 2001 From: collett Date: Tue, 14 Jan 2020 23:41:31 +0900 Subject: [PATCH 3/3] Dots and hots should tick together one total number per tick. --- src/world/Actor/BNpc.cpp | 1 + src/world/Actor/Chara.cpp | 76 +++++++++++++++++---------------- src/world/Actor/Chara.h | 2 +- src/world/Actor/PlayerEvent.cpp | 2 +- 4 files changed, 42 insertions(+), 39 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 54c74953..0a6c5fbe 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -396,6 +396,7 @@ void Sapphire::Entity::BNpc::deaggro( Sapphire::Entity::CharaPtr pChara ) void Sapphire::Entity::BNpc::onTick() { + Chara::onTick(); if( m_state == BNpcState::Retreat ) { regainHp(); diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index 6bd8c039..f3cbd2e7 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -709,9 +709,6 @@ void Sapphire::Entity::Chara::updateStatusEffects() { uint64_t currentTimeMs = Util::getTimeMs(); - uint32_t thisTickDmg = 0; - uint32_t thisTickHeal = 0; - for( auto effectIt : m_statusEffectMap ) { uint8_t effectIndex = effectIt.first; @@ -734,41 +731,7 @@ void Sapphire::Entity::Chara::updateStatusEffects() { effect->setLastTick( currentTimeMs ); effect->onTick(); - - auto thisEffect = effect->getTickEffect(); - - switch( thisEffect.first ) - { - - case 1: - { - thisTickDmg += thisEffect.second; - break; - } - - case 2: - { - thisTickHeal += thisEffect.second; - break; - } - - } } - - } - - if( thisTickDmg != 0 ) - { - takeDamage( thisTickDmg ); - sendToInRangeSet( makeActorControl( getId(), HPFloatingText, 0, - static_cast< uint8_t >( ActionEffectType::Damage ), thisTickDmg ), true ); - } - - if( thisTickHeal != 0 ) - { - heal( thisTickHeal ); - sendToInRangeSet( makeActorControl( getId(), HPFloatingText, 0, - static_cast< uint8_t >( ActionEffectType::Heal ), thisTickHeal ), true ); } } @@ -1035,4 +998,43 @@ float Sapphire::Entity::Chara::applyShieldProtection( float damage ) sendEffectResultToUpdateShieldValue(); // yes this is the packet to update shield value } return remainingDamage; +} + +void Sapphire::Entity::Chara::onTick() +{ + uint32_t thisTickDmg = 0; + uint32_t thisTickHeal = 0; + + for( auto effectIt : m_statusEffectMap ) + { + auto thisEffect = effectIt.second->getTickEffect(); + switch( thisEffect.first ) + { + case 1: + { + thisTickDmg += thisEffect.second; + break; + } + + case 2: + { + thisTickHeal += thisEffect.second; + break; + } + } + } + + if( thisTickDmg != 0 ) + { + takeDamage( thisTickDmg ); + sendToInRangeSet( makeActorControl( getId(), HPFloatingText, 0, + static_cast< uint8_t >( ActionEffectType::Damage ), thisTickDmg ), true ); + } + + if( thisTickHeal != 0 ) + { + heal( thisTickHeal ); + sendToInRangeSet( makeActorControl( getId(), HPFloatingText, 0, + static_cast< uint8_t >( ActionEffectType::Heal ), thisTickHeal ), true ); + } } \ No newline at end of file diff --git a/src/world/Actor/Chara.h b/src/world/Actor/Chara.h index fa6c3247..fb0ba97c 100644 --- a/src/world/Actor/Chara.h +++ b/src/world/Actor/Chara.h @@ -252,7 +252,7 @@ namespace Sapphire::Entity virtual void onActionFriendly( Chara& pSource ) {}; - virtual void onTick() {}; + virtual void onTick(); virtual void changeTarget( uint64_t targetId ); diff --git a/src/world/Actor/PlayerEvent.cpp b/src/world/Actor/PlayerEvent.cpp index 0303b4fb..08f830e4 100644 --- a/src/world/Actor/PlayerEvent.cpp +++ b/src/world/Actor/PlayerEvent.cpp @@ -370,7 +370,7 @@ void Sapphire::Entity::Player::onDeath() // TODO: slightly ugly here and way too static. Needs too be done properly void Sapphire::Entity::Player::onTick() { - + Chara::onTick(); // add 3 seconds to total play time m_playTime += 3;