diff --git a/src/common/Common.h b/src/common/Common.h index c688d088..6dfc5e70 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -531,8 +531,7 @@ namespace Sapphire::Common Unaspected = 7 // Doesn't imply magical unaspected damage - could be unaspected physical }; - enum class ActionType : - int8_t + enum class ActionType : int8_t { WeaponOverride = -1, // Needs more investigation (takes the damage type of the equipped weapon)? Unknown_0 = 0, @@ -546,8 +545,7 @@ namespace Sapphire::Common LimitBreak = 8, }; - enum ActionEffectType : - uint8_t + enum ActionEffectType : uint8_t { Nothing = 0, Miss = 1, @@ -568,8 +566,7 @@ namespace Sapphire::Common Mount = 38 }; - enum class ActionHitSeverityType : - uint8_t + enum class ActionHitSeverityType : uint8_t { NormalDamage = 0, CritHeal = 0, @@ -579,16 +576,14 @@ namespace Sapphire::Common CritDirectHitDamage = 3 }; - enum ActionEffectDisplayType : - uint8_t + enum ActionEffectDisplayType : uint8_t { HideActionName = 0, ShowActionName = 1, ShowItemName = 2, }; - enum class ActionCollisionType : - uint8_t + enum class ActionCollisionType : uint8_t { None, SingleTarget, @@ -601,32 +596,28 @@ namespace Sapphire::Common Unknown3 }; - enum HandleActionType : - uint8_t + enum HandleActionType : uint8_t { Event, Spell, Teleport }; - enum HandleSkillType : - uint8_t + enum HandleSkillType : uint8_t { StdDamage, StdHeal, StdDot, }; - enum InvincibilityType : - uint8_t + enum InvincibilityType : uint8_t { InvincibilityNone, InvincibilityRefill, InvincibilityStayAlive, }; - enum PlayerStateFlag : - uint8_t + enum PlayerStateFlag : uint8_t { HideUILockChar = 0, // as the name suggests, hides the ui and logs the char... InCombat = 1, // in Combat, locks gearchange/return/teleport @@ -642,8 +633,7 @@ namespace Sapphire::Common }; - enum struct FateStatus : - uint8_t + enum struct FateStatus : uint8_t { Active = 2, Inactive = 4, @@ -651,8 +641,7 @@ namespace Sapphire::Common Completed = 8, }; - enum struct ChatType : - uint16_t + enum struct ChatType : uint16_t { LogKindError, ServerDebug, diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index d4402fec..c1c3cf93 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -402,34 +402,48 @@ struct EffectEntry struct EffectHeader { uint64_t animationTargetId; // who the animation targets + 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 + 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 unknown1E; // can be 0,1,2 - maybe other values? - doesn't do anything? - + 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; - uint32_t padding_22[2]; }; -struct FFXIVIpcEffect : - FFXIVIpcBasePacket< Effect > +struct FFXIVIpcEffect : 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]; diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index b9250e66..d95e9056 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -180,13 +180,13 @@ void Sapphire::Entity::BNpc::hateListClear() auto it = m_hateList.begin(); for( auto listEntry : m_hateList ) { - //if( isInRangeSet( listEntry->m_pActor ) ) - //deaggro( listEntry->m_pActor ); + if( isInRangeSet( listEntry->m_pChara ) ) + deaggro( listEntry->m_pChara ); } m_hateList.clear(); } -Sapphire::Entity::ActorPtr Sapphire::Entity::BNpc::hateListGetHighest() +Sapphire::Entity::CharaPtr Sapphire::Entity::BNpc::hateListGetHighest() { auto it = m_hateList.begin(); uint32_t maxHate = 0; @@ -201,25 +201,25 @@ Sapphire::Entity::ActorPtr Sapphire::Entity::BNpc::hateListGetHighest() } if( entry && maxHate != 0 ) - return entry->m_pActor; + return entry->m_pChara; 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 >(); hateEntry->m_hateAmount = hateAmount; - hateEntry->m_pActor = pActor; + hateEntry->m_pChara = pChara; 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 ) { - if( listEntry->m_pActor == pActor ) + if( listEntry->m_pChara == pChara ) { listEntry->m_hateAmount += hateAmount; return; @@ -228,21 +228,21 @@ void Sapphire::Entity::BNpc::hateListUpdate( Sapphire::Entity::ActorPtr pActor, auto hateEntry = std::make_shared< HateListEntry >(); hateEntry->m_hateAmount = hateAmount; - hateEntry->m_pActor = pActor; + hateEntry->m_pChara = pChara; 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 ) { - if( listEntry->m_pActor == pActor ) + if( listEntry->m_pChara == pChara ) { m_hateList.erase( listEntry ); - if( pActor->isPlayer() ) + if( pChara->isPlayer() ) { - PlayerPtr tmpPlayer = pActor->getAsPlayer(); + PlayerPtr tmpPlayer = pChara->getAsPlayer(); //tmpPlayer->onMobDeaggro( getAsBattleNpc() ); } 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 ) { - if( listEntry->m_pActor == pActor ) + if( listEntry->m_pChara == pChara ) return true; } return false; } -void Sapphire::Entity::BNpc::aggro( Sapphire::Entity::ActorPtr pActor ) +void Sapphire::Entity::BNpc::aggro( Sapphire::Entity::CharaPtr pChara ) { m_lastAttack = Util::getTimeMs(); - hateListUpdate( pActor, 1 ); + hateListUpdate( pChara, 1 ); - changeTarget( pActor->getId() ); + changeTarget( pChara->getId() ); setStance( Stance::Active ); 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->onMobAggro( getAsBattleNpc() ); } } -void Sapphire::Entity::BNpc::deaggro( Sapphire::Entity::ActorPtr pActor ) +void Sapphire::Entity::BNpc::deaggro( Sapphire::Entity::CharaPtr pChara ) { - if( !hateListHasActor( pActor ) ) - hateListRemove( pActor ); + if( !hateListHasActor( pChara ) ) + hateListRemove( pChara ); - if( pActor->isPlayer() ) + if( pChara->isPlayer() ) { - PlayerPtr tmpPlayer = pActor->getAsPlayer(); + PlayerPtr tmpPlayer = pChara->getAsPlayer(); //tmpPlayer->onMobDeaggro( getAsBattleNpc() ); } } 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 ) { case BNpcState::Retreat: @@ -302,52 +306,47 @@ void Sapphire::Entity::BNpc::update( int64_t currTime ) 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, - pClosestActor->getPos().x, - pClosestActor->getPos().y, - pClosestActor->getPos().z ); + pClosestChara->getPos().x, + pClosestChara->getPos().y, + pClosestChara->getPos().z ); - if( distance < 8 && pClosestActor->isPlayer() ) - aggro( pClosestActor ); - //if( distance < 8 && getbehavior() == 2 ) + if( distance < aggroRange && pClosestChara->isPlayer() ) + aggro( pClosestChara ); + //if( distance < aggroRange && getbehavior() == 2 ) // aggro( pClosestActor ); } } case BNpcState::Combat: { - auto pActor = hateListGetHighest(); - if( !pActor ) + auto pHatedActor = hateListGetHighest(); + if( !pHatedActor ) return; - auto pClosestActor = pActor->getAsChara(); auto distanceOrig = Util::distance( getPos().x, getPos().y, getPos().z, m_spawnPos.x, m_spawnPos.y, m_spawnPos.z ); - if( pClosestActor && !pClosestActor->isAlive() ) + if( pHatedActor && !pHatedActor->isAlive() ) { - hateListRemove( pClosestActor ); - pActor = hateListGetHighest(); - if( pActor ) - pClosestActor = pActor->getAsChara(); - else - pClosestActor.reset(); + hateListRemove( pHatedActor ); + pHatedActor = hateListGetHighest(); } - if( pClosestActor != nullptr ) + if( pHatedActor ) { auto distance = Util::distance( getPos().x, getPos().y, getPos().z, - pClosestActor->getPos().x, - pClosestActor->getPos().y, - pClosestActor->getPos().z ); + pHatedActor->getPos().x, + pHatedActor->getPos().y, + pHatedActor->getPos().z ); - if( distanceOrig > 30 ) + if( distanceOrig > maxDistanceToOrigin ) { hateListClear(); changeTarget( INVALID_GAME_OBJECT_ID ); @@ -357,14 +356,14 @@ void Sapphire::Entity::BNpc::update( int64_t currTime ) break; } - if( distance > 4 ) - moveTo( pClosestActor->getPos() ); + if( distance > minActorDistance ) + moveTo( pHatedActor->getPos() ); else { - if( face( pClosestActor->getPos() ) ) + if( face( pHatedActor->getPos() ) ) sendPositionUpdate(); // in combat range. ATTACK! - autoAttack( pClosestActor ); + autoAttack( pHatedActor ); } } else diff --git a/src/world/Actor/BNpc.h b/src/world/Actor/BNpc.h index 59cc750b..65bd166a 100644 --- a/src/world/Actor/BNpc.h +++ b/src/world/Actor/BNpc.h @@ -16,7 +16,7 @@ namespace Sapphire::Entity typedef struct { uint32_t m_hateAmount; - ActorPtr m_pActor; + CharaPtr m_pChara; } HateListEntry; enum class BNpcState @@ -67,14 +67,14 @@ namespace Sapphire::Entity void setState( BNpcState state ); void hateListClear(); - ActorPtr hateListGetHighest(); - void hateListAdd( ActorPtr pActor, int32_t hateAmount ); - void hateListUpdate( ActorPtr pActor, int32_t hateAmount ); - void hateListRemove( ActorPtr pActor ); - bool hateListHasActor( ActorPtr pActor ); + CharaPtr hateListGetHighest(); + void hateListAdd( CharaPtr pChara, int32_t hateAmount ); + void hateListUpdate( CharaPtr pChara, int32_t hateAmount ); + void hateListRemove( CharaPtr pChara ); + bool hateListHasActor( CharaPtr pChara ); - void aggro( ActorPtr pActor ); - void deaggro( ActorPtr pActor ); + void aggro( CharaPtr pChara ); + void deaggro( CharaPtr pChara ); void update( int64_t currTime ) override; diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index 868cfe3b..3a42f836 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -38,7 +38,7 @@ Sapphire::Entity::Chara::Chara( ObjKind type, FrameworkPtr pFw ) : Actor( type ), m_pose( 0 ), m_targetId( INVALID_GAME_OBJECT_ID ), - m_pFw( pFw ) + m_pFw( std::move( std::move( pFw ) ) ) { // initialize the free slot queue 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() -{ -} += default; /*! \return the actors name */ 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 */ 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; srand( static_cast< uint32_t >( tick ) ); - uint16_t damage = static_cast< uint16_t >( 10 + rand() % 12 ); - uint32_t variation = static_cast< uint32_t >( 0 + rand() % 4 ); + auto damage = static_cast< uint16_t >( 10 + rand() % 12 ); - 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() ) ); - Server::EffectEntry effectEntry{}; effectEntry.value = damage; effectEntry.effectType = ActionEffectType::Damage; - effectEntry.hitSeverity = static_cast< ActionHitSeverityType >( variation ); - + effectEntry.hitSeverity = ActionHitSeverityType::NormalDamage; effectPacket->addEffect( effectEntry ); sendToInRangeSet( effectPacket ); - if( isPlayer() ) - getAsPlayer()->queuePacket( effectPacket ); - pTarget->takeDamage( damage ); + } } /*! -ChaiScript Skill Handler. +Skill Handler. \param GamePacketPtr to send \param bool should be send to self? */ 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 >(); 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 ), actionInfoPtr, TargetFilter::Allies ); - for( auto pHitActor : actorsCollided ) + for( const auto& pHitActor : actorsCollided ) { 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 */ void Sapphire::Entity::Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, - uint16_t param ) + uint16_t param ) { if( hasStatusEffect( id ) ) return; @@ -781,8 +775,6 @@ void Sapphire::Entity::Chara::updateStatusEffects() bool Sapphire::Entity::Chara::hasStatusEffect( uint32_t id ) { - if( m_statusEffectMap.find( id ) != m_statusEffectMap.end() ) - return true; - return false; + return m_statusEffectMap.find( id ) != m_statusEffectMap.end(); } diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 1b00e7b5..991975e9 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1474,7 +1474,7 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget ) auto effectPacket = std::make_shared< Server::EffectPacket >( getId(), pTarget->getId(), 8 ); effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) ); - Server::EffectEntry entry; + Server::EffectEntry entry{}; entry.value = damage; entry.effectType = Common::ActionEffectType::Damage; 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 ); effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) ); - Server::EffectEntry entry; + Server::EffectEntry entry{}; entry.value = damage; entry.effectType = Common::ActionEffectType::Damage; entry.hitSeverity = Common::ActionHitSeverityType::NormalDamage; diff --git a/src/world/Network/PacketWrappers/EffectPacket.h b/src/world/Network/PacketWrappers/EffectPacket.h index 694cefc8..23cdb7ef 100644 --- a/src/world/Network/PacketWrappers/EffectPacket.h +++ b/src/world/Network/PacketWrappers/EffectPacket.h @@ -17,25 +17,28 @@ namespace Sapphire::Network::Packets::Server EffectPacket( uint64_t sourceId, uint32_t targetId, uint32_t actionId ) : ZoneChannelPacket< FFXIVIpcEffect >( static_cast< uint32_t >( sourceId ), targetId ) { - m_data.header.actionId = actionId; - m_data.header.actionAnimationId = static_cast< uint16_t >( actionId ); + m_data.effectCount = 0; + 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.header.effectDisplayType = Common::ActionEffectDisplayType::ShowActionName; + m_data.effectDisplayType = Common::ActionEffectDisplayType::ShowActionName; } 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 ) { - m_data.header.actionAnimationId = animationId; + m_data.actionAnimationId = animationId; } void setEffectFlags( uint32_t effectFlags ) @@ -45,12 +48,12 @@ namespace Sapphire::Network::Packets::Server void setRotation( uint16_t rotation ) { - m_data.header.rotation = rotation; + m_data.rotation = rotation; } void setTargetActor( const uint32_t targetId ) { - m_data.header.animationTargetId = targetId; + m_data.animationTargetId = targetId; m_data.effectTargetId = targetId; FFXIVPacketBase::setTargetActor( targetId );