1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-23 10:17:44 +00:00

Fix slot implementation and add functionality to replace a status effect

This commit is contained in:
Rushi 2025-01-20 23:03:44 +01:00
parent e442b735d3
commit f2ab5d5304
7 changed files with 172 additions and 46 deletions

View file

@ -9,6 +9,8 @@
#include "Actor/Player.h" #include "Actor/Player.h"
#include "StatusEffect/StatusEffect.h" #include "StatusEffect/StatusEffect.h"
#include "Network/Util/PacketUtil.h"
using namespace Sapphire; using namespace Sapphire;
using namespace Sapphire::Common; using namespace Sapphire::Common;
using namespace Sapphire::World::Action; 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.Arg2 = param;
m_result.Type = CalcResultType::TypeSetStatus; 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 = Sapphire::StatusEffect::make_StatusEffect( id, source.getAsChara(), m_target, duration, 3000 );
m_pStatus->setParam( param ); m_pStatus->setParam( param );
} }
void ActionResult::applyStatusEffect( uint32_t id, int32_t duration, Entity::Chara& source, uint8_t 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.Value = static_cast< int16_t >( id );
m_result.Arg2 = param; 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 = Sapphire::StatusEffect::make_StatusEffect( id, source.getAsChara(), m_target, duration, modifiers, flag, 3000 );
m_pStatus->setParam( param ); 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.Type = CalcResultType::TypeSetStatusMe;
m_result.Flag = static_cast< uint8_t >( ActionResultFlag::EffectOnSource ); 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 = Sapphire::StatusEffect::make_StatusEffect( id, m_target, m_target, duration, 3000 );
m_pStatus->setParam( param ); 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.Type = CalcResultType::TypeSetStatusMe;
m_result.Flag = static_cast< uint8_t >( Common::ActionResultFlag::EffectOnSource ); 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 = Sapphire::StatusEffect::make_StatusEffect( id, m_target, m_target, duration, modifiers, flag, 3000 );
m_pStatus->setParam( param ); 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 ) void ActionResult::mount( uint16_t mountId )
{ {
m_result.Value = static_cast< int16_t >( mountId ); m_result.Value = static_cast< int16_t >( mountId );
@ -161,7 +181,22 @@ void ActionResult::execute()
case CalcResultType::TypeSetStatus: case CalcResultType::TypeSetStatus:
case CalcResultType::TypeSetStatusMe: 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 ); m_target->addStatusEffectByIdIfNotExist( m_pStatus );
else else
m_target->addStatusEffectById( m_pStatus ); m_target->addStatusEffectById( m_pStatus );

View file

@ -22,10 +22,14 @@ namespace Sapphire::World::Action
void comboSucceed(); 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, bool shouldOverride );
void applyStatusEffect( uint32_t id, int32_t duration, Entity::Chara& source, uint8_t param, 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, bool shouldOverride );
void applyStatusEffectSelf( uint32_t id, int32_t duration, uint8_t param, const std::vector< World::Action::StatusModifier >& modifiers, void applyStatusEffectSelf( uint32_t id, int32_t duration, uint8_t param, const std::vector< World::Action::StatusModifier >& modifiers,
uint32_t flag, bool shouldOverride ); 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 ); void mount( uint16_t mountId );
Entity::CharaPtr getTarget() const; Entity::CharaPtr getTarget() const;
@ -40,8 +44,9 @@ namespace Sapphire::World::Action
Common::CalcResultParam m_result; Common::CalcResultParam m_result;
bool m_bOverrideStatus { false }; bool m_bShouldOverride { false };
Sapphire::StatusEffect::StatusEffectPtr m_pStatus; Sapphire::StatusEffect::StatusEffectPtr m_pStatus;
Sapphire::StatusEffect::StatusEffectPtr m_pOldStatus;
}; };

View file

@ -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, 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 ); 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 ); addResultToActor( target, nextResult );
} }
@ -116,6 +116,22 @@ void ActionResultBuilder::applyStatusEffectSelf( uint16_t statusId, uint32_t dur
addResultToActor( m_sourceChara, nextResult ); 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 ) void ActionResultBuilder::mount( Entity::CharaPtr& target, uint16_t mountId )
{ {
ActionResultPtr nextResult = make_ActionResult( target ); ActionResultPtr nextResult = make_ActionResult( target );

View file

@ -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, bool shouldOverride = false );
void applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint32_t duration, uint8_t param, 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, bool shouldOverride = false );
void applyStatusEffectSelf( uint16_t statusId, uint32_t duration, uint8_t param, const std::vector< World::Action::StatusModifier >& modifiers, 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 ); 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 mount( Entity::CharaPtr& target, uint16_t mountId );
void sendActionResults( const std::vector< Entity::CharaPtr >& targetList ); void sendActionResults( const std::vector< Entity::CharaPtr >& targetList );

View file

@ -3,6 +3,7 @@
#include <Action/CommonAction.h> #include <Action/CommonAction.h>
#include <Action/Action.h> #include <Action/Action.h>
#include <Actor/Player.h> #include <Actor/Player.h>
#include <StatusEffect/StatusEffect.h>
using namespace Sapphire; using namespace Sapphire;
using namespace Sapphire::World::Action; 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 ) void Warrior::handleWrath( Entity::Player& player, Action& action )
{ {
Sapphire::StatusEffect::StatusEffectPtr oldStatus = nullptr;
auto effectToApply = Wrath; auto effectToApply = Wrath;
auto parry = 2; auto parry = 2;
auto asChara = player.getAsChara(); auto asChara = player.getAsChara();
@ -38,33 +40,45 @@ void Warrior::handleWrath( Entity::Player& player, Action& action )
if( !pActionBuilder ) if( !pActionBuilder )
return; return;
if( player.hasStatusEffect( Wrath ) ) auto statusMap = player.getStatusEffectMap();
for( const auto& effectIt : statusMap )
{ {
player.replaceSingleStatusEffectById( Wrath ); if( effectIt.second->getId() == Wrath )
effectToApply = WrathII; {
parry += 2; oldStatus = effectIt.second;
} effectToApply = WrathII;
else if( player.hasStatusEffect( WrathII ) ) parry += 2;
{ break;
player.replaceSingleStatusEffectById( WrathII ); }
effectToApply = WrathIII; else if( effectIt.second->getId() == WrathII )
parry += 2; {
} oldStatus = effectIt.second;
else if( player.hasStatusEffect( WrathIII ) ) effectToApply = WrathIII;
{ parry += 2;
player.replaceSingleStatusEffectById( WrathIII ); break;
effectToApply = WrathIV; }
parry += 2; else if( effectIt.second->getId() == WrathIII )
} {
else if( player.hasStatusEffect( WrathIV ) ) oldStatus = effectIt.second;
{ effectToApply = WrathIV;
player.replaceSingleStatusEffectById( WrathIV ); parry += 2;
effectToApply = Infuriated; break;
parry += 2; }
else if( effectIt.second->getId() == WrathIV )
{
oldStatus = effectIt.second;
effectToApply = Infuriated;
parry += 2;
break;
}
} }
if( !player.hasStatusEffect( Infuriated ) ) 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 } } );
} }
} }

View file

@ -521,18 +521,41 @@ int8_t Chara::getStatusEffectFreeSlot()
{ {
int8_t freeEffectSlot = -1; 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; return freeEffectSlot;
freeEffectSlot = static_cast< int8_t >( m_statusEffectFreeSlotQueue.front() ); if( m_statusEffectSlots.empty() )
m_statusEffectFreeSlotQueue.pop(); 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; return freeEffectSlot;
} }
void Chara::statusEffectFreeSlot( uint8_t slotId ) 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 ) 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 ); auto pEffectIt = m_statusEffectMap.find( effectSlotId );
if( pEffectIt == m_statusEffectMap.end() ) if( pEffectIt == m_statusEffectMap.end() )
@ -599,11 +622,38 @@ std::map< uint8_t, Sapphire::StatusEffect::StatusEffectPtr >::iterator Chara::re
auto pEffect = pEffectIt->second; auto pEffect = pEffectIt->second;
pEffect->removeStatus(); pEffect->removeStatus();
if( sendOrder ) if( updateStatus )
{
Network::Util::Packet::sendActorControl( getInRangePlayerIds( isPlayer() ), getId(), StatusEffectLose, pEffect->getId() ); Network::Util::Packet::sendActorControl( getInRangePlayerIds( isPlayer() ), getId(), StatusEffectLose, pEffect->getId() );
Network::Util::Packet::sendHudParam( *this );
}
auto it = m_statusEffectMap.erase( pEffectIt ); 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; return it;
} }

View file

@ -89,6 +89,7 @@ namespace Sapphire::Entity
std::queue< uint8_t > m_statusEffectFreeSlotQueue; std::queue< uint8_t > m_statusEffectFreeSlotQueue;
std::vector< std::pair< uint8_t, uint32_t > > m_statusEffectList; std::vector< std::pair< uint8_t, uint32_t > > m_statusEffectList;
std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap; std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap;
std::set< uint8_t > m_statusEffectSlots;
/*! Detour Crowd AgentId */ /*! Detour Crowd AgentId */
uint32_t m_agentId; uint32_t m_agentId;
@ -108,7 +109,9 @@ namespace Sapphire::Entity
/// Status effect functions /// Status effect functions
void addStatusEffect( StatusEffect::StatusEffectPtr pEffect ); 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 ); void replaceSingleStatusEffectById( uint32_t id );