From f2ab5d5304c7382295786797d33da24b319ee2ef Mon Sep 17 00:00:00 2001 From: Rushi <44952533+Skyliegirl33@users.noreply.github.com> Date: Mon, 20 Jan 2025 23:03:44 +0100 Subject: [PATCH] Fix slot implementation and add functionality to replace a status effect --- src/world/Action/ActionResult.cpp | 51 ++++++++++++++++--- src/world/Action/ActionResult.h | 9 +++- src/world/Action/ActionResultBuilder.cpp | 20 +++++++- src/world/Action/ActionResultBuilder.h | 7 ++- src/world/Action/Job/Warrior.cpp | 62 ++++++++++++++--------- src/world/Actor/Chara.cpp | 64 +++++++++++++++++++++--- src/world/Actor/Chara.h | 5 +- 7 files changed, 172 insertions(+), 46 deletions(-) diff --git a/src/world/Action/ActionResult.cpp b/src/world/Action/ActionResult.cpp index 13b8d99e..72891c65 100644 --- a/src/world/Action/ActionResult.cpp +++ b/src/world/Action/ActionResult.cpp @@ -9,6 +9,8 @@ #include "Actor/Player.h" #include "StatusEffect/StatusEffect.h" +#include "Network/Util/PacketUtil.h" + using namespace Sapphire; using namespace Sapphire::Common; using namespace Sapphire::World::Action; @@ -72,19 +74,21 @@ void ActionResult::applyStatusEffect( uint32_t id, int32_t duration, Entity::Cha m_result.Arg2 = param; m_result.Type = CalcResultType::TypeSetStatus; - m_bOverrideStatus = shouldOverride; + m_bShouldOverride = shouldOverride; m_pStatus = Sapphire::StatusEffect::make_StatusEffect( id, source.getAsChara(), m_target, duration, 3000 ); m_pStatus->setParam( param ); } void ActionResult::applyStatusEffect( uint32_t id, int32_t duration, Entity::Chara& source, uint8_t param, - const std::vector< StatusModifier >& modifiers, uint32_t flag, bool shouldOverride ) + const std::vector< StatusModifier >& modifiers, uint32_t flag, bool statusToSource, bool shouldOverride ) { m_result.Value = static_cast< int16_t >( id ); m_result.Arg2 = param; - m_result.Type = CalcResultType::TypeSetStatus; + m_result.Type = statusToSource ? CalcResultType::TypeSetStatusMe : CalcResultType::TypeSetStatus; + if( statusToSource ) + m_result.Flag = static_cast< uint8_t >( ActionResultFlag::EffectOnSource ); - m_bOverrideStatus = shouldOverride; + m_bShouldOverride = shouldOverride; m_pStatus = Sapphire::StatusEffect::make_StatusEffect( id, source.getAsChara(), m_target, duration, modifiers, flag, 3000 ); m_pStatus->setParam( param ); } @@ -96,7 +100,7 @@ void ActionResult::applyStatusEffectSelf( uint32_t id, int32_t duration, uint8_t m_result.Type = CalcResultType::TypeSetStatusMe; m_result.Flag = static_cast< uint8_t >( ActionResultFlag::EffectOnSource ); - m_bOverrideStatus = shouldOverride; + m_bShouldOverride = shouldOverride; m_pStatus = Sapphire::StatusEffect::make_StatusEffect( id, m_target, m_target, duration, 3000 ); m_pStatus->setParam( param ); } @@ -109,11 +113,27 @@ void ActionResult::applyStatusEffectSelf( uint32_t id, int32_t duration, uint8_t m_result.Type = CalcResultType::TypeSetStatusMe; m_result.Flag = static_cast< uint8_t >( Common::ActionResultFlag::EffectOnSource ); - m_bOverrideStatus = shouldOverride; + m_bShouldOverride = shouldOverride; m_pStatus = Sapphire::StatusEffect::make_StatusEffect( id, m_target, m_target, duration, modifiers, flag, 3000 ); m_pStatus->setParam( param ); } +void ActionResult::replaceStatusEffect( Sapphire::StatusEffect::StatusEffectPtr& pOldStatus, uint32_t id, int32_t duration, Entity::Chara& source, uint8_t param, + const std::vector< StatusModifier >& modifiers, uint32_t flag, bool statusToSource ) +{ + applyStatusEffect( id, duration, source, param, modifiers, flag, statusToSource, false ); + m_pOldStatus = std::move( pOldStatus ); + m_pStatus->setSlot( m_pOldStatus->getSlot() ); +} + +void ActionResult::replaceStatusEffectSelf( Sapphire::StatusEffect::StatusEffectPtr& pOldStatus, uint32_t id, int32_t duration, uint8_t param, + const std::vector< World::Action::StatusModifier >& modifiers, uint32_t flag ) +{ + applyStatusEffectSelf( id, duration, param, modifiers, flag, false ); + m_pOldStatus = std::move( pOldStatus ); + m_pStatus->setSlot( m_pOldStatus->getSlot() ); +} + void ActionResult::mount( uint16_t mountId ) { m_result.Value = static_cast< int16_t >( mountId ); @@ -161,7 +181,22 @@ void ActionResult::execute() case CalcResultType::TypeSetStatus: case CalcResultType::TypeSetStatusMe: { - if( !m_bOverrideStatus ) + for( auto const& entry : m_target->getStatusEffectMap() ) + { + auto statusEffect = entry.second; + if( statusEffect->getId() == m_result.Value && m_bShouldOverride ) + { + statusEffect->refresh( m_pStatus->getDuration() ); + m_pStatus->setSlot( statusEffect->getSlot() ); + + Network::Util::Packet::sendHudParam( *m_target ); + return; + } + } + + if( m_pOldStatus ) + m_target->replaceSingleStatusEffect( m_pOldStatus->getSlot(), m_pStatus ); + else if( !m_bShouldOverride ) m_target->addStatusEffectByIdIfNotExist( m_pStatus ); else m_target->addStatusEffectById( m_pStatus ); @@ -178,4 +213,4 @@ void ActionResult::execute() default: break; } -} \ No newline at end of file +} diff --git a/src/world/Action/ActionResult.h b/src/world/Action/ActionResult.h index 3a10b4ab..59f213e2 100644 --- a/src/world/Action/ActionResult.h +++ b/src/world/Action/ActionResult.h @@ -22,10 +22,14 @@ namespace Sapphire::World::Action void comboSucceed(); void applyStatusEffect( uint32_t id, int32_t duration, Entity::Chara& source, uint8_t param, bool shouldOverride ); void applyStatusEffect( uint32_t id, int32_t duration, Entity::Chara& source, uint8_t param, - const std::vector< World::Action::StatusModifier >& modifiers, uint32_t flag, bool shouldOverride ); + const std::vector< World::Action::StatusModifier >& modifiers, uint32_t flag, bool statusToSource, bool shouldOverride ); void applyStatusEffectSelf( uint32_t id, int32_t duration, uint8_t param, bool shouldOverride ); void applyStatusEffectSelf( uint32_t id, int32_t duration, uint8_t param, const std::vector< World::Action::StatusModifier >& modifiers, uint32_t flag, bool shouldOverride ); + void replaceStatusEffect( Sapphire::StatusEffect::StatusEffectPtr& pOldStatus, uint32_t id, int32_t duration, Entity::Chara& source, uint8_t param, + const std::vector< StatusModifier >& modifiers, uint32_t flag, bool statusToSource ); + void replaceStatusEffectSelf( Sapphire::StatusEffect::StatusEffectPtr& pOldStatus, uint32_t id, int32_t duration, uint8_t param, + const std::vector< World::Action::StatusModifier >& modifiers, uint32_t flag ); void mount( uint16_t mountId ); Entity::CharaPtr getTarget() const; @@ -40,8 +44,9 @@ namespace Sapphire::World::Action Common::CalcResultParam m_result; - bool m_bOverrideStatus { false }; + bool m_bShouldOverride { false }; Sapphire::StatusEffect::StatusEffectPtr m_pStatus; + Sapphire::StatusEffect::StatusEffectPtr m_pOldStatus; }; diff --git a/src/world/Action/ActionResultBuilder.cpp b/src/world/Action/ActionResultBuilder.cpp index db0da0cb..85f901d3 100644 --- a/src/world/Action/ActionResultBuilder.cpp +++ b/src/world/Action/ActionResultBuilder.cpp @@ -94,10 +94,10 @@ void ActionResultBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t } void ActionResultBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint32_t duration, uint8_t param, - const std::vector< World::Action::StatusModifier >& modifiers, uint32_t flag, bool shouldOverride ) + const std::vector< World::Action::StatusModifier >& modifiers, uint32_t flag, bool statusToSource, bool shouldOverride ) { ActionResultPtr nextResult = make_ActionResult( target ); - nextResult->applyStatusEffect( statusId, duration, *m_sourceChara, param, modifiers, flag, shouldOverride ); + nextResult->applyStatusEffect( statusId, duration, *m_sourceChara, param, modifiers, flag, statusToSource, shouldOverride ); addResultToActor( target, nextResult ); } @@ -116,6 +116,22 @@ void ActionResultBuilder::applyStatusEffectSelf( uint16_t statusId, uint32_t dur addResultToActor( m_sourceChara, nextResult ); } +void ActionResultBuilder::replaceStatusEffect( Sapphire::StatusEffect::StatusEffectPtr& pOldStatus, Entity::CharaPtr& target, uint16_t statusId, uint32_t duration, uint8_t param, + const std::vector< World::Action::StatusModifier >& modifiers, uint32_t flag, bool statusToSource ) +{ + ActionResultPtr nextResult = make_ActionResult( target ); + nextResult->replaceStatusEffect( pOldStatus, statusId, duration, *m_sourceChara, param, modifiers, flag, statusToSource ); + addResultToActor( target, nextResult ); +} + +void ActionResultBuilder::replaceStatusEffectSelf( Sapphire::StatusEffect::StatusEffectPtr& pOldStatus, uint16_t statusId, uint32_t duration, uint8_t param, + const std::vector< World::Action::StatusModifier >& modifiers, uint32_t flag ) +{ + ActionResultPtr nextResult = make_ActionResult( m_sourceChara ); + nextResult->replaceStatusEffectSelf( pOldStatus, statusId, duration, param, modifiers, flag ); + addResultToActor( m_sourceChara, nextResult ); +} + void ActionResultBuilder::mount( Entity::CharaPtr& target, uint16_t mountId ) { ActionResultPtr nextResult = make_ActionResult( target ); diff --git a/src/world/Action/ActionResultBuilder.h b/src/world/Action/ActionResultBuilder.h index e2e79747..b6009222 100644 --- a/src/world/Action/ActionResultBuilder.h +++ b/src/world/Action/ActionResultBuilder.h @@ -28,11 +28,14 @@ namespace Sapphire::World::Action void applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint32_t duration, uint8_t param, bool shouldOverride = false ); void applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint32_t duration, uint8_t param, - const std::vector< World::Action::StatusModifier >& modifiers, uint32_t flag = 0, bool shouldOverride = false ); + const std::vector< World::Action::StatusModifier >& modifiers, uint32_t flag = 0, bool statusToSource = false, bool shouldOverride = false ); void applyStatusEffectSelf( uint16_t statusId, uint32_t duration, uint8_t param, bool shouldOverride = false ); void applyStatusEffectSelf( uint16_t statusId, uint32_t duration, uint8_t param, const std::vector< World::Action::StatusModifier >& modifiers, uint32_t flag = 0, bool shouldOverride = false ); - + void replaceStatusEffect( Sapphire::StatusEffect::StatusEffectPtr& pOldStatus, Entity::CharaPtr& target, uint16_t statusId, uint32_t duration, uint8_t param, + const std::vector< StatusModifier >& modifiers, uint32_t flag = 0, bool statusToSource = false ); + void replaceStatusEffectSelf( Sapphire::StatusEffect::StatusEffectPtr& pOldStatus, uint16_t statusId, uint32_t duration, uint8_t param, + const std::vector< World::Action::StatusModifier >& modifiers, uint32_t flag = 0 ); void mount( Entity::CharaPtr& target, uint16_t mountId ); void sendActionResults( const std::vector< Entity::CharaPtr >& targetList ); diff --git a/src/world/Action/Job/Warrior.cpp b/src/world/Action/Job/Warrior.cpp index 4ee8a485..f4e1c9c2 100644 --- a/src/world/Action/Job/Warrior.cpp +++ b/src/world/Action/Job/Warrior.cpp @@ -3,6 +3,7 @@ #include #include #include +#include using namespace Sapphire; using namespace Sapphire::World::Action; @@ -29,6 +30,7 @@ void Warrior::onAction( Entity::Player& player, Action& action ) void Warrior::handleWrath( Entity::Player& player, Action& action ) { + Sapphire::StatusEffect::StatusEffectPtr oldStatus = nullptr; auto effectToApply = Wrath; auto parry = 2; auto asChara = player.getAsChara(); @@ -38,33 +40,45 @@ void Warrior::handleWrath( Entity::Player& player, Action& action ) if( !pActionBuilder ) return; - if( player.hasStatusEffect( Wrath ) ) + auto statusMap = player.getStatusEffectMap(); + + for( const auto& effectIt : statusMap ) { - player.replaceSingleStatusEffectById( Wrath ); - effectToApply = WrathII; - parry += 2; - } - else if( player.hasStatusEffect( WrathII ) ) - { - player.replaceSingleStatusEffectById( WrathII ); - effectToApply = WrathIII; - parry += 2; - } - else if( player.hasStatusEffect( WrathIII ) ) - { - player.replaceSingleStatusEffectById( WrathIII ); - effectToApply = WrathIV; - parry += 2; - } - else if( player.hasStatusEffect( WrathIV ) ) - { - player.replaceSingleStatusEffectById( WrathIV ); - effectToApply = Infuriated; - parry += 2; + if( effectIt.second->getId() == Wrath ) + { + oldStatus = effectIt.second; + effectToApply = WrathII; + parry += 2; + break; + } + else if( effectIt.second->getId() == WrathII ) + { + oldStatus = effectIt.second; + effectToApply = WrathIII; + parry += 2; + break; + } + else if( effectIt.second->getId() == WrathIII ) + { + oldStatus = effectIt.second; + effectToApply = WrathIV; + parry += 2; + break; + } + else if( effectIt.second->getId() == WrathIV ) + { + oldStatus = effectIt.second; + effectToApply = Infuriated; + parry += 2; + break; + } } if( !player.hasStatusEffect( Infuriated ) ) - { - pActionBuilder->applyStatusEffectSelf( effectToApply, 30000, 0, { StatusModifier{ Common::ParamModifier::ParryPercent, parry } }, 0, false ); + { + if( oldStatus ) + pActionBuilder->replaceStatusEffectSelf( oldStatus, effectToApply, 30000, 0, { StatusModifier{ Common::ParamModifier::ParryPercent, parry } } ); + else + pActionBuilder->applyStatusEffectSelf( effectToApply, 30000, 0, { StatusModifier{ Common::ParamModifier::ParryPercent, parry } } ); } } \ No newline at end of file diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index 9593b045..f4f40d8e 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -521,18 +521,41 @@ int8_t Chara::getStatusEffectFreeSlot() { int8_t freeEffectSlot = -1; - if( m_statusEffectFreeSlotQueue.empty() ) + // if( m_statusEffectFreeSlotQueue.empty() ) + // return freeEffectSlot; + + // freeEffectSlot = static_cast< int8_t >( m_statusEffectFreeSlotQueue.front() ); + // m_statusEffectFreeSlotQueue.pop(); + + if( m_statusEffectSlots.size() >= MAX_STATUS_EFFECTS ) return freeEffectSlot; - freeEffectSlot = static_cast< int8_t >( m_statusEffectFreeSlotQueue.front() ); - m_statusEffectFreeSlotQueue.pop(); + if( m_statusEffectSlots.empty() ) + freeEffectSlot = 0; + else + freeEffectSlot = static_cast< int8_t >( *m_statusEffectSlots.rbegin() + 1 ); + + m_statusEffectSlots.insert( freeEffectSlot ); + + Logger::warn( "Slot id being added: {}", freeEffectSlot ); return freeEffectSlot; } void Chara::statusEffectFreeSlot( uint8_t slotId ) { - m_statusEffectFreeSlotQueue.push( slotId ); + // m_statusEffectFreeSlotQueue.push( slotId ); + m_statusEffectSlots.erase( slotId ); + // std::set< uint8_t > shiftedSlots; +} + +void Chara::replaceSingleStatusEffect( uint32_t slotId, StatusEffect::StatusEffectPtr pStatus ) +{ + // removeStatusEffect( slotId, false ); + // addStatusEffect( pStatus ); + pStatus->setSlot( slotId ); + m_statusEffectMap[ slotId ] = pStatus; + pStatus->applyStatus(); } void Chara::replaceSingleStatusEffectById( uint32_t id ) @@ -588,7 +611,7 @@ void Chara::removeStatusEffectByFlag( Common::StatusEffectFlag flag ) } } -std::map< uint8_t, Sapphire::StatusEffect::StatusEffectPtr >::iterator Chara::removeStatusEffect( uint8_t effectSlotId, bool sendOrder ) +std::map< uint8_t, Sapphire::StatusEffect::StatusEffectPtr >::iterator Chara::removeStatusEffect( uint8_t effectSlotId, bool updateStatus ) { auto pEffectIt = m_statusEffectMap.find( effectSlotId ); if( pEffectIt == m_statusEffectMap.end() ) @@ -599,11 +622,38 @@ std::map< uint8_t, Sapphire::StatusEffect::StatusEffectPtr >::iterator Chara::re auto pEffect = pEffectIt->second; pEffect->removeStatus(); - if( sendOrder ) + if( updateStatus ) + { Network::Util::Packet::sendActorControl( getInRangePlayerIds( isPlayer() ), getId(), StatusEffectLose, pEffect->getId() ); + Network::Util::Packet::sendHudParam( *this ); + } auto it = m_statusEffectMap.erase( pEffectIt ); - Network::Util::Packet::sendHudParam( *this ); + + // for( const auto& effectIt : m_statusEffectMap ) + for( auto effectIt = it; effectIt != m_statusEffectMap.end(); ) + { + // if( effectIt.first > effectSlotId ) + // { + // if the status is *after* the one being removed, shift the slots down by one + auto shifted_slot = effectIt->first - 1; + auto node_slot = m_statusEffectSlots.extract( effectIt->first ); + node_slot.value() = shifted_slot; + m_statusEffectSlots.insert( std::move( node_slot ) ); + + auto node_status = m_statusEffectMap.extract( effectIt->first ); + node_status.key() = shifted_slot; + m_statusEffectMap.insert( std::move( node_status ) ); + + effectIt->second->setSlot( effectIt->second->getSlot() - 1 ); + + Logger::warn( "Shifted slot {} to slot: {}", effectSlotId, shifted_slot ); + ++effectIt; + // } + } + + Logger::warn( "Slot id being freed: {}", effectSlotId ); + return it; } diff --git a/src/world/Actor/Chara.h b/src/world/Actor/Chara.h index 212ea1de..252a2cd6 100644 --- a/src/world/Actor/Chara.h +++ b/src/world/Actor/Chara.h @@ -89,6 +89,7 @@ namespace Sapphire::Entity std::queue< uint8_t > m_statusEffectFreeSlotQueue; std::vector< std::pair< uint8_t, uint32_t > > m_statusEffectList; std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap; + std::set< uint8_t > m_statusEffectSlots; /*! Detour Crowd AgentId */ uint32_t m_agentId; @@ -108,7 +109,9 @@ namespace Sapphire::Entity /// Status effect functions void addStatusEffect( StatusEffect::StatusEffectPtr pEffect ); - std::map< uint8_t, StatusEffect::StatusEffectPtr >::iterator removeStatusEffect( uint8_t effectSlotId, bool sendOrder = true ); + std::map< uint8_t, StatusEffect::StatusEffectPtr >::iterator removeStatusEffect( uint8_t effectSlotId, bool updateStatus = true ); + + void replaceSingleStatusEffect( uint32_t slotId, StatusEffect::StatusEffectPtr pStatus ); void replaceSingleStatusEffectById( uint32_t id );