Kelsidavis-WoWee/include/pipeline/wowee_instance_lockouts.hpp
Kelsi 321c2610d0 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

121 lines
4.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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