Implement corpse reclaim: store death position and show Resurrect button

When a player releases spirit, the server sends SMSG_DEATH_RELEASE_LOC
with the corpse map and position. Store this so the ghost can reclaim.

New flow:
- SMSG_DEATH_RELEASE_LOC now stores corpseMapId_/corpseX_/Y_/Z_ instead
  of logging and discarding
- canReclaimCorpse(): true when ghost is on same map within 40 yards of
  stored corpse position
- reclaimCorpse(): sends CMSG_RECLAIM_CORPSE (no payload)
- renderReclaimCorpseButton(): shows "Resurrect from Corpse" button at
  bottom-center when canReclaimCorpse() is true
This commit is contained in:
Kelsi 2026-03-09 22:31:56 -07:00
parent c6e39707de
commit c44477fbee
4 changed files with 61 additions and 6 deletions

View file

@ -2021,13 +2021,14 @@ void GameHandler::handlePacket(network::Packet& packet) {
break;
}
case Opcode::SMSG_DEATH_RELEASE_LOC: {
// uint32 mapId + float x + float y + float z — spirit healer position
// uint32 mapId + float x + float y + float z — corpse/spirit healer position
if (packet.getSize() - packet.getReadPos() >= 16) {
uint32_t mapId = packet.readUInt32();
float x = packet.readFloat();
float y = packet.readFloat();
float z = packet.readFloat();
LOG_INFO("SMSG_DEATH_RELEASE_LOC: map=", mapId, " x=", x, " y=", y, " z=", z);
corpseMapId_ = packet.readUInt32();
corpseX_ = packet.readFloat();
corpseY_ = packet.readFloat();
corpseZ_ = packet.readFloat();
LOG_INFO("SMSG_DEATH_RELEASE_LOC: map=", corpseMapId_,
" x=", corpseX_, " y=", corpseY_, " z=", corpseZ_);
}
break;
}
@ -9459,6 +9460,24 @@ void GameHandler::releaseSpirit() {
}
}
bool GameHandler::canReclaimCorpse() const {
if (!releasedSpirit_ || corpseMapId_ == 0) return false;
// Only if ghost is on the same map as their corpse
if (currentMapId_ != corpseMapId_) return false;
// Must be within 40 yards (server also validates proximity)
float dx = movementInfo.x - corpseX_;
float dy = movementInfo.y - corpseY_;
float dz = movementInfo.z - corpseZ_;
return (dx*dx + dy*dy + dz*dz) <= (40.0f * 40.0f);
}
void GameHandler::reclaimCorpse() {
if (!canReclaimCorpse() || !socket) return;
network::Packet packet(wireOpcode(Opcode::CMSG_RECLAIM_CORPSE));
socket->send(packet);
LOG_INFO("Sent CMSG_RECLAIM_CORPSE");
}
void GameHandler::activateSpiritHealer(uint64_t npcGuid) {
if (state != WorldState::IN_WORLD || !socket) return;
pendingSpiritHealerGuid_ = npcGuid;