1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-28 15:17:46 +00:00

Merge pull request #903 from Skyliegirl33/status-fix

[3.x] StatusEffect and HudParam fixes
This commit is contained in:
Mordred 2023-02-22 17:02:02 +01:00 committed by GitHub
commit 6ea6f8e190
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 65 additions and 16 deletions

View file

@ -15,6 +15,7 @@
#include "Network/PacketWrappers/ActorControlTargetPacket.h" #include "Network/PacketWrappers/ActorControlTargetPacket.h"
#include "Network/PacketWrappers/UpdateHpMpTpPacket.h" #include "Network/PacketWrappers/UpdateHpMpTpPacket.h"
#include "Network/PacketWrappers/EffectPacket1.h" #include "Network/PacketWrappers/EffectPacket1.h"
#include "Network/PacketWrappers/HudParamPacket.h"
#include "StatusEffect/StatusEffect.h" #include "StatusEffect/StatusEffect.h"
#include "Action/Action.h" #include "Action/Action.h"
@ -601,11 +602,11 @@ void Sapphire::Entity::Chara::removeSingleStatusEffectById( uint32_t id )
} }
} }
void Sapphire::Entity::Chara::removeStatusEffect( uint8_t effectSlotId ) std::map< uint8_t, Sapphire::StatusEffect::StatusEffectPtr >::iterator Sapphire::Entity::Chara::removeStatusEffect( uint8_t effectSlotId )
{ {
auto pEffectIt = m_statusEffectMap.find( effectSlotId ); auto pEffectIt = m_statusEffectMap.find( effectSlotId );
if( pEffectIt == m_statusEffectMap.end() ) if( pEffectIt == m_statusEffectMap.end() )
return; return pEffectIt;
statusEffectFreeSlot( effectSlotId ); statusEffectFreeSlot( effectSlotId );
@ -614,9 +615,14 @@ void Sapphire::Entity::Chara::removeStatusEffect( uint8_t effectSlotId )
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeActorControl( getId(), StatusEffectLose, pEffect->getId() ) ); server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeActorControl( getId(), StatusEffectLose, pEffect->getId() ) );
m_statusEffectMap.erase( effectSlotId ); auto it = m_statusEffectMap.erase( pEffectIt );
sendStatusEffectUpdate(); if( isPlayer() )
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeHudParam( *getAsPlayer() ) );
else if( isBattleNpc() )
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeHudParam( *getAsBNpc() ) );
return it;
} }
std::map< uint8_t, Sapphire::StatusEffect::StatusEffectPtr > Sapphire::Entity::Chara::getStatusEffectMap() const std::map< uint8_t, Sapphire::StatusEffect::StatusEffectPtr > Sapphire::Entity::Chara::getStatusEffectMap() const
@ -668,10 +674,10 @@ void Sapphire::Entity::Chara::updateStatusEffects()
{ {
uint64_t currentTimeMs = Util::getTimeMs(); uint64_t currentTimeMs = Util::getTimeMs();
for( const auto& effectIt : m_statusEffectMap ) for( auto effectIt = m_statusEffectMap.begin(); effectIt != m_statusEffectMap.end(); )
{ {
uint8_t effectIndex = effectIt.first; uint8_t effectIndex = effectIt->first;
auto effect = effectIt.second; auto effect = effectIt->second;
uint64_t lastTick = effect->getLastTickMs(); uint64_t lastTick = effect->getLastTickMs();
uint64_t startTime = effect->getStartTimeMs(); uint64_t startTime = effect->getStartTimeMs();
@ -679,12 +685,9 @@ void Sapphire::Entity::Chara::updateStatusEffects()
uint32_t tickRate = effect->getTickRate(); uint32_t tickRate = effect->getTickRate();
if( duration > 0 && ( currentTimeMs - startTime ) > duration ) if( duration > 0 && ( currentTimeMs - startTime ) > duration )
{ effectIt = removeStatusEffect( effectIndex );
// remove status effect else
removeStatusEffect( effectIndex ); ++effectIt;
// break because removing invalidates iterators
break;
}
if( ( currentTimeMs - lastTick ) > tickRate ) if( ( currentTimeMs - lastTick ) > tickRate )
{ {

View file

@ -106,7 +106,7 @@ namespace Sapphire::Entity
/// Status effect functions /// Status effect functions
void addStatusEffect( StatusEffect::StatusEffectPtr pEffect ); void addStatusEffect( StatusEffect::StatusEffectPtr pEffect );
void removeStatusEffect( uint8_t effectSlotId ); std::map< uint8_t, StatusEffect::StatusEffectPtr >::iterator removeStatusEffect( uint8_t effectSlotId );
void removeSingleStatusEffectById( uint32_t id ); void removeSingleStatusEffectById( uint32_t id );

View file

@ -3,6 +3,8 @@
#include <Network/GamePacket.h> #include <Network/GamePacket.h>
#include <StatusEffect/StatusEffect.h> #include <StatusEffect/StatusEffect.h>
#include <Util/Util.h> #include <Util/Util.h>
#include <Actor/Player.h>
#include <Actor/BNpc.h>
#include "Forwards.h" #include "Forwards.h"
namespace Sapphire::Network::Packets::WorldPackets::Server namespace Sapphire::Network::Packets::WorldPackets::Server
@ -19,6 +21,11 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
initialize( player ); initialize( player );
}; };
HudParamPacket( Entity::BNpc& bnpc ) : ZoneChannelPacket< FFXIVIpcHudParam >( bnpc.getId(), bnpc.getId() )
{
initialize( bnpc );
};
private: private:
void initialize( Entity::Player& player ) void initialize( Entity::Player& player )
{ {
@ -32,19 +39,58 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
m_data.HpMax = player.getMaxHp(); m_data.HpMax = player.getMaxHp();
m_data.MpMax = player.getMaxMp(); m_data.MpMax = player.getMaxMp();
for( int i = 0; i < 30; ++i )
m_data.effect[ i ] = { 0, 0, 0.0f, 0 };
auto statusMap = player.getStatusEffectMap(); auto statusMap = player.getStatusEffectMap();
int i = 0; int i = 0;
for( const auto& [ key, val ] : statusMap ) for( const auto& [ key, val ] : statusMap )
{ {
auto timeLeft = static_cast< int32_t >( val->getDuration() - ( Common::Util::getTimeMs() - val->getStartTimeMs() ) );
m_data.effect[ i ].Id = val->getId(); m_data.effect[ i ].Id = val->getId();
m_data.effect[ i ].Source = val->getSrcActorId(); m_data.effect[ i ].Source = val->getSrcActorId();
m_data.effect[ i ].SystemParam = val->getParam(); m_data.effect[ i ].SystemParam = val->getParam();
m_data.effect[ i ].Time = ( val->getDuration() - ( Common::Util::getTimeMs() - val->getStartTimeMs() ) ) / 1000.f; if( timeLeft <= 0 )
m_data.effect[ i ].Time = 0.f;
else
m_data.effect[ i ].Time = timeLeft / 1000.f;
i++; i++;
} }
}; }
void initialize( Entity::BNpc& bnpc )
{
m_data.ClassJob = static_cast< uint8_t >( bnpc.getClass() );
m_data.Lv = bnpc.getLevel();
m_data.OrgLv = bnpc.getLevel();
m_data.LvSync = 0;
m_data.Hp = bnpc.getHp();
m_data.Mp = bnpc.getMp();
m_data.Tp = bnpc.getTp();
m_data.HpMax = bnpc.getMaxHp();
m_data.MpMax = bnpc.getMaxMp();
for( int i = 0; i < 30; ++i )
m_data.effect[ i ] = { 0, 0, 0.0f, 0 };
auto statusMap = bnpc.getStatusEffectMap();
int i = 0;
for( const auto& [ key, val ] : statusMap )
{
auto timeLeft = static_cast< int32_t >( val->getDuration() - ( Common::Util::getTimeMs() - val->getStartTimeMs() ) );
m_data.effect[ i ].Id = val->getId();
m_data.effect[ i ].Source = val->getSrcActorId();
m_data.effect[ i ].SystemParam = val->getParam();
if( timeLeft <= 0 )
m_data.effect[ i ].Time = 0.f;
else
m_data.effect[ i ].Time = timeLeft / 1000.f;
i++;
}
}
}; };
template< typename... Args > template< typename... Args >
std::shared_ptr< HudParamPacket > makeHudParam( Args... args ) std::shared_ptr< HudParamPacket > makeHudParam( Args... args )