mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
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:
parent
c6e39707de
commit
c44477fbee
4 changed files with 61 additions and 6 deletions
|
|
@ -736,6 +736,10 @@ public:
|
|||
bool showDeathDialog() const { return playerDead_ && !releasedSpirit_; }
|
||||
bool showResurrectDialog() const { return resurrectRequestPending_; }
|
||||
const std::string& getResurrectCasterName() const { return resurrectCasterName_; }
|
||||
/** True when ghost is within 40 yards of corpse position (same map). */
|
||||
bool canReclaimCorpse() const;
|
||||
/** Send CMSG_RECLAIM_CORPSE; noop if not a ghost or not near corpse. */
|
||||
void reclaimCorpse();
|
||||
void releaseSpirit();
|
||||
void acceptResurrect();
|
||||
void declineResurrect();
|
||||
|
|
@ -2150,6 +2154,8 @@ private:
|
|||
float serverPitchRate_ = 3.14159f;
|
||||
bool playerDead_ = false;
|
||||
bool releasedSpirit_ = false;
|
||||
uint32_t corpseMapId_ = 0;
|
||||
float corpseX_ = 0.0f, corpseY_ = 0.0f, corpseZ_ = 0.0f;
|
||||
// Death Knight runes (class 6): slots 0-1=Blood, 2-3=Unholy, 4-5=Frost initially
|
||||
std::array<RuneSlot, 6> playerRunes_ = [] {
|
||||
std::array<RuneSlot, 6> r{};
|
||||
|
|
|
|||
|
|
@ -228,6 +228,7 @@ private:
|
|||
void renderTrainerWindow(game::GameHandler& gameHandler);
|
||||
void renderTaxiWindow(game::GameHandler& gameHandler);
|
||||
void renderDeathScreen(game::GameHandler& gameHandler);
|
||||
void renderReclaimCorpseButton(game::GameHandler& gameHandler);
|
||||
void renderResurrectDialog(game::GameHandler& gameHandler);
|
||||
void renderEscapeMenu();
|
||||
void renderSettingsWindow();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -433,6 +433,7 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
|||
// renderQuestMarkers(gameHandler); // Disabled - using 3D billboard markers now
|
||||
renderMinimapMarkers(gameHandler);
|
||||
renderDeathScreen(gameHandler);
|
||||
renderReclaimCorpseButton(gameHandler);
|
||||
renderResurrectDialog(gameHandler);
|
||||
renderChatBubbles(gameHandler);
|
||||
renderEscapeMenu();
|
||||
|
|
@ -7013,6 +7014,34 @@ void GameScreen::renderDeathScreen(game::GameHandler& gameHandler) {
|
|||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
void GameScreen::renderReclaimCorpseButton(game::GameHandler& gameHandler) {
|
||||
if (!gameHandler.isPlayerGhost() || !gameHandler.canReclaimCorpse()) return;
|
||||
|
||||
auto* window = core::Application::getInstance().getWindow();
|
||||
float screenW = window ? static_cast<float>(window->getWidth()) : 1280.0f;
|
||||
float screenH = window ? static_cast<float>(window->getHeight()) : 720.0f;
|
||||
|
||||
float btnW = 220.0f, btnH = 36.0f;
|
||||
ImGui::SetNextWindowPos(ImVec2(screenW / 2 - btnW / 2, screenH * 0.72f), ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize(ImVec2(btnW + 16.0f, btnH + 16.0f), ImGuiCond_Always);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.0f, 8.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.7f));
|
||||
if (ImGui::Begin("##ReclaimCorpse", nullptr,
|
||||
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoBringToFrontOnFocus)) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.15f, 0.35f, 0.15f, 1.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.25f, 0.55f, 0.25f, 1.0f));
|
||||
if (ImGui::Button("Resurrect from Corpse", ImVec2(btnW, btnH))) {
|
||||
gameHandler.reclaimCorpse();
|
||||
}
|
||||
ImGui::PopStyleColor(2);
|
||||
}
|
||||
ImGui::End();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
|
||||
void GameScreen::renderResurrectDialog(game::GameHandler& gameHandler) {
|
||||
if (!gameHandler.showResurrectDialog()) return;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue