diff --git a/src/scripts/action/war/ActionInnerBeast.cpp b/src/scripts/action/war/ActionInnerBeast.cpp index f53ba491..afd5e726 100644 --- a/src/scripts/action/war/ActionInnerBeast.cpp +++ b/src/scripts/action/war/ActionInnerBeast.cpp @@ -3,6 +3,7 @@ #include #include #include +#include using namespace Sapphire; using namespace Sapphire::World::Action; @@ -25,8 +26,8 @@ public: if( !pPlayer ) return; - if( !pPlayer->hasStatusEffect( Unchained ) ) - pPlayer->delModifier( Common::ParamModifier::DamageDealtPercent, -25 ); + if( auto status = pPlayer->getStatusEffectById( Defiance ); status ) + status->setModifier( Common::ParamModifier::DamageDealtPercent, 0 ); auto dmg = action.calcDamage( Potency ); action.getEffectbuilder()->damage( pSource, pTarget, dmg.first, dmg.second ); @@ -38,7 +39,10 @@ public: { StatusModifier{ Common::ParamModifier::DamageTakenPercent, -20 } } ); if( !pPlayer->hasStatusEffect( Unchained ) ) - pPlayer->addModifier( Common::ParamModifier::DamageDealtPercent, -25 ); + { + if( auto status = pPlayer->getStatusEffectById( Defiance ); status ) + status->setModifier( Common::ParamModifier::DamageDealtPercent, -25 ); + } } }; diff --git a/src/scripts/action/war/ActionUnchained.cpp b/src/scripts/action/war/ActionUnchained.cpp index 482e9249..3025ce20 100644 --- a/src/scripts/action/war/ActionUnchained.cpp +++ b/src/scripts/action/war/ActionUnchained.cpp @@ -3,6 +3,7 @@ #include #include #include +#include using namespace Sapphire; using namespace Sapphire::World::Action; @@ -21,7 +22,8 @@ public: if( !pPlayer ) return; - pPlayer->delModifier( Common::ParamModifier::DamageDealtPercent, -25 ); + if( auto status = pPlayer->getStatusEffectById( Defiance ); status ) + status->setModifier( Common::ParamModifier::DamageDealtPercent, 0 ); action.applyStatusEffectSelf( Unchained ); pPlayer->addStatusEffectByIdIfNotExist( Unchained, 20000, *pPlayer->getAsChara() ); diff --git a/src/scripts/statuseffect/StatusEffectUnchained.cpp b/src/scripts/statuseffect/StatusEffectUnchained.cpp index 19aecdef..3a5f991e 100644 --- a/src/scripts/statuseffect/StatusEffectUnchained.cpp +++ b/src/scripts/statuseffect/StatusEffectUnchained.cpp @@ -2,6 +2,7 @@ #include #include #include +#include using namespace Sapphire; using namespace Sapphire::World::Action; @@ -15,8 +16,8 @@ public: void onExpire( Entity::Chara& actor ) override { - if( actor.hasStatusEffect( Defiance ) ) - actor.addModifier( Common::ParamModifier::DamageDealtPercent, -25 ); + if( auto status = actor.getStatusEffectById( Defiance ); status ) + status->setModifier( Common::ParamModifier::DamageDealtPercent, -25 ); } }; diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index 913f0df2..16d611b2 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -643,6 +643,17 @@ std::map< uint8_t, Sapphire::StatusEffect::StatusEffectPtr > Sapphire::Entity::C return m_statusEffectMap; } +Sapphire::StatusEffect::StatusEffectPtr Sapphire::Entity::Chara::getStatusEffectById( uint32_t id ) const +{ + for( const auto& effectIt : m_statusEffectMap ) + { + if( effectIt.second->getId() == id ) + return effectIt.second; + } + + return nullptr; +} + const uint8_t* Sapphire::Entity::Chara::getLookArray() const { return m_customize; @@ -815,45 +826,23 @@ void Sapphire::Entity::Chara::setStatValue( Common::BaseParam baseParam, uint32_ float Sapphire::Entity::Chara::getModifier( Common::ParamModifier paramModifier ) const { - if( m_modifiers.find( paramModifier ) == m_modifiers.end() ) - return paramModifier >= Common::ParamModifier::StrengthPercent ? 1.0f : 0; + auto result = paramModifier >= Common::ParamModifier::StrengthPercent ? 1.0f : 0; - auto& mod = m_modifiers.at( paramModifier ); - if( paramModifier >= Common::ParamModifier::StrengthPercent ) + for( const auto& [ key, status ] : m_statusEffectMap ) { - auto valPercent = 1.0f; - for( const auto val : mod ) - valPercent *= 1.0f + ( val / 100.0f ); - return valPercent; + for( const auto& [ mod, val ] : status->getModifiers() ) + { + if( mod != paramModifier ) + continue; + + if( paramModifier >= Common::ParamModifier::StrengthPercent ) + result *= 1.0f + ( val / 100.0f ); + else + result += val; + } } - else - { - return std::accumulate( mod.begin(), mod.end(), 0 ); - } -} -void Sapphire::Entity::Chara::addModifier( Common::ParamModifier paramModifier, int32_t value ) -{ - m_modifiers[ paramModifier ].push_back( value ); - - if( auto pPlayer = this->getAsPlayer(); pPlayer ) - Common::Service< World::Manager::PlayerMgr >::ref().sendDebug( *pPlayer, "Modifier: {}, value: {}", static_cast< int32_t >( paramModifier ), getModifier( paramModifier ) ); -} - -void Sapphire::Entity::Chara::delModifier( Common::ParamModifier paramModifier, int32_t value ) -{ - if( m_modifiers.find( paramModifier ) == m_modifiers.end() ) - return; - - auto& mod = m_modifiers.at( paramModifier ); - - mod.erase( std::remove( mod.begin(), mod.end(), value ), mod.end() ); - - if( mod.size() == 0 ) - m_modifiers.erase( paramModifier ); - - if( auto pPlayer = this->getAsPlayer(); pPlayer ) - Common::Service< World::Manager::PlayerMgr >::ref().sendDebug( *pPlayer, "Modifier: {}, value: {}", static_cast< int32_t >( paramModifier ), getModifier( paramModifier ) ); + return result; } void Sapphire::Entity::Chara::onTick() diff --git a/src/world/Actor/Chara.h b/src/world/Actor/Chara.h index 089313ae..df81d626 100644 --- a/src/world/Actor/Chara.h +++ b/src/world/Actor/Chara.h @@ -28,13 +28,10 @@ namespace Sapphire::Entity public: using ActorStatsArray = std::array< uint32_t, STAT_ARRAY_SIZE >; - using ActorModifiersMap = std::unordered_map< Common::ParamModifier, std::vector< int32_t > >; ActorStatsArray m_baseStats{ 0 }; ActorStatsArray m_bonusStats{ 0 }; - ActorModifiersMap m_modifiers{ 0 }; - protected: char m_name[34]; /*! Last tick time for the actor ( in ms ) */ @@ -131,6 +128,8 @@ namespace Sapphire::Entity std::map< uint8_t, Sapphire::StatusEffect::StatusEffectPtr > getStatusEffectMap() const; + Sapphire::StatusEffect::StatusEffectPtr getStatusEffectById( uint32_t id ) const; + void sendStatusEffectUpdate(); /*! return a const pointer to the look array */ @@ -169,10 +168,6 @@ namespace Sapphire::Entity float getModifier( Common::ParamModifier paramModifier ) const; - void addModifier( Common::ParamModifier paramModifier, int32_t value ); - - void delModifier( Common::ParamModifier paramModifier, int32_t value ); - uint32_t getHp() const; uint32_t getHpPercent() const; diff --git a/src/world/StatusEffect/StatusEffect.cpp b/src/world/StatusEffect/StatusEffect.cpp index b31a0829..f0598fb4 100644 --- a/src/world/StatusEffect/StatusEffect.cpp +++ b/src/world/StatusEffect/StatusEffect.cpp @@ -6,13 +6,17 @@ #include #include +#include "Manager/PlayerMgr.h" + #include "Actor/Chara.h" +#include "Actor/Player.h" #include "Actor/GameObject.h" #include "Script/ScriptMgr.h" #include "StatusEffect.h" +using namespace Sapphire; using namespace Sapphire::Common; using namespace Sapphire::Network::Packets; //using namespace Sapphire::Network::Packets::WorldPackets::Server; @@ -21,7 +25,7 @@ Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPt uint32_t duration, std::vector< World::Action::StatusModifier >& modifiers, uint32_t tickRate ) : StatusEffect( id, sourceActor, targetActor, duration, tickRate ) { - m_modifiers = std::move( modifiers ); + setModifiers( modifiers ); } Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor, @@ -88,21 +92,49 @@ uint16_t Sapphire::StatusEffect::StatusEffect::getParam() const return m_param; } -void Sapphire::StatusEffect::StatusEffect::applyStatus() +std::unordered_map< Common::ParamModifier, int32_t >& Sapphire::StatusEffect::StatusEffect::getModifiers() { - m_startTime = Util::getTimeMs(); - auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); + return m_modifiers; +} - for( const auto& mod : m_modifiers ) +void Sapphire::StatusEffect::StatusEffect::setModifiers( std::vector< World::Action::StatusModifier > modifiers ) +{ + for( const auto& mod : modifiers ) { - // TODO: ticks if( mod.modifier != Common::ParamModifier::TickDamage && mod.modifier != Common::ParamModifier::TickHeal ) - m_targetActor->addModifier( mod.modifier, mod.value ); + setModifier( mod.modifier, mod.value ); else if( mod.modifier == Common::ParamModifier::TickDamage ) registerTickEffect( mod.modifier, mod.value ); else if( mod.modifier == Common::ParamModifier::TickHeal ) registerTickEffect( mod.modifier, mod.value ); } +} + +void Sapphire::StatusEffect::StatusEffect::setModifier( Common::ParamModifier paramModifier, int32_t value ) +{ + m_modifiers[ paramModifier ] = value; + + if( auto pPlayer = m_targetActor->getAsPlayer(); pPlayer ) + Common::Service< World::Manager::PlayerMgr >::ref().sendDebug( *pPlayer, "Modifier: {}, value: {}", static_cast< int32_t >( paramModifier ), + pPlayer->getModifier( paramModifier ) ); +} + +void Sapphire::StatusEffect::StatusEffect::delModifier( Common::ParamModifier paramModifier ) +{ + if( m_modifiers.find( paramModifier ) == m_modifiers.end() ) + return; + + m_modifiers.erase( paramModifier ); + + if( auto pPlayer = m_targetActor->getAsPlayer(); pPlayer ) + Common::Service< World::Manager::PlayerMgr >::ref().sendDebug( *pPlayer, "Modifier: {}, value: {}", static_cast< int32_t >( paramModifier ), + pPlayer->getModifier( paramModifier ) ); +} + +void Sapphire::StatusEffect::StatusEffect::applyStatus() +{ + m_startTime = Util::getTimeMs(); + auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); m_targetActor->calculateStats(); @@ -131,11 +163,7 @@ void Sapphire::StatusEffect::StatusEffect::removeStatus() { auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); - for( const auto& mod : m_modifiers ) - { - if( mod.modifier != Common::ParamModifier::TickDamage && mod.modifier != Common::ParamModifier::TickHeal ) - m_targetActor->delModifier( mod.modifier, mod.value ); - } + m_modifiers.clear(); m_targetActor->calculateStats(); diff --git a/src/world/StatusEffect/StatusEffect.h b/src/world/StatusEffect/StatusEffect.h index f18ecbcf..80680efd 100644 --- a/src/world/StatusEffect/StatusEffect.h +++ b/src/world/StatusEffect/StatusEffect.h @@ -21,6 +21,14 @@ public: void onTick(); + std::unordered_map< Common::ParamModifier, int32_t >& getModifiers(); + + void setModifiers( std::vector< World::Action::StatusModifier > modifiers ); + + void setModifier( Common::ParamModifier paramModifier, int32_t value ); + + void delModifier( Common::ParamModifier paramModifier ); + void applyStatus(); void removeStatus(); @@ -62,7 +70,7 @@ private: uint16_t m_param; std::string m_name; std::pair< Common::ParamModifier, uint32_t > m_currTickEffect; - std::vector< World::Action::StatusModifier > m_modifiers; + std::unordered_map< Common::ParamModifier, int32_t > m_modifiers; }; }