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 "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 );

View file

@ -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;
};

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,
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 );

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,
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 );

View file

@ -3,6 +3,7 @@
#include <Action/CommonAction.h>
#include <Action/Action.h>
#include <Actor/Player.h>
#include <StatusEffect/StatusEffect.h>
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 );
if( effectIt.second->getId() == Wrath )
{
oldStatus = effectIt.second;
effectToApply = WrathII;
parry += 2;
break;
}
else if( player.hasStatusEffect( WrathII ) )
else if( effectIt.second->getId() == WrathII )
{
player.replaceSingleStatusEffectById( WrathII );
oldStatus = effectIt.second;
effectToApply = WrathIII;
parry += 2;
break;
}
else if( player.hasStatusEffect( WrathIII ) )
else if( effectIt.second->getId() == WrathIII )
{
player.replaceSingleStatusEffectById( WrathIII );
oldStatus = effectIt.second;
effectToApply = WrathIV;
parry += 2;
break;
}
else if( player.hasStatusEffect( WrathIV ) )
else if( effectIt.second->getId() == WrathIV )
{
player.replaceSingleStatusEffectById( 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 } } );
}
}

View file

@ -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;
}

View file

@ -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 );