diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index b853f07f..77daeef4 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -122,9 +122,9 @@ enum ActorControlType : uint16_t ActorFadeOut = 0x10A, ActorFadeIn = 0x10B, WithdrawMsg = 0x10C, - OrderMinion = 0x10D, - ToggleMinion = 0x10E, - LearnMinion = 0x10F, + OrderCompanion = 0x10D, + ToggleCompanion = 0x10E, + LearnCompanion = 0x10F, ActorFateOut1 = 0x110, Emote = 0x122, @@ -278,7 +278,7 @@ enum ActorControlType : uint16_t ChangeTarget = 0x03, DismountReq = 0x65, - + SpawnCompanionReq = 0x66, RemoveStatusEffect = 0x68, CastCancel = 0x69, diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 9ccc85d2..76268f57 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1504,6 +1504,24 @@ void Sapphire::Entity::Player::dismount() m_mount = 0; } +void Sapphire::Entity::Player::spawnCompanion( uint16_t id ) +{ + auto exdData = m_pFw->get< Data::ExdDataGenerated >(); + assert( exdData ); + + auto companion = exdData->get< Data::Companion >( id ); + if( !id ) + return; + + m_companionId = id; + sendToInRangeSet( makeActorControl142( getId(), ActorControlType::ToggleCompanion, id ), true ); +} + +uint16_t Sapphire::Entity::Player::getCurrentCompanion() const +{ + return m_companionId; +} + uint8_t Sapphire::Entity::Player::getCurrentMount() const { return m_mount; diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index 02e1c282..388afa51 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -565,6 +565,11 @@ namespace Sapphire::Entity /*! dismount the current mount and send the packets */ void dismount(); + void spawnCompanion( uint16_t id ); + void despawnCompanion(); + + uint16_t getCurrentCompanion() const; + /*! get the current mount */ uint8_t getCurrentMount() const; @@ -1076,6 +1081,7 @@ namespace Sapphire::Entity // content finder info uint32_t m_cfPenaltyUntil; // unix time + uint16_t m_companionId; uint32_t m_mount; uint32_t m_emoteMode; diff --git a/src/world/Network/Handlers/ClientTriggerHandler.cpp b/src/world/Network/Handlers/ClientTriggerHandler.cpp index 362e6a13..1b49e689 100644 --- a/src/world/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/world/Network/Handlers/ClientTriggerHandler.cpp @@ -126,6 +126,11 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( FrameworkPtr pFw, player.dismount(); break; } + case ClientTriggerType::SpawnCompanionReq: + { + player.spawnCompanion( param1 ); + break; + } case ClientTriggerType::RemoveStatusEffect: // Remove status (clicking it off) { // todo: check if status can be removed by client from exd diff --git a/src/world/Network/PacketWrappers/InitUIPacket.h b/src/world/Network/PacketWrappers/InitUIPacket.h index 91fa6c59..cdcdcf48 100644 --- a/src/world/Network/PacketWrappers/InitUIPacket.h +++ b/src/world/Network/PacketWrappers/InitUIPacket.h @@ -84,6 +84,7 @@ namespace Sapphire::Network::Packets::Server memset( m_data.unlockedPvp, 0xFF, sizeof( m_data.unlockedPvp ) ); memset( m_data.unlockedRaids, 0xFF, sizeof( m_data.unlockedRaids ) ); memset( m_data.unlockedTrials, 0xFF, sizeof( m_data.unlockedTrials ) ); + memset( m_data.minions, 0xFF, sizeof( m_data.minions ) ); }; }; diff --git a/src/world/Network/PacketWrappers/PlayerSpawnPacket.h b/src/world/Network/PacketWrappers/PlayerSpawnPacket.h index 71481112..0f0375a6 100644 --- a/src/world/Network/PacketWrappers/PlayerSpawnPacket.h +++ b/src/world/Network/PacketWrappers/PlayerSpawnPacket.h @@ -71,6 +71,7 @@ namespace Sapphire::Network::Packets::Server m_data.title = player.getTitle(); m_data.voice = player.getVoiceId(); m_data.currentMount = player.getCurrentMount(); + m_data.activeMinion = player.getCurrentCompanion(); m_data.onlineStatus = static_cast< uint8_t >( player.getOnlineStatus() );