From 0a5a5561864b8bc88aacc805472c574b8843dcb6 Mon Sep 17 00:00:00 2001 From: Lucy <44952533+Skyliegirl33@users.noreply.github.com> Date: Mon, 23 Jan 2023 21:36:16 +0100 Subject: [PATCH 1/4] Fix oob memory access --- src/api/PlayerMinimal.cpp | 2 +- src/world/Actor/Player.h | 2 +- src/world/Network/PacketWrappers/PlayerSpawnPacket.h | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/api/PlayerMinimal.cpp b/src/api/PlayerMinimal.cpp index 12402b23..81e64e31 100644 --- a/src/api/PlayerMinimal.cpp +++ b/src/api/PlayerMinimal.cpp @@ -189,7 +189,7 @@ void PlayerMinimal::saveAsNew() std::vector< uint8_t > howTo( 33 ); std::vector< uint8_t > aetherytes( 16 ); std::vector< uint8_t > discovery( 421 ); - std::vector< uint8_t > questComplete( 350 ); + std::vector< uint8_t > questComplete( 342 ); std::vector< uint8_t > unlocks( 64 ); std::vector< uint8_t > mountGuide( 15 ); std::vector< uint8_t > orchestrion( 40 ); diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index ed0228a8..a393fb0d 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -31,7 +31,7 @@ namespace Sapphire::Entity using HowToList = std::array< uint8_t, 34 >; using MinionList = std::array< uint8_t, 40 >; using MountList = std::array< uint8_t, 22 >; - using QuestComplete = std::array< uint8_t, 350 >; + using QuestComplete = std::array< uint8_t, 342 >; using Discovery = std::array< uint8_t, 400 >; using AetheryteList = std::array< uint8_t, 21 >; using UnlockList = std::array< uint8_t, 64 >; diff --git a/src/world/Network/PacketWrappers/PlayerSpawnPacket.h b/src/world/Network/PacketWrappers/PlayerSpawnPacket.h index a647a006..353fd1e2 100644 --- a/src/world/Network/PacketWrappers/PlayerSpawnPacket.h +++ b/src/world/Network/PacketWrappers/PlayerSpawnPacket.h @@ -87,7 +87,8 @@ namespace Sapphire::Network::Packets::WorldPackets::Server m_data.PermissionInvisibility = 0; m_data.GrandCompany = player.getGc(); - m_data.GrandCompanyRank = player.getGcRankArray()[ player.getGc() - 1 ]; + if( m_data.GrandCompany > 0 ) + m_data.GrandCompanyRank = player.getGcRankArray()[ player.getGc() - 1 ]; //m_data.u23 = 0x04; //m_data.u24 = 256; From 8f0c517514fc8b3906d11f424f716ace947b8335 Mon Sep 17 00:00:00 2001 From: Lucy <44952533+Skyliegirl33@users.noreply.github.com> Date: Mon, 23 Jan 2023 21:39:12 +0100 Subject: [PATCH 2/4] [wip] Implement minions --- src/common/Common.h | 1 + src/world/Action/ItemAction.cpp | 16 ++++++++++++ src/world/Action/ItemAction.h | 2 ++ src/world/Actor/Player.cpp | 25 ++++++++++++++++++- src/world/Actor/Player.h | 8 +++++- src/world/Actor/PlayerSql.cpp | 7 ++++-- src/world/Manager/PlayerMgr.cpp | 5 ++++ src/world/Manager/PlayerMgr.h | 2 ++ .../Network/Handlers/PacketCommandHandler.cpp | 5 ++++ .../PacketWrappers/PlayerSetupPacket.h | 2 ++ 10 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/common/Common.h b/src/common/Common.h index fa9e9e2d..86d639e3 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -922,6 +922,7 @@ namespace Sapphire::Common { KeyItemAction = 1, ItemActionVFX = 852, + ItemActionCompanion = 853, ItemActionVFX2 = 944, ItemActionMount = 1322, }; diff --git a/src/world/Action/ItemAction.cpp b/src/world/Action/ItemAction.cpp index f2d51d86..1e8e5678 100644 --- a/src/world/Action/ItemAction.cpp +++ b/src/world/Action/ItemAction.cpp @@ -58,6 +58,13 @@ void ItemAction::execute() break; } + + case Common::ItemActionType::ItemActionCompanion: + { + handleCompanionItem(); + + break; + } } } @@ -81,6 +88,15 @@ void ItemAction::handleVFXItem() m_pSource->sendToInRangeSet( effectPacket, true ); } +void ItemAction::handleCompanionItem() +{ + auto player = getSourceChara()->getAsPlayer(); + + Logger::debug( "Companion arg: {0}", m_itemAction->data().Calcu0Arg[ 0 ] ); + + player->unlockCompanion( m_itemAction->data().Calcu0Arg[ 0 ] ); +} + void ItemAction::handleMountItem() { auto player = getSourceChara()->getAsPlayer(); diff --git a/src/world/Action/ItemAction.h b/src/world/Action/ItemAction.h index b7add735..d1078bd9 100644 --- a/src/world/Action/ItemAction.h +++ b/src/world/Action/ItemAction.h @@ -27,6 +27,8 @@ namespace Sapphire::World::Action private: void handleVFXItem(); + void handleCompanionItem(); + void handleMountItem(); private: diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index fc9b52d6..c7880f65 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1125,6 +1125,28 @@ void Player::unlockMount( uint32_t mountId ) queuePacket( makeActorControlSelf( getId(), Network::ActorControl::SetMountBitmask, mount->data().MountOrder, 1 ) ); } +void Player::unlockCompanion( uint32_t companionId ) +{ + auto& exdData = Common::Service< Data::ExdData >::ref(); + auto companion = exdData.getRow< Excel::Companion >( companionId ); + + //if( companion->data(). == -1 ) + // return; + + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( companionId, value, index ); + + m_minionGuide[ index ] |= value; + + queuePacket( makeActorControlSelf( getId(), Network::ActorControl::LearnCompanion, companionId, 1 ) ); +} + +Player::MinionList& Player::getMinionGuideBitmask() +{ + return m_minionGuide; +} + Player::MountList& Player::getMountGuideBitmask() { return m_mountGuide; @@ -1364,7 +1386,8 @@ void Player::setCompanion( uint8_t id ) return; m_companionId = id; - sendToInRangeSet( makeActorControl( getId(), ActorControlType::ToggleCompanion, id ), true ); + + Service< World::Manager::PlayerMgr >::ref().onCompanionUpdate( *this, m_companionId ); } uint8_t Player::getCurrentCompanion() const diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index a393fb0d..8118431e 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -459,6 +459,12 @@ namespace Sapphire::Entity /*! unlock a mount */ void unlockMount( uint32_t mountId ); + /*! unlock a companion */ + void unlockCompanion( uint32_t companionId ); + + /*! return a const pointer to the minion guide bitmask array */ + MinionList& getMinionGuideBitmask(); + /*! return a const pointer to the setMount guide bitmask array */ MountList& getMountGuideBitmask(); @@ -873,7 +879,7 @@ namespace Sapphire::Entity uint16_t m_activeTitle{}; TitleList m_titleList{}; HowToList m_howTo{}; - MinionList m_minions{}; + MinionList m_minionGuide{}; MountList m_mountGuide{}; QuestComplete m_questCompleteFlags{}; Discovery m_discovery{}; diff --git a/src/world/Actor/PlayerSql.cpp b/src/world/Actor/PlayerSql.cpp index 07695d46..77ec4e01 100644 --- a/src/world/Actor/PlayerSql.cpp +++ b/src/world/Actor/PlayerSql.cpp @@ -129,6 +129,9 @@ bool Sapphire::Entity::Player::loadFromDb( uint64_t characterId ) auto titleList = res->getBlobVector( "TitleList" ); memcpy( reinterpret_cast< char* >( m_titleList.data() ), titleList.data(), titleList.size() ); + auto minionGuide = res->getBlobVector( "Minions" ); + memcpy( reinterpret_cast< char* >( m_minionGuide.data() ), minionGuide.data(), minionGuide.size() ); + auto mountGuide = res->getBlobVector( "Mounts" ); memcpy( reinterpret_cast< char* >( m_mountGuide.data() ), mountGuide.data(), mountGuide.size() ); @@ -384,8 +387,8 @@ void Sapphire::Entity::Player::updateDbChara() const memcpy( howToVec.data(), m_howTo.data(), m_howTo.size() ); stmt->setBinary( 40, howToVec ); - std::vector< uint8_t > minionsVec( sizeof( m_minions ) ); - memcpy( minionsVec.data(), m_minions.data(), m_minions.size() ); + std::vector< uint8_t > minionsVec( sizeof( m_minionGuide ) ); + memcpy( minionsVec.data(), m_minionGuide.data(), m_minionGuide.size() ); stmt->setBinary( 41, minionsVec ); std::vector< uint8_t > mountsVec( sizeof( m_mountGuide ) ); diff --git a/src/world/Manager/PlayerMgr.cpp b/src/world/Manager/PlayerMgr.cpp index 16439b7b..c43e1f85 100644 --- a/src/world/Manager/PlayerMgr.cpp +++ b/src/world/Manager/PlayerMgr.cpp @@ -223,6 +223,11 @@ void PlayerMgr::onGcUpdate( Entity::Player& player ) server.queueForPlayer( player.getCharacterId(), gcAffPacket ); } +void PlayerMgr::onCompanionUpdate( Entity::Player& player, uint8_t companionId ) +{ + player.sendToInRangeSet( makeActorControl( player.getId(), ActorControlType::ToggleCompanion, companionId ), true ); +} + void PlayerMgr::onMountUpdate( Entity::Player& player, uint32_t mountId ) { if( mountId != 0 ) diff --git a/src/world/Manager/PlayerMgr.h b/src/world/Manager/PlayerMgr.h index 91c73406..15e686a9 100644 --- a/src/world/Manager/PlayerMgr.h +++ b/src/world/Manager/PlayerMgr.h @@ -44,6 +44,8 @@ class PlayerMgr void onGcUpdate( Sapphire::Entity::Player& player ); + void onCompanionUpdate( Entity::Player& player, uint8_t companionId ); + void onMountUpdate( Sapphire::Entity::Player& player, uint32_t mountId ); void onMobKill( Sapphire::Entity::Player& player, Sapphire::Entity::BNpc& bnpc ); diff --git a/src/world/Network/Handlers/PacketCommandHandler.cpp b/src/world/Network/Handlers/PacketCommandHandler.cpp index 632b0db4..265ab496 100644 --- a/src/world/Network/Handlers/PacketCommandHandler.cpp +++ b/src/world/Network/Handlers/PacketCommandHandler.cpp @@ -465,6 +465,11 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_ player.setCompanion( static_cast< uint8_t >( param1 ) ); break; } + case PacketCommand::COMPANION_CANCEL: + { + player.setCompanion( 0 ); + break; + } case PacketCommand::REQUEST_STATUS_RESET: // Remove status (clicking it off) { // todo: check if status can be removed by client from exd diff --git a/src/world/Network/PacketWrappers/PlayerSetupPacket.h b/src/world/Network/PacketWrappers/PlayerSetupPacket.h index da562f69..d9b2a61f 100644 --- a/src/world/Network/PacketWrappers/PlayerSetupPacket.h +++ b/src/world/Network/PacketWrappers/PlayerSetupPacket.h @@ -58,6 +58,8 @@ namespace Sapphire::Network::Packets::WorldPackets::Server // memcpy( m_data.orchestrionMask, player.getOrchestrionBitmask(), sizeof( m_data.orchestrionMask ) ); + memcpy( m_data.Companion, player.getMinionGuideBitmask().data(), sizeof( m_data.Companion ) ); + memcpy( m_data.MountList, player.getMountGuideBitmask().data(), sizeof( m_data.MountList ) ); memcpy( m_data.Reward, player.getUnlockBitmask().data(), sizeof( m_data.Reward ) ); From ac4c8ec8a6f96ddb57ec9880da39b1c004094cac Mon Sep 17 00:00:00 2001 From: Lucy <44952533+Skyliegirl33@users.noreply.github.com> Date: Fri, 20 Jan 2023 23:13:05 +0100 Subject: [PATCH 3/4] Add sprint costtype --- src/common/Common.h | 1 + src/world/Action/Action.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/common/Common.h b/src/common/Common.h index 86d639e3..8dca3a4b 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -816,6 +816,7 @@ namespace Sapphire::Common MagicPoints = 3, TacticsPoints = 5, TacticsPoints1 = 6, + Sprint = 18, // WARGauge = 22, // DRKGauge = 25, // AetherflowStack = 30, diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index d7394234..5a26c0f6 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -702,6 +702,7 @@ bool Action::Action::primaryCostCheck( bool subtractCosts ) { case Common::ActionPrimaryCostType::TacticsPoints: case Common::ActionPrimaryCostType::TacticsPoints1: + case Common::ActionPrimaryCostType::Sprint: { auto curTp = m_pSource->getTp(); From 4abe2532c3a81efd9e3cd3ff0df4a5d56e44c039 Mon Sep 17 00:00:00 2001 From: Lucy <44952533+Skyliegirl33@users.noreply.github.com> Date: Sat, 21 Jan 2023 02:12:00 +0100 Subject: [PATCH 4/4] [wip] Implement persistent emote cancelling --- src/common/Network/CommonActorControl.h | 2 ++ .../Network/Handlers/PacketCommandHandler.cpp | 26 +++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index 411ce218..2c971c47 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -148,6 +148,8 @@ namespace Sapphire::Network::ActorControl Emote = 0x122, EmoteInterrupt = 0x123, + EmoteModeInterrupt = 0x124, + EmoteModeInterruptNonImmediate = 0x125, SetPose = 0x127, diff --git a/src/world/Network/Handlers/PacketCommandHandler.cpp b/src/world/Network/Handlers/PacketCommandHandler.cpp index 265ab496..4d05bd2b 100644 --- a/src/world/Network/Handlers/PacketCommandHandler.cpp +++ b/src/world/Network/Handlers/PacketCommandHandler.cpp @@ -15,6 +15,7 @@ #include "Network/PacketWrappers/InspectPacket.h" #include "Network/PacketWrappers/ActorControlPacket.h" #include "Network/PacketWrappers/ActorControlTargetPacket.h" +#include "Network/PacketWrappers/MoveActorPacket.h" #include "Action/Action.h" @@ -553,15 +554,21 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_ player.sendToInRangeSet( makeActorControl( player.getId(), ActorControlType::EmoteInterrupt ) ); break; } - /* case PacketCommand::PersistentEmoteCancel: // cancel persistent emote - { - player.setPersistentEmote( 0 ); - player.emoteInterrupt(); - player.setStatus( ActorStatus::Idle ); - auto pSetStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( ActorStatus::Idle ) ); - player.sendToInRangeSet( pSetStatusPacket ); + case PacketCommand::EMOTE_MODE_CANCEL: + { + if( player.getPersistentEmote() > 0 ) + { + auto movePacket = std::make_shared< MoveActorPacket >( player, player.getRot(), 2, 0, 0, 0x5A / 4 ); + player.sendToInRangeSet( movePacket ); + + player.setPersistentEmote( 0 ); + player.sendToInRangeSet( makeActorControl( player.getId(), ActorControlType::EmoteModeInterrupt ) ); + player.setStatus( ActorStatus::Idle ); + + player.sendToInRangeSet( makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( ActorStatus::Idle ) ) ); + } break; - }*/ + } case PacketCommand::POSE_EMOTE_CONFIG: // change pose case PacketCommand::POSE_EMOTE_WORK: // reapply pose { @@ -572,9 +579,6 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_ } case PacketCommand::POSE_EMOTE_CANCEL: // cancel pose { - player.setPose( static_cast< uint8_t >( param12 ) ); - auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, param11, param12 ); - player.sendToInRangeSet( pSetStatusPacket, true ); break; } case PacketCommand::REVIVE: // return dead / accept raise