feat: add right-click pet spell autocast toggle via CMSG_PET_SPELL_AUTOCAST

Right-clicking a castable pet ability (actionId > 6) in the pet action
bar now sends CMSG_PET_SPELL_AUTOCAST to toggle the spell's autocast
state. The local petAutocastSpells_ set is updated optimistically and
the tooltip shows the current state with a right-click hint.
This commit is contained in:
Kelsi 2026-03-18 05:08:10 -07:00
parent 586408516b
commit e7fe35c1f9
3 changed files with 28 additions and 2 deletions

View file

@ -746,6 +746,8 @@ public:
}
// Send CMSG_PET_ACTION to issue a pet command
void sendPetAction(uint32_t action, uint64_t targetGuid = 0);
// Toggle autocast for a pet spell via CMSG_PET_SPELL_AUTOCAST
void togglePetSpellAutocast(uint32_t spellId);
const std::unordered_set<uint32_t>& getKnownSpells() const { return knownSpells; }
// ---- Pet Stable ----

View file

@ -18291,6 +18291,24 @@ void GameHandler::dismissPet() {
socket->send(packet);
}
void GameHandler::togglePetSpellAutocast(uint32_t spellId) {
if (petGuid_ == 0 || spellId == 0 || state != WorldState::IN_WORLD || !socket) return;
bool currentlyOn = petAutocastSpells_.count(spellId) != 0;
uint8_t newState = currentlyOn ? 0 : 1;
// CMSG_PET_SPELL_AUTOCAST: petGuid(8) + spellId(4) + state(1)
network::Packet pkt(wireOpcode(Opcode::CMSG_PET_SPELL_AUTOCAST));
pkt.writeUInt64(petGuid_);
pkt.writeUInt32(spellId);
pkt.writeUInt8(newState);
socket->send(pkt);
// Optimistically update local state; server will confirm via SMSG_PET_SPELLS
if (newState)
petAutocastSpells_.insert(spellId);
else
petAutocastSpells_.erase(spellId);
LOG_DEBUG("togglePetSpellAutocast: spellId=", spellId, " autocast=", (int)newState);
}
void GameHandler::renamePet(const std::string& newName) {
if (petGuid_ == 0 || state != WorldState::IN_WORLD || !socket) return;
if (newName.empty() || newName.size() > 12) return; // Server enforces max 12 chars

View file

@ -3899,6 +3899,10 @@ void GameScreen::renderPetFrame(game::GameHandler& gameHandler) {
uint64_t targetGuid = (actionId > 5) ? gameHandler.getTargetGuid() : 0u;
gameHandler.sendPetAction(slotVal, targetGuid);
}
// Right-click toggles autocast for castable pet spells (actionId > 6)
if (actionId > 6 && ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
gameHandler.togglePetSpellAutocast(actionId);
}
// Tooltip: rich spell info for pet spells, simple label for built-in commands
if (ImGui::IsItemHovered()) {
@ -3920,8 +3924,10 @@ void GameScreen::renderPetFrame(game::GameHandler& gameHandler) {
if (nm.empty()) nm = "Spell #" + std::to_string(actionId);
ImGui::Text("%s", nm.c_str());
}
if (autocastOn)
ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "Autocast: On");
ImGui::TextColored(autocastOn
? ImVec4(0.4f, 1.0f, 0.4f, 1.0f)
: ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
"Autocast: %s (right-click to toggle)", autocastOn ? "On" : "Off");
if (petOnCd) {
if (petCd >= 60.0f)
ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f),