mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-03 00:03:50 +00:00
Add Tier 6 commands: party/raid management
- Uninvite/kick: /uninvite, /kick <player name> to remove player from party/raid - Leave party: /leave, /leaveparty to leave current group - Main tank: /maintank, /mt to set target as main tank (uses raid marker index 0) - Main assist: /mainassist, /ma to set target as main assist (uses raid marker index 1) - Clear markers: /clearmaintank, /clearmainassist to remove designations - Raid info: /raidinfo to display raid lockouts and saved instances Added opcodes: - CMSG_REQUEST_RAID_INFO (0x2CD) for requesting raid lockout info - SMSG_RAID_INSTANCE_INFO (0x2CC) for receiving raid info response New packet builders: - GroupUninvitePacket for removing players from group - GroupDisbandPacket for leaving party (with logging) - RaidTargetUpdatePacket for setting raid markers (main tank/assist) - RequestRaidInfoPacket for querying raid lockouts All commands include proper validation and user feedback.
This commit is contained in:
parent
9f3bead117
commit
ce6f66fcfa
6 changed files with 246 additions and 11 deletions
|
|
@ -261,6 +261,15 @@ public:
|
||||||
std::string getLastWhisperSender() const { return lastWhisperSender_; }
|
std::string getLastWhisperSender() const { return lastWhisperSender_; }
|
||||||
void setLastWhisperSender(const std::string& name) { lastWhisperSender_ = name; }
|
void setLastWhisperSender(const std::string& name) { lastWhisperSender_ = name; }
|
||||||
|
|
||||||
|
// Party/Raid management
|
||||||
|
void uninvitePlayer(const std::string& playerName);
|
||||||
|
void leaveParty();
|
||||||
|
void setMainTank(uint64_t targetGuid);
|
||||||
|
void setMainAssist(uint64_t targetGuid);
|
||||||
|
void clearMainTank();
|
||||||
|
void clearMainAssist();
|
||||||
|
void requestRaidInfo();
|
||||||
|
|
||||||
// ---- Phase 1: Name queries ----
|
// ---- Phase 1: Name queries ----
|
||||||
void queryPlayerName(uint64_t guid);
|
void queryPlayerName(uint64_t guid);
|
||||||
void queryCreatureInfo(uint32_t entry, uint64_t guid);
|
void queryCreatureInfo(uint32_t entry, uint64_t guid);
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,8 @@ enum class Opcode : uint16_t {
|
||||||
SMSG_GROUP_LIST = 0x07D,
|
SMSG_GROUP_LIST = 0x07D,
|
||||||
SMSG_PARTY_COMMAND_RESULT = 0x07E,
|
SMSG_PARTY_COMMAND_RESULT = 0x07E,
|
||||||
MSG_RAID_TARGET_UPDATE = 0x321,
|
MSG_RAID_TARGET_UPDATE = 0x321,
|
||||||
|
CMSG_REQUEST_RAID_INFO = 0x2CD,
|
||||||
|
SMSG_RAID_INSTANCE_INFO = 0x2CC,
|
||||||
|
|
||||||
// ---- Phase 5: Loot ----
|
// ---- Phase 5: Loot ----
|
||||||
CMSG_AUTOSTORE_LOOT_ITEM = 0x108,
|
CMSG_AUTOSTORE_LOOT_ITEM = 0x108,
|
||||||
|
|
|
||||||
|
|
@ -884,6 +884,39 @@ public:
|
||||||
static network::Packet build();
|
static network::Packet build();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Party/Raid Management
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/** CMSG_GROUP_UNINVITE_GUID packet builder */
|
||||||
|
class GroupUninvitePacket {
|
||||||
|
public:
|
||||||
|
static network::Packet build(const std::string& playerName);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** CMSG_GROUP_DISBAND packet builder */
|
||||||
|
class GroupDisbandPacket {
|
||||||
|
public:
|
||||||
|
static network::Packet build();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** MSG_RAID_TARGET_UPDATE packet builder */
|
||||||
|
class RaidTargetUpdatePacket {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Build raid target marker update packet
|
||||||
|
* @param targetIndex 0-7 for raid icons, 0 = MainTank, 1 = MainAssist
|
||||||
|
* @param targetGuid GUID to mark, or 0 to clear
|
||||||
|
*/
|
||||||
|
static network::Packet build(uint8_t targetIndex, uint64_t targetGuid);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** CMSG_REQUEST_RAID_INFO packet builder */
|
||||||
|
class RequestRaidInfoPacket {
|
||||||
|
public:
|
||||||
|
static network::Packet build();
|
||||||
|
};
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Random Roll
|
// Random Roll
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
@ -1315,12 +1348,6 @@ public:
|
||||||
static network::Packet build();
|
static network::Packet build();
|
||||||
};
|
};
|
||||||
|
|
||||||
/** CMSG_GROUP_DISBAND (leave party) packet builder */
|
|
||||||
class GroupDisbandPacket {
|
|
||||||
public:
|
|
||||||
static network::Packet build();
|
|
||||||
};
|
|
||||||
|
|
||||||
/** SMSG_GROUP_LIST parser */
|
/** SMSG_GROUP_LIST parser */
|
||||||
class GroupListParser {
|
class GroupListParser {
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -2116,6 +2116,109 @@ void GameHandler::replyToLastWhisper(const std::string& message) {
|
||||||
LOG_INFO("Replied to ", lastWhisperSender_, ": ", message);
|
LOG_INFO("Replied to ", lastWhisperSender_, ": ", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameHandler::uninvitePlayer(const std::string& playerName) {
|
||||||
|
if (state != WorldState::IN_WORLD || !socket) {
|
||||||
|
LOG_WARNING("Cannot uninvite player: not in world or not connected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playerName.empty()) {
|
||||||
|
addSystemChatMessage("You must specify a player name to uninvite.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto packet = GroupUninvitePacket::build(playerName);
|
||||||
|
socket->send(packet);
|
||||||
|
addSystemChatMessage("Removed " + playerName + " from the group.");
|
||||||
|
LOG_INFO("Uninvited player: ", playerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameHandler::leaveParty() {
|
||||||
|
if (state != WorldState::IN_WORLD || !socket) {
|
||||||
|
LOG_WARNING("Cannot leave party: not in world or not connected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto packet = GroupDisbandPacket::build();
|
||||||
|
socket->send(packet);
|
||||||
|
addSystemChatMessage("You have left the group.");
|
||||||
|
LOG_INFO("Left party/raid");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameHandler::setMainTank(uint64_t targetGuid) {
|
||||||
|
if (state != WorldState::IN_WORLD || !socket) {
|
||||||
|
LOG_WARNING("Cannot set main tank: not in world or not connected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetGuid == 0) {
|
||||||
|
addSystemChatMessage("You must have a target selected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main tank uses index 0
|
||||||
|
auto packet = RaidTargetUpdatePacket::build(0, targetGuid);
|
||||||
|
socket->send(packet);
|
||||||
|
addSystemChatMessage("Main tank set.");
|
||||||
|
LOG_INFO("Set main tank: 0x", std::hex, targetGuid, std::dec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameHandler::setMainAssist(uint64_t targetGuid) {
|
||||||
|
if (state != WorldState::IN_WORLD || !socket) {
|
||||||
|
LOG_WARNING("Cannot set main assist: not in world or not connected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetGuid == 0) {
|
||||||
|
addSystemChatMessage("You must have a target selected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main assist uses index 1
|
||||||
|
auto packet = RaidTargetUpdatePacket::build(1, targetGuid);
|
||||||
|
socket->send(packet);
|
||||||
|
addSystemChatMessage("Main assist set.");
|
||||||
|
LOG_INFO("Set main assist: 0x", std::hex, targetGuid, std::dec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameHandler::clearMainTank() {
|
||||||
|
if (state != WorldState::IN_WORLD || !socket) {
|
||||||
|
LOG_WARNING("Cannot clear main tank: not in world or not connected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear main tank by setting GUID to 0
|
||||||
|
auto packet = RaidTargetUpdatePacket::build(0, 0);
|
||||||
|
socket->send(packet);
|
||||||
|
addSystemChatMessage("Main tank cleared.");
|
||||||
|
LOG_INFO("Cleared main tank");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameHandler::clearMainAssist() {
|
||||||
|
if (state != WorldState::IN_WORLD || !socket) {
|
||||||
|
LOG_WARNING("Cannot clear main assist: not in world or not connected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear main assist by setting GUID to 0
|
||||||
|
auto packet = RaidTargetUpdatePacket::build(1, 0);
|
||||||
|
socket->send(packet);
|
||||||
|
addSystemChatMessage("Main assist cleared.");
|
||||||
|
LOG_INFO("Cleared main assist");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameHandler::requestRaidInfo() {
|
||||||
|
if (state != WorldState::IN_WORLD || !socket) {
|
||||||
|
LOG_WARNING("Cannot request raid info: not in world or not connected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto packet = RequestRaidInfoPacket::build();
|
||||||
|
socket->send(packet);
|
||||||
|
addSystemChatMessage("Requesting raid lockout information...");
|
||||||
|
LOG_INFO("Requested raid info");
|
||||||
|
}
|
||||||
|
|
||||||
void GameHandler::releaseSpirit() {
|
void GameHandler::releaseSpirit() {
|
||||||
if (!playerDead_) return;
|
if (!playerDead_) return;
|
||||||
if (socket && state == WorldState::IN_WORLD) {
|
if (socket && state == WorldState::IN_WORLD) {
|
||||||
|
|
|
||||||
|
|
@ -1421,6 +1421,37 @@ network::Packet DuelCancelPacket::build() {
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Party/Raid Management
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
network::Packet GroupUninvitePacket::build(const std::string& playerName) {
|
||||||
|
network::Packet packet(static_cast<uint16_t>(Opcode::CMSG_GROUP_UNINVITE_GUID));
|
||||||
|
packet.writeString(playerName);
|
||||||
|
LOG_DEBUG("Built CMSG_GROUP_UNINVITE_GUID for player: ", playerName);
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
network::Packet GroupDisbandPacket::build() {
|
||||||
|
network::Packet packet(static_cast<uint16_t>(Opcode::CMSG_GROUP_DISBAND));
|
||||||
|
LOG_DEBUG("Built CMSG_GROUP_DISBAND");
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
network::Packet RaidTargetUpdatePacket::build(uint8_t targetIndex, uint64_t targetGuid) {
|
||||||
|
network::Packet packet(static_cast<uint16_t>(Opcode::MSG_RAID_TARGET_UPDATE));
|
||||||
|
packet.writeUInt8(targetIndex);
|
||||||
|
packet.writeUInt64(targetGuid);
|
||||||
|
LOG_DEBUG("Built MSG_RAID_TARGET_UPDATE, index: ", (uint32_t)targetIndex, ", guid: 0x", std::hex, targetGuid, std::dec);
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
network::Packet RequestRaidInfoPacket::build() {
|
||||||
|
network::Packet packet(static_cast<uint16_t>(Opcode::CMSG_REQUEST_RAID_INFO));
|
||||||
|
LOG_DEBUG("Built CMSG_REQUEST_RAID_INFO");
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Random Roll
|
// Random Roll
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
@ -2092,11 +2123,6 @@ network::Packet GroupDeclinePacket::build() {
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
network::Packet GroupDisbandPacket::build() {
|
|
||||||
network::Packet packet(static_cast<uint16_t>(Opcode::CMSG_GROUP_DISBAND));
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GroupListParser::parse(network::Packet& packet, GroupListData& data) {
|
bool GroupListParser::parse(network::Packet& packet, GroupListData& data) {
|
||||||
data.groupType = packet.readUInt8();
|
data.groupType = packet.readUInt8();
|
||||||
data.subGroup = packet.readUInt8();
|
data.subGroup = packet.readUInt8();
|
||||||
|
|
|
||||||
|
|
@ -1330,6 +1330,74 @@ void GameScreen::sendChatMessage(game::GameHandler& gameHandler) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Party/Raid management commands
|
||||||
|
if (cmdLower == "uninvite" || cmdLower == "kick") {
|
||||||
|
if (spacePos != std::string::npos) {
|
||||||
|
std::string playerName = command.substr(spacePos + 1);
|
||||||
|
gameHandler.uninvitePlayer(playerName);
|
||||||
|
} else {
|
||||||
|
game::MessageChatData msg;
|
||||||
|
msg.type = game::ChatType::SYSTEM;
|
||||||
|
msg.language = game::ChatLanguage::UNIVERSAL;
|
||||||
|
msg.message = "Usage: /uninvite <player name>";
|
||||||
|
gameHandler.addLocalChatMessage(msg);
|
||||||
|
}
|
||||||
|
chatInputBuffer[0] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLower == "leave" || cmdLower == "leaveparty") {
|
||||||
|
gameHandler.leaveParty();
|
||||||
|
chatInputBuffer[0] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLower == "maintank" || cmdLower == "mt") {
|
||||||
|
if (gameHandler.hasTarget()) {
|
||||||
|
gameHandler.setMainTank(gameHandler.getTargetGuid());
|
||||||
|
} else {
|
||||||
|
game::MessageChatData msg;
|
||||||
|
msg.type = game::ChatType::SYSTEM;
|
||||||
|
msg.language = game::ChatLanguage::UNIVERSAL;
|
||||||
|
msg.message = "You must target a player to set as main tank.";
|
||||||
|
gameHandler.addLocalChatMessage(msg);
|
||||||
|
}
|
||||||
|
chatInputBuffer[0] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLower == "mainassist" || cmdLower == "ma") {
|
||||||
|
if (gameHandler.hasTarget()) {
|
||||||
|
gameHandler.setMainAssist(gameHandler.getTargetGuid());
|
||||||
|
} else {
|
||||||
|
game::MessageChatData msg;
|
||||||
|
msg.type = game::ChatType::SYSTEM;
|
||||||
|
msg.language = game::ChatLanguage::UNIVERSAL;
|
||||||
|
msg.message = "You must target a player to set as main assist.";
|
||||||
|
gameHandler.addLocalChatMessage(msg);
|
||||||
|
}
|
||||||
|
chatInputBuffer[0] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLower == "clearmaintank") {
|
||||||
|
gameHandler.clearMainTank();
|
||||||
|
chatInputBuffer[0] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLower == "clearmainassist") {
|
||||||
|
gameHandler.clearMainAssist();
|
||||||
|
chatInputBuffer[0] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLower == "raidinfo") {
|
||||||
|
gameHandler.requestRaidInfo();
|
||||||
|
chatInputBuffer[0] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Chat channel slash commands
|
// Chat channel slash commands
|
||||||
bool isChannelCommand = false;
|
bool isChannelCommand = false;
|
||||||
if (cmdLower == "s" || cmdLower == "say") {
|
if (cmdLower == "s" || cmdLower == "say") {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue