1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-01 08:27:46 +00:00

Status effect rework for actionintegrity.

This commit is contained in:
Mordred 2023-03-10 22:34:12 +01:00
parent 5d353de158
commit 72f06fb072
9 changed files with 76 additions and 62 deletions

View file

@ -17,10 +17,7 @@ public:
return; return;
uint32_t duration = ( sourceChara->getAsPlayer()->getTp() / 50 ) * 1000; uint32_t duration = ( sourceChara->getAsPlayer()->getTp() / 50 ) * 1000;
action.getActionResultBuilder()->applyStatusEffect( sourceChara, 50, duration, 30, false );
action.getActionResultBuilder()->applyStatusEffect( sourceChara, 50, 30 );
sourceChara->getAsPlayer()->addStatusEffectByIdIfNotExist( 50, duration, *sourceChara, 30 );
sourceChara->getAsPlayer()->setTp( 0 ); sourceChara->getAsPlayer()->setTp( 0 );
} }
}; };

View file

@ -7,6 +7,7 @@
#include "Actor/Chara.h" #include "Actor/Chara.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;
@ -70,11 +71,15 @@ void ActionResult::comboSucceed()
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_COMBO_HIT; m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_COMBO_HIT;
} }
void ActionResult::applyStatusEffect( uint16_t statusId, uint8_t param ) void ActionResult::applyStatusEffect( uint32_t id, int32_t duration, Entity::Chara& source, uint8_t param, bool shouldOverride )
{ {
m_result.Value = static_cast< int16_t >( statusId ); m_result.Value = static_cast< int16_t >( id );
m_result.Arg2 = param; m_result.Arg2 = param;
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_SET_STATUS; m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_SET_STATUS;
m_bOverrideStatus = shouldOverride;
m_pStatus = StatusEffect::make_StatusEffect( id, source.getAsChara(), m_target, duration, 3000 );
m_pStatus->setParam( param );
} }
void ActionResult::mount( uint16_t mountId ) void ActionResult::mount( uint16_t mountId )
@ -89,6 +94,11 @@ const Common::CalcResultParam& ActionResult::getCalcResultParam() const
return m_result; return m_result;
} }
const StatusEffect::StatusEffectPtr ActionResult::getStatusEffect() const
{
return m_pStatus;
}
void ActionResult::execute() void ActionResult::execute()
{ {
if( !m_target ) if( !m_target )
@ -114,6 +124,15 @@ void ActionResult::execute()
break; break;
} }
case Common::ActionEffectType::CALC_RESULT_TYPE_SET_STATUS:
{
if( !m_bOverrideStatus )
m_target->addStatusEffectByIdIfNotExist( m_pStatus->getId(), m_pStatus->getDuration(), *m_pStatus->getSrcActor(), m_pStatus->getParam() );
else
m_target->addStatusEffectById( m_pStatus->getId(), m_pStatus->getDuration(), *m_pStatus->getSrcActor(), m_pStatus->getParam() );
break;
}
case Common::ActionEffectType::CALC_RESULT_TYPE_MOUNT: case Common::ActionEffectType::CALC_RESULT_TYPE_MOUNT:
{ {
auto pPlayer = m_target->getAsPlayer(); auto pPlayer = m_target->getAsPlayer();

View file

@ -19,7 +19,7 @@ namespace Sapphire::World::Action
void restoreMP( uint32_t amount, Common::ActionResultFlag flag = Common::ActionResultFlag::None ); void restoreMP( uint32_t amount, Common::ActionResultFlag flag = Common::ActionResultFlag::None );
void startCombo( uint16_t actionId ); void startCombo( uint16_t actionId );
void comboSucceed(); void comboSucceed();
void applyStatusEffect( uint16_t statusId, uint8_t param ); void applyStatusEffect( uint32_t id, int32_t duration, Entity::Chara& source, uint8_t param, bool shouldOverride );
void mount( uint16_t mountId ); void mount( uint16_t mountId );
Entity::CharaPtr getTarget() const; Entity::CharaPtr getTarget() const;
@ -27,6 +27,7 @@ namespace Sapphire::World::Action
uint64_t getDelay(); uint64_t getDelay();
const Common::CalcResultParam& getCalcResultParam() const; const Common::CalcResultParam& getCalcResultParam() const;
const Sapphire::StatusEffect::StatusEffectPtr getStatusEffect() const;
void execute(); void execute();
@ -37,6 +38,9 @@ namespace Sapphire::World::Action
Common::CalcResultParam m_result; Common::CalcResultParam m_result;
bool m_bOverrideStatus { false };
Sapphire::StatusEffect::StatusEffectPtr m_pStatus;
}; };
using ActionResultList = std::vector< ActionResultPtr >; using ActionResultList = std::vector< ActionResultPtr >;

View file

@ -81,10 +81,10 @@ void ActionResultBuilder::comboSucceed( Entity::CharaPtr& target )
addResultToActor( target, nextResult ); addResultToActor( target, nextResult );
} }
void ActionResultBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param ) void ActionResultBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint32_t duration, uint8_t param, bool shouldOverride )
{ {
ActionResultPtr nextResult = make_ActionResult( target, 0 ); ActionResultPtr nextResult = make_ActionResult( target, 0 );
nextResult->applyStatusEffect( statusId, param ); nextResult->applyStatusEffect( statusId, duration, *m_sourceChara, param, shouldOverride );
addResultToActor( target, nextResult ); addResultToActor( target, nextResult );
} }
@ -122,6 +122,8 @@ std::shared_ptr< FFXIVPacketBase > ActionResultBuilder::createActionResultPacket
actionResult->setRequestId( m_requestId ); actionResult->setRequestId( m_requestId );
actionResult->setResultId( m_resultId ); actionResult->setResultId( m_resultId );
actionResult->setEffectFlags( Common::ActionEffectDisplayType::HideActionName ); actionResult->setEffectFlags( Common::ActionEffectDisplayType::HideActionName );
if( !m_actorResultsMap.empty() )
taskMgr.queueTask( World::makeActionIntegrityTask( m_resultId, m_sourceChara, m_actorResultsMap.begin()->second, 300 ) );
m_actorResultsMap.clear(); m_actorResultsMap.clear();
return actionResult; return actionResult;
} }

View file

@ -25,7 +25,7 @@ namespace Sapphire::World::Action
void comboSucceed( Entity::CharaPtr& target ); void comboSucceed( Entity::CharaPtr& target );
void applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param ); void applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint32_t duration, uint8_t param, bool shouldOverride );
void mount( Entity::CharaPtr& target, uint16_t mountId ); void mount( Entity::CharaPtr& target, uint16_t mountId );

View file

@ -500,37 +500,8 @@ void Chara::addStatusEffect( StatusEffect::StatusEffectPtr pEffect )
return; return;
pEffect->applyStatus(); pEffect->applyStatus();
pEffect->setSlot( nextSlot );
m_statusEffectMap[ nextSlot ] = pEffect; m_statusEffectMap[ nextSlot ] = pEffect;
auto statusEffectAdd = makeZonePacket< FFXIVIpcActionIntegrity >( getId() );
statusEffectAdd->data().ResultId = pZone->getNextActionResultId();
statusEffectAdd->data().Target = pEffect->getTargetActorId();
statusEffectAdd->data().Hp = getHp();
statusEffectAdd->data().Mp = static_cast< uint16_t >( getMp() );
statusEffectAdd->data().Tp = static_cast< uint16_t >( getTp() );
statusEffectAdd->data().HpMax = getMaxHp();
statusEffectAdd->data().MpMax = static_cast< uint16_t >( getMaxMp() );
statusEffectAdd->data().ClassJob = static_cast< uint8_t >( getClass() );
statusEffectAdd->data().StatusCount = 1;
statusEffectAdd->data().unknown_E0 = 0xE0;
// set all status sources to u32 invalid game obj
// todo: chara status effect map should be filled instead, since hudparam also uses invalid gameobj
for( int i = 0; i < 4; ++i )
{
statusEffectAdd->data().Status[ i ].Source = INVALID_GAME_OBJECT_ID;
}
auto& status = statusEffectAdd->data().Status[ 0 ];
status.Source = pEffect->getSrcActorId();
status.Time = static_cast< float >( pEffect->getDuration() ) / 1000;
status.Id = static_cast< uint16_t >( pEffect->getId() );
status.Slot = static_cast< uint8_t >( nextSlot );
status.SystemParam = static_cast< int16_t >( pEffect->getParam() );
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), statusEffectAdd );
} }
/*! \param StatusEffectPtr to be applied to the actor */ /*! \param StatusEffectPtr to be applied to the actor */

View file

@ -72,6 +72,11 @@ uint32_t Sapphire::StatusEffect::StatusEffect::getSrcActorId() const
return m_sourceActor->getId(); return m_sourceActor->getId();
} }
Sapphire::Entity::CharaPtr Sapphire::StatusEffect::StatusEffect::getSrcActor() const
{
return m_sourceActor;
}
uint32_t Sapphire::StatusEffect::StatusEffect::getTargetActorId() const uint32_t Sapphire::StatusEffect::StatusEffect::getTargetActorId() const
{ {
return m_targetActor->getId(); return m_targetActor->getId();
@ -86,25 +91,6 @@ void Sapphire::StatusEffect::StatusEffect::applyStatus()
{ {
m_startTime = Util::getTimeMs(); m_startTime = Util::getTimeMs();
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
// this is only right when an action is being used by the player
// else you probably need to use an actorcontrol
//GamePacketNew< FFXIVIpcEffect > effectPacket( m_sourceActor->getId() );
//effectPacket.data().targetId = m_sourceActor->getId();
//effectPacket.data().actionAnimationId = 3;
//effectPacket.data().unknown_3 = 1;
//effectPacket.data().actionTextId = 3;
//effectPacket.data().unknown_5 = 1;
//effectPacket.data().unknown_6 = 321;
//effectPacket.data().rotation = ( uint16_t ) ( 0x8000 * ( ( m_sourceActor->getPos().getR() + 3.1415926 ) ) / 3.1415926 );
//effectPacket.data().effectTargetId = m_sourceActor->getId();
//effectPacket.data().effects[4].unknown_1 = 17;
//effectPacket.data().effects[4].bonusPercent = 30;
//effectPacket.data().effects[4].param1 = m_id;
//effectPacket.data().effects[4].unknown_5 = 0x80;
//m_sourceActor->sendToInRangeSet( effectPacket, true );
scriptMgr.onStatusReceive( m_targetActor, m_id ); scriptMgr.onStatusReceive( m_targetActor, m_id );
} }
@ -153,3 +139,13 @@ const std::string& Sapphire::StatusEffect::StatusEffect::getName() const
{ {
return m_name; return m_name;
} }
uint8_t Sapphire::StatusEffect::StatusEffect::getSlot() const
{
return m_slot;
}
void Sapphire::StatusEffect::StatusEffect::setSlot( uint8_t slot )
{
m_slot = slot;
}

View file

@ -28,6 +28,7 @@ public:
uint32_t getTickRate() const; uint32_t getTickRate() const;
uint32_t getSrcActorId() const; uint32_t getSrcActorId() const;
Entity::CharaPtr getSrcActor() const;
uint32_t getTargetActorId() const; uint32_t getTargetActorId() const;
@ -47,6 +48,9 @@ public:
const std::string& getName() const; const std::string& getName() const;
uint8_t getSlot() const;
void setSlot( uint8_t slot );
private: private:
uint32_t m_id; uint32_t m_id;
Entity::CharaPtr m_sourceActor; Entity::CharaPtr m_sourceActor;
@ -57,6 +61,7 @@ private:
uint64_t m_lastTick; uint64_t m_lastTick;
uint16_t m_param; uint16_t m_param;
std::string m_name; std::string m_name;
uint8_t m_slot;
std::pair< uint8_t, uint32_t > m_currTickEffect; std::pair< uint8_t, uint32_t > m_currTickEffect;
}; };

View file

@ -6,6 +6,7 @@
#include <WorldServer.h> #include <WorldServer.h>
#include <Service.h> #include <Service.h>
#include <Network/PacketWrappers/WarpPacket.h> #include <Network/PacketWrappers/WarpPacket.h>
#include <StatusEffect/StatusEffect.h>
#include <utility> #include <utility>
@ -39,15 +40,31 @@ void ActionIntegrityTask::execute()
if( inRangePlayers.empty() ) if( inRangePlayers.empty() )
return; return;
auto integrityPacket = makeZonePacket< FFXIVIpcActionIntegrity >( 0 );
auto& data = integrityPacket->data();
integrityPacket->setSourceActor( m_pTarget->getId() );
for( int i = 0; i < 4; ++i )
data.Status[ i ].Source = Common::INVALID_GAME_OBJECT_ID;
int statusIdx = 0;
for( auto& actionResult : m_results ) for( auto& actionResult : m_results )
{ {
if( actionResult && actionResult->getTarget() && actionResult->getTarget()->isAlive() ) if( actionResult && actionResult->getTarget() && actionResult->getTarget()->isAlive() )
actionResult->execute(); actionResult->execute();
if( actionResult->getCalcResultParam().Type == Common::CALC_RESULT_TYPE_SET_STATUS )
{
auto& status = data.Status[ statusIdx++ ];
auto pEffect = actionResult->getStatusEffect();
status.Source = pEffect->getSrcActorId();
status.Time = static_cast< float >( pEffect->getDuration() ) / 1000;
status.Id = static_cast< uint16_t >( pEffect->getId() );
status.Slot = static_cast< uint8_t >( pEffect->getSlot() );
status.SystemParam = static_cast< int16_t >( pEffect->getParam() );
}
} }
auto integrityPacket = makeZonePacket< FFXIVIpcActionIntegrity >( 0 );
auto& data = integrityPacket->data();
integrityPacket->setSourceActor( m_pTarget->getId() );
data.Hp = m_pTarget->getHp(); data.Hp = m_pTarget->getHp();
data.HpMax = m_pTarget->getMaxHp(); data.HpMax = m_pTarget->getMaxHp();
data.Mp = m_pTarget->getMp(); data.Mp = m_pTarget->getMp();
@ -55,6 +72,9 @@ void ActionIntegrityTask::execute()
data.Tp = m_pTarget->getTp(); data.Tp = m_pTarget->getTp();
data.ResultId = m_resultId; data.ResultId = m_resultId;
data.Target = m_pTarget->getId(); data.Target = m_pTarget->getId();
data.StatusCount = statusIdx;
data.ClassJob = static_cast< uint8_t >( m_pTarget->getClass() );
data.unknown_E0 = 0xE0;
server.queueForPlayers( inRangePlayers, integrityPacket ); server.queueForPlayers( inRangePlayers, integrityPacket );