fix: use expansion-aware explored zone count to prevent fog-of-war corruption

Classic 1.12 and Turtle WoW have only 64 PLAYER_EXPLORED_ZONES uint32
fields (zone IDs pack into 2048 bits). TBC and WotLK use 128 (needed for
Outland/Northrend zone IDs up to bit 4095).

The hardcoded PLAYER_EXPLORED_ZONES_COUNT=128 caused extractExploredZoneFields
to read 64 extra fields beyond the actual zone block in Classic/Turtle —
consuming PLAYER_REST_STATE_EXPERIENCE, PLAYER_FIELD_COINAGE, and character-
points fields as zone flags. On the world map, this could mark zones as
explored based on random bit patterns in those unrelated fields.

Add `exploredZonesCount()` virtual method to PacketParsers (default=128,
Classic/Turtle override=64) and use it in extractExploredZoneFields to
limit reads to the correct block and zero-fill remaining slots.
This commit is contained in:
Kelsi 2026-03-10 23:18:16 -07:00
parent 1b55ebb387
commit 3a7ff71262
2 changed files with 22 additions and 1 deletions

View file

@ -17556,18 +17556,31 @@ void GameHandler::extractSkillFields(const std::map<uint16_t, uint32_t>& fields)
}
void GameHandler::extractExploredZoneFields(const std::map<uint16_t, uint32_t>& fields) {
// Number of explored-zone uint32 fields varies by expansion:
// Classic/Turtle = 64, TBC/WotLK = 128. Always allocate 128 for world-map
// bit lookups, but only read the expansion-specific count to avoid reading
// player money or rest-XP fields as zone flags.
const size_t zoneCount = packetParsers_
? static_cast<size_t>(packetParsers_->exploredZonesCount())
: PLAYER_EXPLORED_ZONES_COUNT;
if (playerExploredZones_.size() != PLAYER_EXPLORED_ZONES_COUNT) {
playerExploredZones_.assign(PLAYER_EXPLORED_ZONES_COUNT, 0u);
}
bool foundAny = false;
for (size_t i = 0; i < PLAYER_EXPLORED_ZONES_COUNT; i++) {
for (size_t i = 0; i < zoneCount; i++) {
const uint16_t fieldIdx = static_cast<uint16_t>(fieldIndex(UF::PLAYER_EXPLORED_ZONES_START) + i);
auto it = fields.find(fieldIdx);
if (it == fields.end()) continue;
playerExploredZones_[i] = it->second;
foundAny = true;
}
// Zero out slots beyond the expansion's zone count to prevent stale data
// from polluting the fog-of-war display.
for (size_t i = zoneCount; i < PLAYER_EXPLORED_ZONES_COUNT; i++) {
playerExploredZones_[i] = 0u;
}
if (foundAny) {
hasPlayerExploredZones_ = true;