1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-08 03:37:45 +00:00

Cleaned up bnppc code, fixed effect packet

This commit is contained in:
Mordred 2019-01-19 01:15:17 +01:00
parent 77c4403a2c
commit 38acccea57
7 changed files with 121 additions and 124 deletions

View file

@ -531,8 +531,7 @@ namespace Sapphire::Common
Unaspected = 7 // Doesn't imply magical unaspected damage - could be unaspected physical Unaspected = 7 // Doesn't imply magical unaspected damage - could be unaspected physical
}; };
enum class ActionType : enum class ActionType : int8_t
int8_t
{ {
WeaponOverride = -1, // Needs more investigation (takes the damage type of the equipped weapon)? WeaponOverride = -1, // Needs more investigation (takes the damage type of the equipped weapon)?
Unknown_0 = 0, Unknown_0 = 0,
@ -546,8 +545,7 @@ namespace Sapphire::Common
LimitBreak = 8, LimitBreak = 8,
}; };
enum ActionEffectType : enum ActionEffectType : uint8_t
uint8_t
{ {
Nothing = 0, Nothing = 0,
Miss = 1, Miss = 1,
@ -568,8 +566,7 @@ namespace Sapphire::Common
Mount = 38 Mount = 38
}; };
enum class ActionHitSeverityType : enum class ActionHitSeverityType : uint8_t
uint8_t
{ {
NormalDamage = 0, NormalDamage = 0,
CritHeal = 0, CritHeal = 0,
@ -579,16 +576,14 @@ namespace Sapphire::Common
CritDirectHitDamage = 3 CritDirectHitDamage = 3
}; };
enum ActionEffectDisplayType : enum ActionEffectDisplayType : uint8_t
uint8_t
{ {
HideActionName = 0, HideActionName = 0,
ShowActionName = 1, ShowActionName = 1,
ShowItemName = 2, ShowItemName = 2,
}; };
enum class ActionCollisionType : enum class ActionCollisionType : uint8_t
uint8_t
{ {
None, None,
SingleTarget, SingleTarget,
@ -601,32 +596,28 @@ namespace Sapphire::Common
Unknown3 Unknown3
}; };
enum HandleActionType : enum HandleActionType : uint8_t
uint8_t
{ {
Event, Event,
Spell, Spell,
Teleport Teleport
}; };
enum HandleSkillType : enum HandleSkillType : uint8_t
uint8_t
{ {
StdDamage, StdDamage,
StdHeal, StdHeal,
StdDot, StdDot,
}; };
enum InvincibilityType : enum InvincibilityType : uint8_t
uint8_t
{ {
InvincibilityNone, InvincibilityNone,
InvincibilityRefill, InvincibilityRefill,
InvincibilityStayAlive, InvincibilityStayAlive,
}; };
enum PlayerStateFlag : enum PlayerStateFlag : uint8_t
uint8_t
{ {
HideUILockChar = 0, // as the name suggests, hides the ui and logs the char... HideUILockChar = 0, // as the name suggests, hides the ui and logs the char...
InCombat = 1, // in Combat, locks gearchange/return/teleport InCombat = 1, // in Combat, locks gearchange/return/teleport
@ -642,8 +633,7 @@ namespace Sapphire::Common
}; };
enum struct FateStatus : enum struct FateStatus : uint8_t
uint8_t
{ {
Active = 2, Active = 2,
Inactive = 4, Inactive = 4,
@ -651,8 +641,7 @@ namespace Sapphire::Common
Completed = 8, Completed = 8,
}; };
enum struct ChatType : enum struct ChatType : uint16_t
uint16_t
{ {
LogKindError, LogKindError,
ServerDebug, ServerDebug,

View file

@ -402,34 +402,48 @@ struct EffectEntry
struct EffectHeader struct EffectHeader
{ {
uint64_t animationTargetId; // who the animation targets uint64_t animationTargetId; // who the animation targets
uint32_t actionId; // what the casting player casts, shown in battle log/ui uint32_t actionId; // what the casting player casts, shown in battle log/ui
uint32_t globalEffectCounter; // seems to only increment on retail? uint32_t globalEffectCounter; // seems to only increment on retail?
float animationLockTime; // maybe? doesn't seem to do anything
float animationLockTime; // maybe? doesn't seem to do anything
uint32_t someTargetId; // always 00 00 00 E0, 0x0E000000 is the internal def for INVALID TARGET ID uint32_t someTargetId; // always 00 00 00 E0, 0x0E000000 is the internal def for INVALID TARGET ID
uint16_t hiddenAnimation; // if 0, always shows animation, otherwise hides it. counts up by 1 for each animation skipped on a caster uint16_t hiddenAnimation; // if 0, always shows animation, otherwise hides it. counts up by 1 for each animation skipped on a caster
uint16_t rotation; uint16_t rotation;
uint16_t actionAnimationId; // the animation that is played by the casting character uint16_t actionAnimationId; // the animation that is played by the casting character
uint8_t unknown1E; // can be 0,1,2 - maybe other values? - doesn't do anything? uint8_t variation; // variation in the animation
Common::ActionEffectDisplayType effectDisplayType; Common::ActionEffectDisplayType effectDisplayType;
uint8_t unknown20; // is read by handler, runs code which gets the LODWORD of animationLockTime (wtf?) uint8_t unknown20; // is read by handler, runs code which gets the LODWORD of animationLockTime (wtf?)
uint8_t effectCount; // ignores effects if 0, otherwise parses all of them uint8_t effectCount; // ignores effects if 0, otherwise parses all of them
uint16_t padding_21;
uint32_t padding_22[2];
}; };
struct FFXIVIpcEffect : struct FFXIVIpcEffect : FFXIVIpcBasePacket< Effect >
FFXIVIpcBasePacket< Effect >
{ {
EffectHeader header; uint64_t animationTargetId; // who the animation targets
EffectEntry effects[8]; uint32_t actionId; // what the casting player casts, shown in battle log/ui
uint32_t globalEffectCounter; // seems to only increment on retail?
float animationLockTime; // maybe? doesn't seem to do anything
uint32_t someTargetId; // always 00 00 00 E0, 0x0E000000 is the internal def for INVALID TARGET ID
uint16_t hiddenAnimation; // if 0, always shows animation, otherwise hides it. counts up by 1 for each animation skipped on a caster
uint16_t rotation;
uint16_t actionAnimationId; // the animation that is played by the casting character
uint8_t variation; // variation in the animation
Common::ActionEffectDisplayType effectDisplayType;
uint8_t unknown20; // is read by handler, runs code which gets the LODWORD of animationLockTime (wtf?)
uint8_t effectCount; // ignores effects if 0, otherwise parses all of them
uint16_t padding_21;
uint16_t padding_22[3];
uint8_t effects[8*8];
uint16_t padding_6A[3]; uint16_t padding_6A[3];

View file

@ -180,13 +180,13 @@ void Sapphire::Entity::BNpc::hateListClear()
auto it = m_hateList.begin(); auto it = m_hateList.begin();
for( auto listEntry : m_hateList ) for( auto listEntry : m_hateList )
{ {
//if( isInRangeSet( listEntry->m_pActor ) ) if( isInRangeSet( listEntry->m_pChara ) )
//deaggro( listEntry->m_pActor ); deaggro( listEntry->m_pChara );
} }
m_hateList.clear(); m_hateList.clear();
} }
Sapphire::Entity::ActorPtr Sapphire::Entity::BNpc::hateListGetHighest() Sapphire::Entity::CharaPtr Sapphire::Entity::BNpc::hateListGetHighest()
{ {
auto it = m_hateList.begin(); auto it = m_hateList.begin();
uint32_t maxHate = 0; uint32_t maxHate = 0;
@ -201,25 +201,25 @@ Sapphire::Entity::ActorPtr Sapphire::Entity::BNpc::hateListGetHighest()
} }
if( entry && maxHate != 0 ) if( entry && maxHate != 0 )
return entry->m_pActor; return entry->m_pChara;
return nullptr; return nullptr;
} }
void Sapphire::Entity::BNpc::hateListAdd( Sapphire::Entity::ActorPtr pActor, int32_t hateAmount ) void Sapphire::Entity::BNpc::hateListAdd( Sapphire::Entity::CharaPtr pChara, int32_t hateAmount )
{ {
auto hateEntry = std::make_shared< HateListEntry >(); auto hateEntry = std::make_shared< HateListEntry >();
hateEntry->m_hateAmount = hateAmount; hateEntry->m_hateAmount = hateAmount;
hateEntry->m_pActor = pActor; hateEntry->m_pChara = pChara;
m_hateList.insert( hateEntry ); m_hateList.insert( hateEntry );
} }
void Sapphire::Entity::BNpc::hateListUpdate( Sapphire::Entity::ActorPtr pActor, int32_t hateAmount ) void Sapphire::Entity::BNpc::hateListUpdate( Sapphire::Entity::CharaPtr pChara, int32_t hateAmount )
{ {
for( auto listEntry : m_hateList ) for( auto listEntry : m_hateList )
{ {
if( listEntry->m_pActor == pActor ) if( listEntry->m_pChara == pChara )
{ {
listEntry->m_hateAmount += hateAmount; listEntry->m_hateAmount += hateAmount;
return; return;
@ -228,21 +228,21 @@ void Sapphire::Entity::BNpc::hateListUpdate( Sapphire::Entity::ActorPtr pActor,
auto hateEntry = std::make_shared< HateListEntry >(); auto hateEntry = std::make_shared< HateListEntry >();
hateEntry->m_hateAmount = hateAmount; hateEntry->m_hateAmount = hateAmount;
hateEntry->m_pActor = pActor; hateEntry->m_pChara = pChara;
m_hateList.insert( hateEntry ); m_hateList.insert( hateEntry );
} }
void Sapphire::Entity::BNpc::hateListRemove( Sapphire::Entity::ActorPtr pActor ) void Sapphire::Entity::BNpc::hateListRemove( Sapphire::Entity::CharaPtr pChara )
{ {
for( auto listEntry : m_hateList ) for( auto listEntry : m_hateList )
{ {
if( listEntry->m_pActor == pActor ) if( listEntry->m_pChara == pChara )
{ {
m_hateList.erase( listEntry ); m_hateList.erase( listEntry );
if( pActor->isPlayer() ) if( pChara->isPlayer() )
{ {
PlayerPtr tmpPlayer = pActor->getAsPlayer(); PlayerPtr tmpPlayer = pChara->getAsPlayer();
//tmpPlayer->onMobDeaggro( getAsBattleNpc() ); //tmpPlayer->onMobDeaggro( getAsBattleNpc() );
} }
return; return;
@ -250,47 +250,51 @@ void Sapphire::Entity::BNpc::hateListRemove( Sapphire::Entity::ActorPtr pActor )
} }
} }
bool Sapphire::Entity::BNpc::hateListHasActor( Sapphire::Entity::ActorPtr pActor ) bool Sapphire::Entity::BNpc::hateListHasActor( Sapphire::Entity::CharaPtr pChara )
{ {
for( auto listEntry : m_hateList ) for( auto listEntry : m_hateList )
{ {
if( listEntry->m_pActor == pActor ) if( listEntry->m_pChara == pChara )
return true; return true;
} }
return false; return false;
} }
void Sapphire::Entity::BNpc::aggro( Sapphire::Entity::ActorPtr pActor ) void Sapphire::Entity::BNpc::aggro( Sapphire::Entity::CharaPtr pChara )
{ {
m_lastAttack = Util::getTimeMs(); m_lastAttack = Util::getTimeMs();
hateListUpdate( pActor, 1 ); hateListUpdate( pChara, 1 );
changeTarget( pActor->getId() ); changeTarget( pChara->getId() );
setStance( Stance::Active ); setStance( Stance::Active );
m_state = BNpcState::Combat; m_state = BNpcState::Combat;
if( pActor->isPlayer() ) if( pChara->isPlayer() )
{ {
PlayerPtr tmpPlayer = pActor->getAsPlayer(); PlayerPtr tmpPlayer = pChara->getAsPlayer();
tmpPlayer->queuePacket( makeActorControl142( getId(), ActorControlType::ToggleWeapon, 0, 1, 1 ) ); tmpPlayer->queuePacket( makeActorControl142( getId(), ActorControlType::ToggleWeapon, 0, 1, 1 ) );
//tmpPlayer->onMobAggro( getAsBattleNpc() ); //tmpPlayer->onMobAggro( getAsBattleNpc() );
} }
} }
void Sapphire::Entity::BNpc::deaggro( Sapphire::Entity::ActorPtr pActor ) void Sapphire::Entity::BNpc::deaggro( Sapphire::Entity::CharaPtr pChara )
{ {
if( !hateListHasActor( pActor ) ) if( !hateListHasActor( pChara ) )
hateListRemove( pActor ); hateListRemove( pChara );
if( pActor->isPlayer() ) if( pChara->isPlayer() )
{ {
PlayerPtr tmpPlayer = pActor->getAsPlayer(); PlayerPtr tmpPlayer = pChara->getAsPlayer();
//tmpPlayer->onMobDeaggro( getAsBattleNpc() ); //tmpPlayer->onMobDeaggro( getAsBattleNpc() );
} }
} }
void Sapphire::Entity::BNpc::update( int64_t currTime ) void Sapphire::Entity::BNpc::update( int64_t currTime )
{ {
const uint8_t minActorDistance = 4;
const uint8_t aggroRange = 8;
const uint8_t maxDistanceToOrigin = 30;
switch( m_state ) switch( m_state )
{ {
case BNpcState::Retreat: case BNpcState::Retreat:
@ -302,52 +306,47 @@ void Sapphire::Entity::BNpc::update( int64_t currTime )
case BNpcState::Idle: case BNpcState::Idle:
{ {
CharaPtr pClosestActor = getClosestChara(); CharaPtr pClosestChara = getClosestChara();
if( ( pClosestActor != nullptr ) && pClosestActor->isAlive() ) if( pClosestChara && pClosestChara->isAlive() )
{ {
auto distance = Util::distance( getPos().x, getPos().y, getPos().z, auto distance = Util::distance( getPos().x, getPos().y, getPos().z,
pClosestActor->getPos().x, pClosestChara->getPos().x,
pClosestActor->getPos().y, pClosestChara->getPos().y,
pClosestActor->getPos().z ); pClosestChara->getPos().z );
if( distance < 8 && pClosestActor->isPlayer() ) if( distance < aggroRange && pClosestChara->isPlayer() )
aggro( pClosestActor ); aggro( pClosestChara );
//if( distance < 8 && getbehavior() == 2 ) //if( distance < aggroRange && getbehavior() == 2 )
// aggro( pClosestActor ); // aggro( pClosestActor );
} }
} }
case BNpcState::Combat: case BNpcState::Combat:
{ {
auto pActor = hateListGetHighest(); auto pHatedActor = hateListGetHighest();
if( !pActor ) if( !pHatedActor )
return; return;
auto pClosestActor = pActor->getAsChara();
auto distanceOrig = Util::distance( getPos().x, getPos().y, getPos().z, auto distanceOrig = Util::distance( getPos().x, getPos().y, getPos().z,
m_spawnPos.x, m_spawnPos.x,
m_spawnPos.y, m_spawnPos.y,
m_spawnPos.z ); m_spawnPos.z );
if( pClosestActor && !pClosestActor->isAlive() ) if( pHatedActor && !pHatedActor->isAlive() )
{ {
hateListRemove( pClosestActor ); hateListRemove( pHatedActor );
pActor = hateListGetHighest(); pHatedActor = hateListGetHighest();
if( pActor )
pClosestActor = pActor->getAsChara();
else
pClosestActor.reset();
} }
if( pClosestActor != nullptr ) if( pHatedActor )
{ {
auto distance = Util::distance( getPos().x, getPos().y, getPos().z, auto distance = Util::distance( getPos().x, getPos().y, getPos().z,
pClosestActor->getPos().x, pHatedActor->getPos().x,
pClosestActor->getPos().y, pHatedActor->getPos().y,
pClosestActor->getPos().z ); pHatedActor->getPos().z );
if( distanceOrig > 30 ) if( distanceOrig > maxDistanceToOrigin )
{ {
hateListClear(); hateListClear();
changeTarget( INVALID_GAME_OBJECT_ID ); changeTarget( INVALID_GAME_OBJECT_ID );
@ -357,14 +356,14 @@ void Sapphire::Entity::BNpc::update( int64_t currTime )
break; break;
} }
if( distance > 4 ) if( distance > minActorDistance )
moveTo( pClosestActor->getPos() ); moveTo( pHatedActor->getPos() );
else else
{ {
if( face( pClosestActor->getPos() ) ) if( face( pHatedActor->getPos() ) )
sendPositionUpdate(); sendPositionUpdate();
// in combat range. ATTACK! // in combat range. ATTACK!
autoAttack( pClosestActor ); autoAttack( pHatedActor );
} }
} }
else else

View file

@ -16,7 +16,7 @@ namespace Sapphire::Entity
typedef struct typedef struct
{ {
uint32_t m_hateAmount; uint32_t m_hateAmount;
ActorPtr m_pActor; CharaPtr m_pChara;
} HateListEntry; } HateListEntry;
enum class BNpcState enum class BNpcState
@ -67,14 +67,14 @@ namespace Sapphire::Entity
void setState( BNpcState state ); void setState( BNpcState state );
void hateListClear(); void hateListClear();
ActorPtr hateListGetHighest(); CharaPtr hateListGetHighest();
void hateListAdd( ActorPtr pActor, int32_t hateAmount ); void hateListAdd( CharaPtr pChara, int32_t hateAmount );
void hateListUpdate( ActorPtr pActor, int32_t hateAmount ); void hateListUpdate( CharaPtr pChara, int32_t hateAmount );
void hateListRemove( ActorPtr pActor ); void hateListRemove( CharaPtr pChara );
bool hateListHasActor( ActorPtr pActor ); bool hateListHasActor( CharaPtr pChara );
void aggro( ActorPtr pActor ); void aggro( CharaPtr pChara );
void deaggro( ActorPtr pActor ); void deaggro( CharaPtr pChara );
void update( int64_t currTime ) override; void update( int64_t currTime ) override;

View file

@ -38,7 +38,7 @@ Sapphire::Entity::Chara::Chara( ObjKind type, FrameworkPtr pFw ) :
Actor( type ), Actor( type ),
m_pose( 0 ), m_pose( 0 ),
m_targetId( INVALID_GAME_OBJECT_ID ), m_targetId( INVALID_GAME_OBJECT_ID ),
m_pFw( pFw ) m_pFw( std::move( std::move( pFw ) ) )
{ {
// initialize the free slot queue // initialize the free slot queue
for( uint8_t i = 0; i < MAX_STATUS_EFFECTS; i++ ) for( uint8_t i = 0; i < MAX_STATUS_EFFECTS; i++ )
@ -48,8 +48,7 @@ Sapphire::Entity::Chara::Chara( ObjKind type, FrameworkPtr pFw ) :
} }
Sapphire::Entity::Chara::~Chara() Sapphire::Entity::Chara::~Chara()
{ = default;
}
/*! \return the actors name */ /*! \return the actors name */
std::string Sapphire::Entity::Chara::getName() const std::string Sapphire::Entity::Chara::getName() const
@ -375,7 +374,7 @@ Sapphire::Action::ActionPtr Sapphire::Entity::Chara::getCurrentAction() const
/*! \param ActionPtr of the action to be registered */ /*! \param ActionPtr of the action to be registered */
void Sapphire::Entity::Chara::setCurrentAction( Sapphire::Action::ActionPtr pAction ) void Sapphire::Entity::Chara::setCurrentAction( Sapphire::Action::ActionPtr pAction )
{ {
m_pCurrentAction = pAction; m_pCurrentAction = std::move( pAction );
} }
/*! /*!
@ -398,36 +397,31 @@ void Sapphire::Entity::Chara::autoAttack( CharaPtr pTarget )
m_lastAttack = tick; m_lastAttack = tick;
srand( static_cast< uint32_t >( tick ) ); srand( static_cast< uint32_t >( tick ) );
uint16_t damage = static_cast< uint16_t >( 10 + rand() % 12 ); auto damage = static_cast< uint16_t >( 10 + rand() % 12 );
uint32_t variation = static_cast< uint32_t >( 0 + rand() % 4 );
auto effectPacket = std::make_shared< Server::EffectPacket >( getId(), pTarget->getId(), 0x336 ); auto effectPacket = std::make_shared< Server::EffectPacket >( getId(), pTarget->getId(), 7 );
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) ); effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
Server::EffectEntry effectEntry{}; Server::EffectEntry effectEntry{};
effectEntry.value = damage; effectEntry.value = damage;
effectEntry.effectType = ActionEffectType::Damage; effectEntry.effectType = ActionEffectType::Damage;
effectEntry.hitSeverity = static_cast< ActionHitSeverityType >( variation ); effectEntry.hitSeverity = ActionHitSeverityType::NormalDamage;
effectPacket->addEffect( effectEntry ); effectPacket->addEffect( effectEntry );
sendToInRangeSet( effectPacket ); sendToInRangeSet( effectPacket );
if( isPlayer() )
getAsPlayer()->queuePacket( effectPacket );
pTarget->takeDamage( damage ); pTarget->takeDamage( damage );
} }
} }
/*! /*!
ChaiScript Skill Handler. Skill Handler.
\param GamePacketPtr to send \param GamePacketPtr to send
\param bool should be send to self? \param bool should be send to self?
*/ */
void Sapphire::Entity::Chara::handleScriptSkill( uint32_t type, uint16_t actionId, uint64_t param1, void Sapphire::Entity::Chara::handleScriptSkill( uint32_t type, uint16_t actionId, uint64_t param1,
uint64_t param2, Entity::Chara& target ) uint64_t param2, Entity::Chara& target )
{ {
auto pExdData = m_pFw->get< Data::ExdDataGenerated >(); auto pExdData = m_pFw->get< Data::ExdDataGenerated >();
if( isPlayer() ) if( isPlayer() )
@ -534,7 +528,7 @@ void Sapphire::Entity::Chara::handleScriptSkill( uint32_t type, uint16_t actionI
auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeActors( true ), auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeActors( true ),
actionInfoPtr, TargetFilter::Allies ); actionInfoPtr, TargetFilter::Allies );
for( auto pHitActor : actorsCollided ) for( const auto& pHitActor : actorsCollided )
{ {
effectPacket->setTargetActor( pHitActor->getId() ); effectPacket->setTargetActor( pHitActor->getId() );
@ -599,7 +593,7 @@ void Sapphire::Entity::Chara::addStatusEffectById( uint32_t id, int32_t duration
/*! \param StatusEffectPtr to be applied to the actor */ /*! \param StatusEffectPtr to be applied to the actor */
void Sapphire::Entity::Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, void Sapphire::Entity::Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source,
uint16_t param ) uint16_t param )
{ {
if( hasStatusEffect( id ) ) if( hasStatusEffect( id ) )
return; return;
@ -781,8 +775,6 @@ void Sapphire::Entity::Chara::updateStatusEffects()
bool Sapphire::Entity::Chara::hasStatusEffect( uint32_t id ) bool Sapphire::Entity::Chara::hasStatusEffect( uint32_t id )
{ {
if( m_statusEffectMap.find( id ) != m_statusEffectMap.end() ) return m_statusEffectMap.find( id ) != m_statusEffectMap.end();
return true;
return false;
} }

View file

@ -1474,7 +1474,7 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget )
auto effectPacket = std::make_shared< Server::EffectPacket >( getId(), pTarget->getId(), 8 ); auto effectPacket = std::make_shared< Server::EffectPacket >( getId(), pTarget->getId(), 8 );
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) ); effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
Server::EffectEntry entry; Server::EffectEntry entry{};
entry.value = damage; entry.value = damage;
entry.effectType = Common::ActionEffectType::Damage; entry.effectType = Common::ActionEffectType::Damage;
entry.hitSeverity = Common::ActionHitSeverityType::NormalDamage; entry.hitSeverity = Common::ActionHitSeverityType::NormalDamage;
@ -1488,7 +1488,7 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget )
auto effectPacket = std::make_shared< Server::EffectPacket >( getId(), pTarget->getId(), 7 ); auto effectPacket = std::make_shared< Server::EffectPacket >( getId(), pTarget->getId(), 7 );
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) ); effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
Server::EffectEntry entry; Server::EffectEntry entry{};
entry.value = damage; entry.value = damage;
entry.effectType = Common::ActionEffectType::Damage; entry.effectType = Common::ActionEffectType::Damage;
entry.hitSeverity = Common::ActionHitSeverityType::NormalDamage; entry.hitSeverity = Common::ActionHitSeverityType::NormalDamage;

View file

@ -17,25 +17,28 @@ namespace Sapphire::Network::Packets::Server
EffectPacket( uint64_t sourceId, uint32_t targetId, uint32_t actionId ) : EffectPacket( uint64_t sourceId, uint32_t targetId, uint32_t actionId ) :
ZoneChannelPacket< FFXIVIpcEffect >( static_cast< uint32_t >( sourceId ), targetId ) ZoneChannelPacket< FFXIVIpcEffect >( static_cast< uint32_t >( sourceId ), targetId )
{ {
m_data.header.actionId = actionId; m_data.effectCount = 0;
m_data.header.actionAnimationId = static_cast< uint16_t >( actionId ); m_data.actionId = actionId;
m_data.actionAnimationId = static_cast< uint16_t >( actionId );
m_data.header.animationTargetId = targetId; m_data.animationTargetId = targetId;
m_data.effectTargetId = targetId; m_data.effectTargetId = targetId;
m_data.header.effectDisplayType = Common::ActionEffectDisplayType::ShowActionName; m_data.effectDisplayType = Common::ActionEffectDisplayType::ShowActionName;
} }
void addEffect( const Server::EffectEntry& effect ) void addEffect( const Server::EffectEntry& effect )
{ {
assert( m_data.header.effectCount <= 8 ); assert( m_data.effectCount <= 8 );
std::memcpy( &m_data.effects[ m_data.header.effectCount++ ], &effect, sizeof( Server::EffectEntry ) ); std::memset( m_data.effects, 0, sizeof( Server::EffectEntry ) * 8 );
std::memcpy( &m_data.effects[ m_data.effectCount * 8 ], &effect, sizeof( Server::EffectEntry ) );
m_data.effectCount++;
} }
void setAnimationId( uint16_t animationId ) void setAnimationId( uint16_t animationId )
{ {
m_data.header.actionAnimationId = animationId; m_data.actionAnimationId = animationId;
} }
void setEffectFlags( uint32_t effectFlags ) void setEffectFlags( uint32_t effectFlags )
@ -45,12 +48,12 @@ namespace Sapphire::Network::Packets::Server
void setRotation( uint16_t rotation ) void setRotation( uint16_t rotation )
{ {
m_data.header.rotation = rotation; m_data.rotation = rotation;
} }
void setTargetActor( const uint32_t targetId ) void setTargetActor( const uint32_t targetId )
{ {
m_data.header.animationTargetId = targetId; m_data.animationTargetId = targetId;
m_data.effectTargetId = targetId; m_data.effectTargetId = targetId;
FFXIVPacketBase::setTargetActor( targetId ); FFXIVPacketBase::setTargetActor( targetId );