From fb8c251a821d9150b6637bc5376c251b867b1ae0 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Thu, 12 Mar 2026 21:28:24 -0700 Subject: [PATCH] feat: implement SMSG_ACHIEVEMENT_DELETED, SMSG_CRITERIA_DELETED, SMSG_FORCED_DEATH_UPDATE - SMSG_ACHIEVEMENT_DELETED: removes achievement from earnedAchievements_ and achievementDates_ so the achievements UI stays accurate after revocation - SMSG_CRITERIA_DELETED: removes criteria from criteriaProgress_ tracking - SMSG_FORCED_DEATH_UPDATE: sets playerDead_ when server force-kills the player (GM command, scripted events) instead of silently consuming --- src/game/game_handler.cpp | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index 07b56112..d6f03a03 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -2307,10 +2307,16 @@ void GameHandler::handlePacket(network::Packet& packet) { case Opcode::SMSG_DAMAGE_CALC_LOG: case Opcode::SMSG_DYNAMIC_DROP_ROLL_RESULT: case Opcode::SMSG_DESTRUCTIBLE_BUILDING_DAMAGE: - case Opcode::SMSG_FORCED_DEATH_UPDATE: // Consume — handled by broader object update or not yet implemented packet.setReadPos(packet.getSize()); break; + case Opcode::SMSG_FORCED_DEATH_UPDATE: + // Server forces player into dead state (GM command, scripted event, etc.) + playerDead_ = true; + if (ghostStateCallback_) ghostStateCallback_(false); // dead but not ghost yet + LOG_INFO("SMSG_FORCED_DEATH_UPDATE: player force-killed"); + packet.setReadPos(packet.getSize()); + break; // ---- Zone defense messages ---- case Opcode::SMSG_DEFENSE_MESSAGE: { @@ -2392,11 +2398,27 @@ void GameHandler::handlePacket(network::Packet& packet) { // Time bias — consume without processing packet.setReadPos(packet.getSize()); break; - case Opcode::SMSG_ACHIEVEMENT_DELETED: - case Opcode::SMSG_CRITERIA_DELETED: - // Consume achievement/criteria removal notifications + case Opcode::SMSG_ACHIEVEMENT_DELETED: { + // uint32 achievementId — remove from local earned set + if (packet.getSize() - packet.getReadPos() >= 4) { + uint32_t achId = packet.readUInt32(); + earnedAchievements_.erase(achId); + achievementDates_.erase(achId); + LOG_DEBUG("SMSG_ACHIEVEMENT_DELETED: id=", achId); + } packet.setReadPos(packet.getSize()); break; + } + case Opcode::SMSG_CRITERIA_DELETED: { + // uint32 criteriaId — remove from local criteria progress + if (packet.getSize() - packet.getReadPos() >= 4) { + uint32_t critId = packet.readUInt32(); + criteriaProgress_.erase(critId); + LOG_DEBUG("SMSG_CRITERIA_DELETED: id=", critId); + } + packet.setReadPos(packet.getSize()); + break; + } // ---- Combat clearing ---- case Opcode::SMSG_ATTACKSWING_DEADTARGET: