From 42222e4095b47aec6531c46a3204b196ae06b5af Mon Sep 17 00:00:00 2001 From: Kelsi Date: Sat, 21 Mar 2026 14:08:47 -0700 Subject: [PATCH] feat: handle MSG_CORPSE_QUERY for server-authoritative corpse position Parse MSG_CORPSE_QUERY server response to get the exact corpse location and map ID. Also send the query after releasing spirit so the minimap corpse marker points to the correct position even when the player died in an instance and releases to an outdoor graveyard. Previously the corpse position was only set from the entity death location, which could be wrong for cross-map ghost runs. --- src/game/game_handler.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index 114a55c2..1d6f7365 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -2780,6 +2780,25 @@ void GameHandler::handlePacket(network::Packet& packet) { barberShopOpen_ = true; if (addonEventCallback_) addonEventCallback_("BARBER_SHOP_OPEN", {}); break; + case Opcode::MSG_CORPSE_QUERY: { + // Server response: uint8 found + (if found) uint32 mapId + float x + float y + float z + uint32 corpseMapId + if (packet.getSize() - packet.getReadPos() < 1) break; + uint8_t found = packet.readUInt8(); + if (found && packet.getSize() - packet.getReadPos() >= 20) { + /*uint32_t mapId =*/ packet.readUInt32(); + float cx = packet.readFloat(); + float cy = packet.readFloat(); + float cz = packet.readFloat(); + uint32_t corpseMapId = packet.readUInt32(); + // Server coords: x=west, y=north (opposite of canonical) + corpseX_ = cx; + corpseY_ = cy; + corpseZ_ = cz; + corpseMapId_ = corpseMapId; + LOG_INFO("MSG_CORPSE_QUERY: corpse at (", cx, ",", cy, ",", cz, ") map=", corpseMapId); + } + break; + } case Opcode::SMSG_FEIGN_DEATH_RESISTED: addUIError("Your Feign Death was resisted."); addSystemChatMessage("Your Feign Death attempt was resisted."); @@ -14728,6 +14747,9 @@ void GameHandler::releaseSpirit() { repopPending_ = true; lastRepopRequestMs_ = static_cast(now); LOG_INFO("Sent CMSG_REPOP_REQUEST (Release Spirit)"); + // Query server for authoritative corpse position (response updates corpseX_/Y_/Z_) + network::Packet cq(wireOpcode(Opcode::MSG_CORPSE_QUERY)); + socket->send(cq); } }