mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-23 07:40:14 +00:00
Add Tier 8 commands: advanced targeting system
Targeting Commands: - /cleartarget - Clear current target selection - /targetenemy - Cycle to next hostile target (Tab equivalent) - /targetfriend - Cycle to next friendly player - /targetlasttarget, /targetlast - Switch to previous target - /targetlastenemy - Cycle to previous hostile target - /targetlastfriend - Cycle to previous friendly player - /focus - Set current target as focus (client-side) - /clearfocus - Clear focus target Implementation: - Added focusGuid and lastTargetGuid to GameHandler for client-side tracking - setTarget() now automatically saves previous target to lastTargetGuid - setFocus() and clearFocus() manage focus target with user feedback - targetLastTarget() swaps current and previous targets - targetEnemy() cycles through hostile entities (Units) - targetFriend() cycles through friendly entities (Players) - Both targetEnemy/targetFriend support reverse parameter for backwards cycling Features: - Focus targeting is client-side (no server opcode in 3.3.5a) - Last target tracking happens automatically on every target change - Enemy/friend cycling iterates through visible entities - Provides user feedback when no targets available - Tab-like cycling behavior with wraparound All commands work entirely client-side for responsive targeting.
This commit is contained in:
parent
bca3f64af6
commit
dfc4008ec7
3 changed files with 206 additions and 0 deletions
|
|
@ -1521,6 +1521,12 @@ void GameHandler::handleMessageChat(network::Packet& packet) {
|
|||
|
||||
void GameHandler::setTarget(uint64_t guid) {
|
||||
if (guid == targetGuid) return;
|
||||
|
||||
// Save previous target
|
||||
if (targetGuid != 0) {
|
||||
lastTargetGuid = targetGuid;
|
||||
}
|
||||
|
||||
targetGuid = guid;
|
||||
|
||||
// Inform server of target selection (Phase 1)
|
||||
|
|
@ -1548,6 +1554,135 @@ std::shared_ptr<Entity> GameHandler::getTarget() const {
|
|||
return entityManager.getEntity(targetGuid);
|
||||
}
|
||||
|
||||
void GameHandler::setFocus(uint64_t guid) {
|
||||
focusGuid = guid;
|
||||
if (guid != 0) {
|
||||
auto entity = entityManager.getEntity(guid);
|
||||
if (entity) {
|
||||
std::string name = "Unknown";
|
||||
if (entity->getType() == ObjectType::PLAYER) {
|
||||
auto player = std::dynamic_pointer_cast<Player>(entity);
|
||||
if (player && !player->getName().empty()) {
|
||||
name = player->getName();
|
||||
}
|
||||
}
|
||||
addSystemChatMessage("Focus set: " + name);
|
||||
LOG_INFO("Focus set: 0x", std::hex, guid, std::dec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameHandler::clearFocus() {
|
||||
if (focusGuid != 0) {
|
||||
addSystemChatMessage("Focus cleared.");
|
||||
LOG_INFO("Focus cleared");
|
||||
}
|
||||
focusGuid = 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<Entity> GameHandler::getFocus() const {
|
||||
if (focusGuid == 0) return nullptr;
|
||||
return entityManager.getEntity(focusGuid);
|
||||
}
|
||||
|
||||
void GameHandler::targetLastTarget() {
|
||||
if (lastTargetGuid == 0) {
|
||||
addSystemChatMessage("No previous target.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Swap current and last target
|
||||
uint64_t temp = targetGuid;
|
||||
setTarget(lastTargetGuid);
|
||||
lastTargetGuid = temp;
|
||||
}
|
||||
|
||||
void GameHandler::targetEnemy(bool reverse) {
|
||||
// Get list of hostile entities
|
||||
std::vector<uint64_t> hostiles;
|
||||
auto& entities = entityManager.getEntities();
|
||||
|
||||
for (const auto& [guid, entity] : entities) {
|
||||
if (entity->getType() == ObjectType::UNIT) {
|
||||
// Check if hostile (this is simplified - would need faction checking)
|
||||
auto unit = std::dynamic_pointer_cast<Unit>(entity);
|
||||
if (unit && guid != playerGuid) {
|
||||
hostiles.push_back(guid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hostiles.empty()) {
|
||||
addSystemChatMessage("No enemies in range.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Find current target in list
|
||||
auto it = std::find(hostiles.begin(), hostiles.end(), targetGuid);
|
||||
|
||||
if (it == hostiles.end()) {
|
||||
// Not currently targeting a hostile, target first one
|
||||
setTarget(reverse ? hostiles.back() : hostiles.front());
|
||||
} else {
|
||||
// Cycle to next/previous
|
||||
if (reverse) {
|
||||
if (it == hostiles.begin()) {
|
||||
setTarget(hostiles.back());
|
||||
} else {
|
||||
setTarget(*(--it));
|
||||
}
|
||||
} else {
|
||||
++it;
|
||||
if (it == hostiles.end()) {
|
||||
setTarget(hostiles.front());
|
||||
} else {
|
||||
setTarget(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameHandler::targetFriend(bool reverse) {
|
||||
// Get list of friendly entities (players)
|
||||
std::vector<uint64_t> friendlies;
|
||||
auto& entities = entityManager.getEntities();
|
||||
|
||||
for (const auto& [guid, entity] : entities) {
|
||||
if (entity->getType() == ObjectType::PLAYER && guid != playerGuid) {
|
||||
friendlies.push_back(guid);
|
||||
}
|
||||
}
|
||||
|
||||
if (friendlies.empty()) {
|
||||
addSystemChatMessage("No friendly targets in range.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Find current target in list
|
||||
auto it = std::find(friendlies.begin(), friendlies.end(), targetGuid);
|
||||
|
||||
if (it == friendlies.end()) {
|
||||
// Not currently targeting a friend, target first one
|
||||
setTarget(reverse ? friendlies.back() : friendlies.front());
|
||||
} else {
|
||||
// Cycle to next/previous
|
||||
if (reverse) {
|
||||
if (it == friendlies.begin()) {
|
||||
setTarget(friendlies.back());
|
||||
} else {
|
||||
setTarget(*(--it));
|
||||
}
|
||||
} else {
|
||||
++it;
|
||||
if (it == friendlies.end()) {
|
||||
setTarget(friendlies.front());
|
||||
} else {
|
||||
setTarget(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameHandler::inspectTarget() {
|
||||
if (state != WorldState::IN_WORLD || !socket) {
|
||||
LOG_WARNING("Cannot inspect: not in world or not connected");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue