Kelsidavis-WoWee/include/pipeline/wowee_instance_lockouts.hpp

122 lines
4.5 KiB
C++
Raw Normal View History

feat(editor): add WHLD (Instance Lockout Schedule) open catalog format Open replacement for the engine-side instance reset timer logic plus the per-map InstanceTemplate.dbc reset fields. Defines how often each (map × difficulty) combination resets its lockout, how many boss kills each character can claim per lockout window, and the number of bonus rolls available (Cataclysm+ stub for forward compatibility). One entry per (map × difficulty × group size). Icecrown Citadel 10-Normal weekly, ICC 25-Normal weekly, ICC 10-Heroic weekly, and ICC 25-Heroic weekly are four separate entries with the same mapId but different difficultyId and resetIntervalMs. Cross-references back to WMS (mapId), WCDF (difficultyId), and forward to WBOS — the encounters bound to one lockout are the WBOS entries whose (mapId, difficultyId) pair matches. Four lockout kinds capture the canonical reset cadences: - Daily (24h, 86400000ms) — heroic dungeons, daily quests - Weekly (7d, 604800000ms) — raid lockouts - SemiWeekly (3.5d, 302400000ms) — Cata+ split lockouts - Custom (arbitrary intervalMs) — Wintergrasp 2.5h, holiday events with non-standard cadence nextResetMs(lockoutId, currentMs) is the engine helper that returns the next reset wall-clock millis after a given current time, rounded up to the nearest interval boundary. The engine overrides the epoch with its configured server reset time (typically Tuesday 8:00am server-local), but the catalog provides the interval shape. The info renderer pretty-prints intervals: 86400000ms reads as "1d", 9000000ms as "150m", which matches how server admins think about reset cadences. Three preset emitters: --gen-hld (4 ICC raid weekly lockouts), --gen-hld-dungeon (4 5-man heroic daily lockouts), --gen-hld-event (3 world-event lockouts including Wintergrasp's canonical Custom 2.5h interval). Validation enforces id+name+kind+resetIntervalMs presence, no duplicate ids; warns on non-standard raidGroupSize, kind/interval mismatches (Daily kind without 24h interval, Weekly kind without 7d interval), and 0 boss kill cap (instance grants no lockout-bound progress, every visit is fresh). Wired through the cross-format table; WHLD appears in all 18 cross-format utilities. Format count 91 -> 92; CLI flag count 1062 -> 1067.
2026-05-09 23:51:49 -07:00
#pragma once
#include <cstdint>
#include <string>
#include <vector>
namespace wowee {
namespace pipeline {
// Wowee Open Instance Lockout Schedule catalog (.whld)
// — novel replacement for the engine-side instance reset
// timer logic plus the per-map InstanceTemplate.dbc reset
// fields. Defines how often each (map × difficulty)
// combination resets its lockout, how many boss kills
// each character can claim per lockout window, and the
// number of bonus rolls available (Cataclysm+ feature
// stubbed for forward compatibility).
//
// One entry per (map × difficulty × group size) — Icecrown
// Citadel 10-Normal weekly, ICC 25-Normal weekly, ICC
// 10-Heroic weekly, and ICC 25-Heroic weekly are four
// separate entries with the same mapId but different
// difficultyId and resetIntervalMs.
//
// Cross-references with previously-added formats:
// WMS: mapId references the instance map.
// WCDF: difficultyId references the difficulty routing
// entry that maps base creature -> variants.
// WBOS: encounters in this lockout are the WBOS entries
// whose (mapId, difficultyId) pair matches.
//
// Binary layout (little-endian):
// magic[4] = "WHLD"
// version (uint32) = current 1
// nameLen + name (catalog label)
// entryCount (uint32)
// entries (each):
// lockoutId (uint32)
// nameLen + name
// descLen + description
// mapId (uint32)
// difficultyId (uint32)
// resetIntervalMs (uint32)
// maxBossKillsPerLockout (uint8) / bonusRolls (uint8)
// raidLockoutKind (uint8) / raidGroupSize (uint8)
// iconColorRGBA (uint32)
struct WoweeInstanceLockout {
enum LockoutKind : uint8_t {
Daily = 0, // 24h reset (5-man heroics, daily quests)
Weekly = 1, // 7d reset (raid lockouts)
SemiWeekly = 2, // 3.5d reset (Cata+ split lockouts)
Custom = 3, // arbitrary intervalMs
};
static constexpr uint32_t kDailyMs = 86400000u; // 24 * 3600 * 1000
static constexpr uint32_t kWeeklyMs = 604800000u; // 7 * kDailyMs
static constexpr uint32_t kSemiWeeklyMs = 302400000u; // 3.5d
struct Entry {
uint32_t lockoutId = 0;
std::string name;
std::string description;
uint32_t mapId = 0;
uint32_t difficultyId = 0;
uint32_t resetIntervalMs = 0;
uint8_t maxBossKillsPerLockout = 0;
uint8_t bonusRolls = 0;
uint8_t raidLockoutKind = Weekly;
uint8_t raidGroupSize = 10; // 5 / 10 / 25 / 40
uint32_t iconColorRGBA = 0xFFFFFFFFu;
};
std::string name;
std::vector<Entry> entries;
bool isValid() const { return !entries.empty(); }
const Entry* findById(uint32_t lockoutId) const;
// Returns all lockouts bound to a given map (typically
// all 4 difficulty variants of one raid). Used by the
// raid-finder UI to populate the difficulty picker.
std::vector<const Entry*> findByMap(uint32_t mapId) const;
// Returns the next reset wall-clock millis after the
// given current time, assuming the standard Tuesday
// reset epoch. Engines override with their server's
// chosen reset time.
uint64_t nextResetMs(uint32_t lockoutId,
uint64_t currentMs) const;
static const char* lockoutKindName(uint8_t k);
};
class WoweeInstanceLockoutLoader {
public:
static bool save(const WoweeInstanceLockout& cat,
const std::string& basePath);
static WoweeInstanceLockout load(const std::string& basePath);
static bool exists(const std::string& basePath);
// Preset emitters used by --gen-hld* variants.
//
// makeRaidWeekly — 4 raid weekly lockouts (ICC 10N /
// ICC 25N / ICC 10H / ICC 25H) with
// 12-boss kill caps and 7-day
// reset.
// makeDungeonDaily — 4 5-man daily heroic lockouts
// (HoR / FoS / PoS / TotC) with
// 24h reset and 1-boss caps each.
// makeWorldEvent — 3 special event lockouts
// (Brewfest daily / Hallow's End
// pumpkin daily / Wintergrasp
// battle 2.5h reset).
static WoweeInstanceLockout makeRaidWeekly(const std::string& catalogName);
static WoweeInstanceLockout makeDungeonDaily(const std::string& catalogName);
static WoweeInstanceLockout makeWorldEvent(const std::string& catalogName);
};
} // namespace pipeline
} // namespace wowee