Add pet tracking via SMSG_PET_SPELLS and dismiss pet button

This commit is contained in:
Kelsi 2026-02-26 10:41:29 -08:00
parent a1f73fdd39
commit 74b78cd10b
5 changed files with 45 additions and 2 deletions

View file

@ -441,6 +441,9 @@ public:
void castSpell(uint32_t spellId, uint64_t targetGuid = 0);
void cancelCast();
void cancelAura(uint32_t spellId);
void dismissPet();
bool hasPet() const { return petGuid_ != 0; }
uint64_t getPetGuid() const { return petGuid_; }
const std::unordered_set<uint32_t>& getKnownSpells() const { return knownSpells; }
bool isCasting() const { return casting; }
bool isGameObjectInteractionCasting() const {
@ -1137,6 +1140,7 @@ private:
void handleGuildInvite(network::Packet& packet);
void handleGuildCommandResult(network::Packet& packet);
void handlePetitionShowlist(network::Packet& packet);
void handlePetSpells(network::Packet& packet);
void handleTurnInPetitionResults(network::Packet& packet);
// ---- Character creation handler ----
@ -1475,6 +1479,7 @@ private:
std::array<ActionBarSlot, 12> actionBar{};
std::vector<AuraSlot> playerAuras;
std::vector<AuraSlot> targetAuras;
uint64_t petGuid_ = 0;
// ---- Phase 4: Group ----
GroupListData partyData;

View file

@ -1698,6 +1698,12 @@ public:
static network::Packet build(uint32_t spellId);
};
/** CMSG_PET_ACTION packet builder */
class PetActionPacket {
public:
static network::Packet build(uint64_t petGuid, uint32_t action);
};
/** SMSG_CAST_FAILED data */
struct CastFailedData {
uint8_t castCount = 0;

View file

@ -1836,6 +1836,9 @@ void GameHandler::handlePacket(network::Packet& packet) {
case Opcode::SMSG_GUILD_COMMAND_RESULT:
handleGuildCommandResult(packet);
break;
case Opcode::SMSG_PET_SPELLS:
handlePetSpells(packet);
break;
case Opcode::SMSG_PETITION_SHOWLIST:
handlePetitionShowlist(packet);
break;
@ -3322,6 +3325,7 @@ void GameHandler::selectCharacter(uint64_t characterGuid) {
actionBar = {};
playerAuras.clear();
targetAuras.clear();
petGuid_ = 0;
playerXp_ = 0;
playerNextLevelXp_ = 0;
serverPlayerLevel_ = 1;
@ -9261,6 +9265,18 @@ void GameHandler::cancelAura(uint32_t spellId) {
socket->send(packet);
}
void GameHandler::handlePetSpells(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 8) return;
petGuid_ = packet.readUInt64();
LOG_DEBUG("SMSG_PET_SPELLS: petGuid=0x", std::hex, petGuid_, std::dec);
}
void GameHandler::dismissPet() {
if (petGuid_ == 0 || state != WorldState::IN_WORLD || !socket) return;
auto packet = PetActionPacket::build(petGuid_, 0x07000000);
socket->send(packet);
}
void GameHandler::setActionBarSlot(int slot, ActionBarSlot::Type type, uint32_t id) {
if (slot < 0 || slot >= ACTION_BAR_SLOTS) return;
actionBar[slot].type = type;

View file

@ -2890,6 +2890,13 @@ network::Packet CancelAuraPacket::build(uint32_t spellId) {
return packet;
}
network::Packet PetActionPacket::build(uint64_t petGuid, uint32_t action) {
network::Packet packet(wireOpcode(Opcode::CMSG_PET_ACTION));
packet.writeUInt64(petGuid);
packet.writeUInt32(action);
return packet;
}
bool CastFailedParser::parse(network::Packet& packet, CastFailedData& data) {
data.castCount = packet.readUInt8();
data.spellId = packet.readUInt32();

View file

@ -4720,14 +4720,13 @@ void GameScreen::renderGuildRoster(game::GameHandler& gameHandler) {
void GameScreen::renderBuffBar(game::GameHandler& gameHandler) {
const auto& auras = gameHandler.getPlayerAuras();
if (auras.empty()) return;
// Count non-empty auras
int activeCount = 0;
for (const auto& a : auras) {
if (!a.isEmpty()) activeCount++;
}
if (activeCount == 0) return;
if (activeCount == 0 && !gameHandler.hasPet()) return;
auto* assetMgr = core::Application::getInstance().getAssetManager();
@ -4813,6 +4812,16 @@ void GameScreen::renderBuffBar(game::GameHandler& gameHandler) {
ImGui::PopID();
shown++;
}
// Dismiss Pet button
if (gameHandler.hasPet()) {
if (shown > 0) ImGui::Spacing();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.6f, 0.2f, 0.2f, 0.9f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.8f, 0.3f, 0.3f, 1.0f));
if (ImGui::Button("Dismiss Pet", ImVec2(-1, 0))) {
gameHandler.dismissPet();
}
ImGui::PopStyleColor(2);
}
}
ImGui::End();