mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-23 07:40:14 +00:00
Add Tier 2 utility commands: helm/cloak toggles, follow, and assist
Display Toggle Commands: - Add /helm, /helmet, /showhelm to toggle helm visibility - Add /cloak, /showcloak to toggle cloak visibility - Track visibility state with helmVisible_ and cloakVisible_ flags - Show confirmation messages: "Helm/Cloak is now visible/hidden" - Use CMSG_SHOWING_HELM (0x2B9) and CMSG_SHOWING_CLOAK (0x2BA) Follow Command: - Add /follow and /f to follow current target - Works with both players and NPCs - Show "Now following [Name]" confirmation message - Track follow target with followTargetGuid_ for future movement logic Assist Command: - Add /assist to target what your current target is targeting - Read target's target from UNIT_FIELD_TARGET update fields (offset 6-7) - Reconstruct 64-bit target GUID from two 32-bit field values - Automatically switch your target to assist target - Show helpful messages: "[Name] has no target" when appropriate - Essential for combat coordination in groups Implementation: - Add ShowingHelmPacket and ShowingCloakPacket builders - Add toggleHelm() and toggleCloak() methods with state management - Add followTarget() for setting follow target - Add assistTarget() with smart target field reading - Use Entity::getFields() to access protected update fields - Handle missing targets and invalid states gracefully - All commands provide chat feedback - Support multiple aliases for user convenience
This commit is contained in:
parent
ec32286b0d
commit
acef7ccbec
6 changed files with 198 additions and 0 deletions
|
|
@ -1776,6 +1776,123 @@ void GameHandler::setStandState(uint8_t standState) {
|
|||
LOG_INFO("Changed stand state to: ", (int)standState);
|
||||
}
|
||||
|
||||
void GameHandler::toggleHelm() {
|
||||
if (state != WorldState::IN_WORLD || !socket) {
|
||||
LOG_WARNING("Cannot toggle helm: not in world or not connected");
|
||||
return;
|
||||
}
|
||||
|
||||
helmVisible_ = !helmVisible_;
|
||||
auto packet = ShowingHelmPacket::build(helmVisible_);
|
||||
socket->send(packet);
|
||||
addSystemChatMessage(helmVisible_ ? "Helm is now visible." : "Helm is now hidden.");
|
||||
LOG_INFO("Helm visibility toggled: ", helmVisible_);
|
||||
}
|
||||
|
||||
void GameHandler::toggleCloak() {
|
||||
if (state != WorldState::IN_WORLD || !socket) {
|
||||
LOG_WARNING("Cannot toggle cloak: not in world or not connected");
|
||||
return;
|
||||
}
|
||||
|
||||
cloakVisible_ = !cloakVisible_;
|
||||
auto packet = ShowingCloakPacket::build(cloakVisible_);
|
||||
socket->send(packet);
|
||||
addSystemChatMessage(cloakVisible_ ? "Cloak is now visible." : "Cloak is now hidden.");
|
||||
LOG_INFO("Cloak visibility toggled: ", cloakVisible_);
|
||||
}
|
||||
|
||||
void GameHandler::followTarget() {
|
||||
if (state != WorldState::IN_WORLD) {
|
||||
LOG_WARNING("Cannot follow: not in world");
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetGuid == 0) {
|
||||
addSystemChatMessage("You must target someone to follow.");
|
||||
return;
|
||||
}
|
||||
|
||||
auto target = getTarget();
|
||||
if (!target) {
|
||||
addSystemChatMessage("Invalid target.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set follow target
|
||||
followTargetGuid_ = targetGuid;
|
||||
|
||||
// Get target name
|
||||
std::string targetName = "Target";
|
||||
if (target->getType() == ObjectType::PLAYER) {
|
||||
auto player = std::static_pointer_cast<Player>(target);
|
||||
if (!player->getName().empty()) {
|
||||
targetName = player->getName();
|
||||
}
|
||||
} else if (target->getType() == ObjectType::UNIT) {
|
||||
auto unit = std::static_pointer_cast<Unit>(target);
|
||||
targetName = unit->getName();
|
||||
}
|
||||
|
||||
addSystemChatMessage("Now following " + targetName + ".");
|
||||
LOG_INFO("Following target: ", targetName, " (GUID: 0x", std::hex, targetGuid, std::dec, ")");
|
||||
}
|
||||
|
||||
void GameHandler::assistTarget() {
|
||||
if (state != WorldState::IN_WORLD) {
|
||||
LOG_WARNING("Cannot assist: not in world");
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetGuid == 0) {
|
||||
addSystemChatMessage("You must target someone to assist.");
|
||||
return;
|
||||
}
|
||||
|
||||
auto target = getTarget();
|
||||
if (!target) {
|
||||
addSystemChatMessage("Invalid target.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get target name
|
||||
std::string targetName = "Target";
|
||||
if (target->getType() == ObjectType::PLAYER) {
|
||||
auto player = std::static_pointer_cast<Player>(target);
|
||||
if (!player->getName().empty()) {
|
||||
targetName = player->getName();
|
||||
}
|
||||
} else if (target->getType() == ObjectType::UNIT) {
|
||||
auto unit = std::static_pointer_cast<Unit>(target);
|
||||
targetName = unit->getName();
|
||||
}
|
||||
|
||||
// Try to read target GUID from update fields (UNIT_FIELD_TARGET)
|
||||
// Field offset 6 is typically UNIT_FIELD_TARGET in 3.3.5a
|
||||
uint64_t assistTargetGuid = 0;
|
||||
const auto& fields = target->getFields();
|
||||
auto it = fields.find(6);
|
||||
if (it != fields.end()) {
|
||||
// Low 32 bits
|
||||
assistTargetGuid = it->second;
|
||||
// Try to get high 32 bits from next field
|
||||
auto it2 = fields.find(7);
|
||||
if (it2 != fields.end()) {
|
||||
assistTargetGuid |= (static_cast<uint64_t>(it2->second) << 32);
|
||||
}
|
||||
}
|
||||
|
||||
if (assistTargetGuid == 0) {
|
||||
addSystemChatMessage(targetName + " has no target.");
|
||||
LOG_INFO("Assist: ", targetName, " has no target");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set our target to their target
|
||||
setTarget(assistTargetGuid);
|
||||
LOG_INFO("Assisting ", targetName, ", now targeting GUID: 0x", std::hex, assistTargetGuid, std::dec);
|
||||
}
|
||||
|
||||
void GameHandler::releaseSpirit() {
|
||||
if (!playerDead_) return;
|
||||
if (socket && state == WorldState::IN_WORLD) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue