Add /inspect command to view player equipment

- Add CMSG_INSPECT (0x114) and SMSG_INSPECT_RESULTS (0x115) opcodes
- Implement InspectPacket builder for sending inspect requests
- Add inspectTarget() method to GameHandler with validation
- Add /inspect slash command in chat system
- Validate target is a player before sending inspect request
- Show helpful error messages for invalid inspect attempts
- Display confirmation message when inspect request is sent
This commit is contained in:
kelsi davis 2026-02-07 12:37:13 -08:00
parent 4da8c75af4
commit 8b8e32e716
6 changed files with 51 additions and 0 deletions

View file

@ -202,6 +202,9 @@ public:
bool hasTarget() const { return targetGuid != 0; }
void tabTarget(float playerX, float playerY, float playerZ);
// Inspection
void inspectTarget();
// ---- Phase 1: Name queries ----
void queryPlayerName(uint64_t guid);
void queryCreatureInfo(uint32_t entry, uint64_t guid);

View file

@ -166,6 +166,8 @@ enum class Opcode : uint16_t {
CMSG_USE_ITEM = 0x00AB,
CMSG_AUTOEQUIP_ITEM = 0x10A,
SMSG_INVENTORY_CHANGE_FAILURE = 0x112,
CMSG_INSPECT = 0x114,
SMSG_INSPECT_RESULTS = 0x115,
// ---- Death/Respawn ----
CMSG_REPOP_REQUEST = 0x015A,

View file

@ -664,6 +664,12 @@ public:
static network::Packet build(uint64_t guid);
};
/** CMSG_INSPECT packet builder */
class InspectPacket {
public:
static network::Packet build(uint64_t targetGuid);
};
/** CMSG_NAME_QUERY packet builder */
class NameQueryPacket {
public:

View file

@ -1504,6 +1504,32 @@ std::shared_ptr<Entity> GameHandler::getTarget() const {
return entityManager.getEntity(targetGuid);
}
void GameHandler::inspectTarget() {
if (state != WorldState::IN_WORLD || !socket) {
LOG_WARNING("Cannot inspect: not in world or not connected");
return;
}
if (targetGuid == 0) {
addSystemChatMessage("You must target a player to inspect.");
return;
}
auto target = getTarget();
if (!target || target->getType() != ObjectType::PLAYER) {
addSystemChatMessage("You can only inspect players.");
return;
}
auto packet = InspectPacket::build(targetGuid);
socket->send(packet);
auto player = std::static_pointer_cast<Player>(target);
std::string name = player->getName().empty() ? "Target" : player->getName();
addSystemChatMessage("Inspecting " + name + "...");
LOG_INFO("Sent inspect request for player: ", name, " (GUID: 0x", std::hex, targetGuid, std::dec, ")");
}
void GameHandler::releaseSpirit() {
if (!playerDead_) return;
if (socket && state == WorldState::IN_WORLD) {

View file

@ -1174,6 +1174,13 @@ network::Packet SetActiveMoverPacket::build(uint64_t guid) {
return packet;
}
network::Packet InspectPacket::build(uint64_t targetGuid) {
network::Packet packet(static_cast<uint16_t>(Opcode::CMSG_INSPECT));
packet.writeUInt64(targetGuid);
LOG_DEBUG("Built CMSG_INSPECT: target=0x", std::hex, targetGuid, std::dec);
return packet;
}
network::Packet NameQueryPacket::build(uint64_t playerGuid) {
network::Packet packet(static_cast<uint16_t>(Opcode::CMSG_NAME_QUERY));
packet.writeUInt64(playerGuid);

View file

@ -956,6 +956,13 @@ void GameScreen::sendChatMessage(game::GameHandler& gameHandler) {
return;
}
// /inspect command
if (cmdLower == "inspect") {
gameHandler.inspectTarget();
chatInputBuffer[0] = '\0';
return;
}
// Chat channel slash commands
bool isChannelCommand = false;
if (cmdLower == "s" || cmdLower == "say") {