class_name Dungeons extends RefCounted ## The kinds of dungeon run, defined in code like everything else in ## `src/content/`. ## ## [constant ORDER] does double duty: it is the wire order for the dungeon id, ## and it is the order the hub's portals are assigned. The Nth `P` marker in the ## lobby stamp (reading order) opens the Nth entry here, so adding a dungeon is ## one entry plus one marker. const STANDARD := &"warden_descent" const PROVING := &"proving_grounds" const ORDER: Array[StringName] = [ STANDARD, PROVING, ] static func default_id() -> StringName: return STANDARD static func get_def(id: StringName) -> DungeonDef: match id: STANDARD: return standard() PROVING: return proving_grounds() return null ## Falls back to the standard run rather than to null. An id off the wire has to ## resolve to something playable, and "the normal dungeon" is the safe answer. static func get_or_default(id: StringName) -> DungeonDef: var d := get_def(id) return d if d != null else standard() static func index_of(id: StringName) -> int: return maxi(ORDER.find(id), 0) static func by_index(index: int) -> StringName: if index < 0 or index >= ORDER.size(): return default_id() return ORDER[index] # --- The dungeons ----------------------------------------------------------- ## The real thing. Every multiplier is 1.0, which is the point: this is the ## baseline the other definitions are described against. static func standard() -> DungeonDef: var d := DungeonDef.new() d.id = STANDARD d.display_name = "Warden's Descent" d.subtitle = "the real run" d.tint = Color(0.5, 0.9, 1.0) return d ## A test harness you can walk into. ## ## Same generator, same rooms, same enemies and the same Warden -- everything ## dies far faster and drops far more often, so a manual pass over the loot, ## the inventory and all four boss phases takes a couple of minutes instead of a ## quarter of an hour. Being reachable from the hub rather than hidden behind a ## launch flag is most of the value: you can compare the two back to back in one ## session without restarting the server. static func proving_grounds() -> DungeonDef: var d := DungeonDef.new() d.id = PROVING d.display_name = "Proving Grounds" d.subtitle = "for testing -- fragile, generous" d.enemy_hp_mult = 0.2 d.boss_hp_mult = 0.08 # 0.08 -> 0.8 for trash. High enough that a handful of kills fills a bag, # which is what makes the four-slot limit and dropping testable at all. d.loot_chance_mult = 10.0 d.tint = Color(1.0, 0.75, 0.35) return d