fix: cache player death position so corpse reclaim works in Classic
Some checks are pending
Build / Build (arm64) (push) Waiting to run
Build / Build (x86-64) (push) Waiting to run
Build / Build (macOS arm64) (push) Waiting to run
Build / Build (windows-arm64) (push) Waiting to run
Build / Build (windows-x86-64) (push) Waiting to run
Security / CodeQL (C/C++) (push) Waiting to run
Security / Semgrep (push) Waiting to run
Security / Sanitizer Build (ASan/UBSan) (push) Waiting to run

Classic 1.12 does not send SMSG_DEATH_RELEASE_LOC, leaving corpseMapId_=0
and preventing the 'Resurrect from Corpse' button from appearing.

- When health reaches 0 via VALUES update, immediately cache movementInfo
  as corpse position (canonical->server axis swap applied correctly)
- Do the same on UNIT_DYNFLAG_DEAD set path
- Clear corpseMapId_ when ghost flag is removed (corpse reclaimed)
- Clear corpseMapId_ in same-map spirit-healer resurrection path

The CORPSE object detection (UPDATE_OBJECT) and SMSG_DEATH_RELEASE_LOC
(TBC/WotLK) will still override with exact server coordinates when received.
This commit is contained in:
Kelsi 2026-03-13 04:04:38 -07:00
parent 499638142e
commit 8f08d75748

View file

@ -10266,7 +10266,18 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
playerDead_ = true;
releasedSpirit_ = false;
stopAutoAttack();
LOG_INFO("Player died!");
// Cache death position as corpse location.
// Classic WoW does not send SMSG_DEATH_RELEASE_LOC, so
// this is the primary source for canReclaimCorpse().
// movementInfo is canonical (x=north, y=west); corpseX_/Y_
// are raw server coords (x=west, y=north) — swap axes.
corpseX_ = movementInfo.y; // canonical west = server X
corpseY_ = movementInfo.x; // canonical north = server Y
corpseZ_ = movementInfo.z;
corpseMapId_ = currentMapId_;
LOG_INFO("Player died! Corpse position cached at server=(",
corpseX_, ",", corpseY_, ",", corpseZ_,
") map=", corpseMapId_);
}
if (entity->getType() == ObjectType::UNIT && npcDeathCallback_) {
npcDeathCallback_(block.guid);
@ -10301,7 +10312,11 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
if (!wasDead && nowDead) {
playerDead_ = true;
releasedSpirit_ = false;
LOG_INFO("Player died (dynamic flags)");
corpseX_ = movementInfo.y;
corpseY_ = movementInfo.x;
corpseZ_ = movementInfo.z;
corpseMapId_ = currentMapId_;
LOG_INFO("Player died (dynamic flags). Corpse cached map=", corpseMapId_);
} else if (wasDead && !nowDead) {
playerDead_ = false;
releasedSpirit_ = false;
@ -10575,6 +10590,7 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
playerDead_ = false;
repopPending_ = false;
resurrectPending_ = false;
corpseMapId_ = 0; // corpse reclaimed
LOG_INFO("Player resurrected (PLAYER_FLAGS ghost cleared)");
if (ghostStateCallback_) ghostStateCallback_(false);
}
@ -19390,6 +19406,7 @@ void GameHandler::handleNewWorld(network::Packet& packet) {
repopPending_ = false;
pendingSpiritHealerGuid_ = 0;
resurrectCasterGuid_ = 0;
corpseMapId_ = 0;
hostileAttackers_.clear();
stopAutoAttack();
tabCycleStale = true;