A dungeon in every area
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
cd44709d80
commit
60b446acfd
3 changed files with 242 additions and 10 deletions
204
game.py
204
game.py
|
|
@ -1005,11 +1005,17 @@ def dungeon_scale(size: int) -> tuple[float, float]:
|
|||
|
||||
|
||||
def _dungeon_foe(action_id: str, variant: str, hp: float = 1.0, hits: float = 1.0, loot: float | None = None,
|
||||
level: int | None = None, archetype: str | None = None, name: str | None = None, big: bool = False,
|
||||
**extra) -> dict:
|
||||
"""One of a race's variants, as a dungeon enemy: `hp` times as tough (and worth as much more XP),
|
||||
hitting `hits` times as hard. It drops what its race does, `loot` (else `hp`) times as often."""
|
||||
hitting `hits` times as hard. It drops what its race does, `loot` (else `hp`) times as often. It can
|
||||
stand at another `level`, as another `archetype` (`big` for a boss's size), under another `name`."""
|
||||
action = next(a for a in COMBAT_ACTIONS if a["id"] == action_id)
|
||||
foe = next(v for v in action["enemy"]["variants"] if v["name"] == variant)
|
||||
if level or archetype or big:
|
||||
foe = monster(name or foe["name"], archetype or foe["archetype"], level or foe["level"], foe["attack"],
|
||||
foe["vulnerable"], foe["resists"], boss=big)
|
||||
foe = {**foe, "name": name or foe["name"]}
|
||||
return {**{key: foe[key] for key in ("name", "archetype", "level", "interval", "accuracy", "evasion",
|
||||
"attack", "vulnerable", "resists")},
|
||||
"boss": extra.pop("boss", False), "hp": round(foe["hp"] * hp), "max_hit": max(1, round(foe["max_hit"] * hits)),
|
||||
|
|
@ -1045,8 +1051,175 @@ DUNGEONS = {
|
|||
_dungeon_foe("fight_cave_trolls", "Troll bruiser", *FINAL_BOSS, 1, dormant=True)]),
|
||||
],
|
||||
},
|
||||
"dungeon_goblin_warren": {
|
||||
"name": "Goblin Warren", "area": "Greenwood", "tier": 0, "level": 8, "bonus_gold": 30,
|
||||
"pulls": [
|
||||
("Wolf den", [_dungeon_foe("fight_wolves", v, *TRASH, 1, level=6) for v in ("Grey wolf", "Timber wolf", "Grey wolf")]),
|
||||
("Tunnel mouth", [_dungeon_foe("fight_goblins", v, *TRASH, 1, level=6)
|
||||
for v in ("Goblin brute", "Goblin rogue", "Goblin warlock")]),
|
||||
("Old One-Eye", [_dungeon_foe("fight_wolves", "Wolf alpha", MINI_BOSS, 3.0, level=7, name="Old One-Eye", boss=True,
|
||||
abilities=["crushing_decree", "lunge"], enrage_at=150,
|
||||
phases=[{"at": 0.5, "say": "Aaaooo!", "wake": ["e1", "e2"]}]),
|
||||
_dungeon_foe("fight_wolves", "Grey wolf", *TRASH, 1, level=6, dormant=True),
|
||||
_dungeon_foe("fight_wolves", "Grey wolf", *TRASH, 1, level=6, dormant=True)]),
|
||||
("Fungus cave", [_dungeon_foe("fight_goblins", v, *TRASH, 1, level=6)
|
||||
for v in ("Goblin rogue", "Goblin rogue", "Goblin warlock")]),
|
||||
("Grizzik the Hexer", [_dungeon_foe("fight_goblins", "Goblin warlock", MINI_BOSS, 4.0, level=7, archetype="elite",
|
||||
name="Grizzik the Hexer", boss=True, abilities=["hex_storm", "hex_bolt"],
|
||||
enrage_at=150)]),
|
||||
("Throne cave", [_dungeon_foe("fight_goblins", v, *TRASH, 1, level=6)
|
||||
for v in ("Goblin brute", "Goblin brute", "Goblin warlock")]),
|
||||
("Goblin king", [_dungeon_foe("fight_goblins", "Goblin brute", *FINAL_BOSS, 2, level=9, archetype="boss",
|
||||
name="Goblin king", big=True, boss=True,
|
||||
abilities=["crushing_decree", "royal_stomp", "heavy_slam"], enrage_at=210,
|
||||
phases=[{"at": 0.5, "say": "Guards! Guards!", "wake": ["e1", "e2"]}]),
|
||||
_dungeon_foe("fight_goblins", "Goblin brute", *FINAL_BOSS, 1, level=6, dormant=True),
|
||||
_dungeon_foe("fight_goblins", "Goblin brute", *FINAL_BOSS, 1, level=6, dormant=True)]),
|
||||
],
|
||||
},
|
||||
"dungeon_bandit_stronghold": {
|
||||
"name": "Bandit Stronghold", "area": "Frontier", "tier": 2, "level": 40, "bonus_gold": 300,
|
||||
"pulls": [
|
||||
("Palisade", [_dungeon_foe("fight_scouts", v, *TRASH, 1, level=35)
|
||||
for v in ("Bandit brute", "Bandit archer", "Bandit archer")]),
|
||||
("Gate", [_dungeon_foe("fight_scouts", v, *TRASH, 1, level=35) for v in ("Bandit brute", "Bandit brute", "Hedge mage")]),
|
||||
("Bandit captain", [_dungeon_foe("fight_scouts", "Bandit brute", MINI_BOSS, 3.0, level=37, archetype="elite",
|
||||
name="Bandit captain", boss=True, abilities=["cheap_shot", "heavy_slam"],
|
||||
enrage_at=150)]),
|
||||
("Barracks", [_dungeon_foe("fight_scouts", v, *TRASH, 1, level=35)
|
||||
for v in ("Bandit brute", "Bandit archer", "Bandit archer", "Hedge mage")]),
|
||||
("Hedge witch", [_dungeon_foe("fight_scouts", "Hedge mage", MINI_BOSS, 5.5, level=37, archetype="elite",
|
||||
name="Hedge witch", boss=True, abilities=["witchfire", "hex_bolt"], enrage_at=150,
|
||||
phases=[{"at": 0.5, "say": "Cut them down!", "wake": ["e1", "e2"]}]),
|
||||
_dungeon_foe("fight_scouts", "Bandit archer", *TRASH, 1, level=35, dormant=True),
|
||||
_dungeon_foe("fight_scouts", "Bandit archer", *TRASH, 1, level=35, dormant=True)]),
|
||||
("Armoury", [_dungeon_foe("fight_scouts", v, *TRASH, 1, level=35) for v in ("Bandit brute", "Hedge mage", "Hedge mage")]),
|
||||
("Bandit warlord", [_dungeon_foe("fight_stronghold", "Bandit warlord", *FINAL_BOSS, 2, boss=True,
|
||||
abilities=["execute", "whirlwind", "heavy_slam"], enrage_at=210,
|
||||
phases=[{"at": 0.5, "say": "To arms!", "wake": ["e1", "e2"]}]),
|
||||
_dungeon_foe("fight_scouts", "Bandit brute", *FINAL_BOSS, 1, level=35, dormant=True),
|
||||
_dungeon_foe("fight_scouts", "Bandit brute", *FINAL_BOSS, 1, level=35, dormant=True)]),
|
||||
],
|
||||
},
|
||||
"dungeon_barrow_crypts": {
|
||||
"name": "Barrow Crypts", "area": "Sunken Barrows", "tier": 2, "level": 35, "bonus_gold": 250,
|
||||
"pulls": [
|
||||
("Barrow mound", [_dungeon_foe("fight_stone_guardians", v, *TRASH, 1)
|
||||
for v in ("Stone guardian", "Barrow sentry", "Barrow sentry")]),
|
||||
("Flooded hall", [_dungeon_foe("fight_bog_wraiths", v, *TRASH, 1)
|
||||
for v in ("Drowned knight", "Bog wraith", "Marsh wisp")]),
|
||||
("Runebound guardian", [_dungeon_foe("fight_stone_guardians", "Runebound guardian", MINI_BOSS, 3.0, boss=True,
|
||||
abilities=["rune_blast", "shatter"], enrage_at=150)]),
|
||||
("Lizard warren", [_dungeon_foe("fight_lizardfolk", v, *TRASH, 1)
|
||||
for v in ("Lizard warrior", "Lizard spearman", "Lizard spearman", "Lizard shaman")]),
|
||||
("Brood mother", [_dungeon_foe("fight_giant_spiders", "Brood mother", MINI_BOSS, 5.5, boss=True,
|
||||
abilities=["venom_spray", "lunge"], enrage_at=150,
|
||||
phases=[{"at": 0.5, "say": "The eggs are hatching!", "wake": ["e1", "e2"]}]),
|
||||
_dungeon_foe("fight_giant_spiders", "Spider hunter", *TRASH, 1, dormant=True),
|
||||
_dungeon_foe("fight_giant_spiders", "Spider hunter", *TRASH, 1, dormant=True)]),
|
||||
("Bone gallery", [_dungeon_foe("fight_bog_wraiths", v, *TRASH, 1) for v in ("Bog wraith", "Bog wraith", "Drowned knight")]),
|
||||
("Barrow king", [_dungeon_foe("fight_barrow_king", "Barrow king", *FINAL_BOSS, 2, boss=True,
|
||||
abilities=["grave_chill", "soul_rend", "heavy_slam"], enrage_at=210,
|
||||
phases=[{"at": 0.5, "say": "Rise, my knights!", "wake": ["e1", "e2"]}]),
|
||||
_dungeon_foe("fight_bog_wraiths", "Drowned knight", *FINAL_BOSS, 1, dormant=True),
|
||||
_dungeon_foe("fight_bog_wraiths", "Drowned knight", *FINAL_BOSS, 1, dormant=True)]),
|
||||
],
|
||||
},
|
||||
"dungeon_deep_forge": {
|
||||
"name": "The Deep Forge", "area": "Iron Hills", "tier": 3, "level": 50, "bonus_gold": 400,
|
||||
"pulls": [
|
||||
("Mine shaft", [_dungeon_foe("fight_mine_ghosts", v, *TRASH, 1) for v in ("Lost miner", "Lantern ghost", "Shaft howler")]),
|
||||
("Orc camp", [_dungeon_foe("fight_orcs", v, *TRASH, 1) for v in ("Orc berserker", "Orc archer", "Orc shaman")]),
|
||||
("Iron colossus", [_dungeon_foe("fight_iron_golems", "Iron colossus", MINI_BOSS, 3.0, boss=True,
|
||||
abilities=["forge_blast", "shatter"], enrage_at=150)]),
|
||||
("Foundry", [_dungeon_foe("fight_iron_golems", v, *TRASH, 1) for v in ("Iron golem", "Forge golem", "Forge golem")]),
|
||||
("Orc warchief", [_dungeon_foe("fight_orcs", "Orc berserker", MINI_BOSS, 5.5, archetype="elite", name="Orc warchief",
|
||||
boss=True, abilities=["war_cry", "lunge"], enrage_at=150,
|
||||
phases=[{"at": 0.5, "say": "Blood and iron!", "wake": ["e1", "e2"]}]),
|
||||
_dungeon_foe("fight_orcs", "Orc berserker", *TRASH, 1, dormant=True),
|
||||
_dungeon_foe("fight_orcs", "Orc berserker", *TRASH, 1, dormant=True)]),
|
||||
("Wyvern roost", [_dungeon_foe("fight_wyverns", v, *TRASH, 1) for v in ("Wyvern", "Wyvern hatchling", "Venomspitter")]),
|
||||
("Green dragon", [_dungeon_foe("fight_green_dragon", "Green dragon", *FINAL_BOSS, 2, boss=True,
|
||||
abilities=["acid_spit", "acid_breath", "tail_swipe"], enrage_at=210,
|
||||
phases=[{"at": 0.5, "say": "The brood answers!", "wake": ["e1", "e2"]}]),
|
||||
_dungeon_foe("fight_wyverns", "Wyvern", *FINAL_BOSS, 1, dormant=True),
|
||||
_dungeon_foe("fight_wyverns", "Wyvern", *FINAL_BOSS, 1, dormant=True)]),
|
||||
],
|
||||
},
|
||||
"dungeon_frozen_hold": {
|
||||
"name": "Frozen Hold", "area": "Frostpeak", "tier": 4, "level": 65, "bonus_gold": 550,
|
||||
"pulls": [
|
||||
("Ice gate", [_dungeon_foe("fight_ice_elementals", v, *TRASH, 1) for v in ("Ice brute", "Frost wisp", "Frost wisp")]),
|
||||
("Troll cave", [_dungeon_foe("fight_frost_trolls", v, *TRASH, 1)
|
||||
for v in ("Frost troll", "Troll icehurler", "Troll rimecaller")]),
|
||||
("Glacier colossus", [_dungeon_foe("fight_ice_elementals", "Glacier colossus", MINI_BOSS, 3.0, boss=True,
|
||||
abilities=["deep_freeze", "shatter"], enrage_at=150)]),
|
||||
("Griffin eyrie", [_dungeon_foe("fight_griffins", v, *TRASH, 1) for v in ("Griffin", "Griffin rider", "Storm griffin")]),
|
||||
("Banshee queen", [_dungeon_foe("fight_banshees", "Banshee", MINI_BOSS, 5.5, archetype="elite", name="Banshee queen",
|
||||
boss=True, abilities=["wail", "lunge"], enrage_at=150,
|
||||
phases=[{"at": 0.5, "say": "Sing with me!", "wake": ["e1", "e2"]}]),
|
||||
_dungeon_foe("fight_banshees", "Keening shade", *TRASH, 1, dormant=True),
|
||||
_dungeon_foe("fight_banshees", "Keening shade", *TRASH, 1, dormant=True)]),
|
||||
("Hall of echoes", [_dungeon_foe("fight_banshees", v, *TRASH, 1) for v in ("Wailing knight", "Banshee", "Banshee")]),
|
||||
("Blue dragon", [_dungeon_foe("fight_blue_dragon", "Blue dragon", *FINAL_BOSS, 2, boss=True,
|
||||
abilities=["frost_lance", "frost_breath", "tail_swipe"], enrage_at=210,
|
||||
phases=[{"at": 0.5, "say": "Freeze!", "wake": ["e1", "e2"]}]),
|
||||
_dungeon_foe("fight_ice_elementals", "Ice brute", *FINAL_BOSS, 1, dormant=True),
|
||||
_dungeon_foe("fight_ice_elementals", "Ice brute", *FINAL_BOSS, 1, dormant=True)]),
|
||||
],
|
||||
},
|
||||
"dungeon_dragons_lair": {
|
||||
"name": "Dragon's Lair", "area": "Dragon's Spine", "tier": 5, "level": 80, "bonus_gold": 750,
|
||||
"pulls": [
|
||||
("Lava tubes", [_dungeon_foe("fight_magma_constructs", v, *TRASH, 1)
|
||||
for v in ("Magma brute", "Cinder golem", "Fire binder")]),
|
||||
("Shadow pass", [_dungeon_foe("fight_shades", v, *TRASH, 1) for v in ("Shade", "Shadow blade", "Shadow blade")]),
|
||||
("Void knight", [_dungeon_foe("fight_shades", "Void knight", MINI_BOSS, 3.0, boss=True,
|
||||
abilities=["void_bolt", "shatter"], enrage_at=150)]),
|
||||
("Roc nests", [_dungeon_foe("fight_rocs", v, *TRASH, 1) for v in ("Roc", "Roc hatchling", "Thunder roc")]),
|
||||
("Flame high priest", [_dungeon_foe("fight_dragonkin", "Flame priest", MINI_BOSS, 5.5, archetype="elite",
|
||||
name="Flame high priest", boss=True, abilities=["flame_wave", "hex_bolt"],
|
||||
enrage_at=150, phases=[{"at": 0.5, "say": "Burn!", "wake": ["e1", "e2"]}]),
|
||||
_dungeon_foe("fight_dragonkin", "Flame priest", *TRASH, 1, dormant=True),
|
||||
_dungeon_foe("fight_dragonkin", "Flame priest", *TRASH, 1, dormant=True)]),
|
||||
("Drakeguard hall", [_dungeon_foe("fight_dragonkin", v, *TRASH, 1)
|
||||
for v in ("Drakeguard", "Drake lancer", "Flame priest")]),
|
||||
("Red dragon", [_dungeon_foe("fight_red_dragon", "Red dragon", *FINAL_BOSS, 2, boss=True,
|
||||
abilities=["inferno", "fire_breath", "tail_swipe"], enrage_at=210,
|
||||
phases=[{"at": 0.5, "say": "Guards!", "wake": ["e1", "e2"]}]),
|
||||
_dungeon_foe("fight_dragonkin", "Drakeguard", *FINAL_BOSS, 1, dormant=True),
|
||||
_dungeon_foe("fight_dragonkin", "Drakeguard", *FINAL_BOSS, 1, dormant=True)]),
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
# Each boss pull's last touch, HP and hits, so that a group on auto loses it and one that plays
|
||||
# wins it (tools/balance.py dungeon, and dungeon perfect).
|
||||
DUNGEON_TUNING = {
|
||||
("dungeon_goblin_warren", "Old One-Eye"): (0.8, 0.8), ("dungeon_goblin_warren", "Grizzik the Hexer"): (1.5, 0.5),
|
||||
("dungeon_goblin_warren", "Goblin king"): (0.8, 1.2),
|
||||
("dungeon_bandit_stronghold", "Bandit captain"): (1.0, 1.2), ("dungeon_bandit_stronghold", "Hedge witch"): (1.25, 0.65),
|
||||
("dungeon_bandit_stronghold", "Bandit warlord"): (1.5, 1.4),
|
||||
("dungeon_barrow_crypts", "Runebound guardian"): (0.8, 1.2), ("dungeon_barrow_crypts", "Brood mother"): (1.0, 1.2),
|
||||
("dungeon_barrow_crypts", "Barrow king"): (1.5, 1.0),
|
||||
("dungeon_deep_forge", "Orc warchief"): (1.0, 1.3), ("dungeon_deep_forge", "Green dragon"): (1.25, 1.2),
|
||||
("dungeon_frozen_hold", "Glacier colossus"): (1.0, 1.2), ("dungeon_frozen_hold", "Banshee queen"): (1.25, 1.0),
|
||||
("dungeon_frozen_hold", "Blue dragon"): (1.5, 1.2),
|
||||
("dungeon_dragons_lair", "Void knight"): (1.5, 1.0), ("dungeon_dragons_lair", "Flame high priest"): (0.8, 1.2),
|
||||
("dungeon_dragons_lair", "Red dragon"): (1.5, 1.4),
|
||||
}
|
||||
|
||||
|
||||
def _tune_dungeons() -> None:
|
||||
for key, spec in DUNGEONS.items():
|
||||
for index, (name, pack) in enumerate(spec["pulls"]):
|
||||
hp, hits = DUNGEON_TUNING.get((key, name), (1, 1))
|
||||
spec["pulls"][index] = (name, [{**foe, "hp": round(foe["hp"] * hp), "max_hit": max(1, round(foe["max_hit"] * hits))}
|
||||
for foe in pack])
|
||||
|
||||
|
||||
_tune_dungeons()
|
||||
|
||||
|
||||
def _dungeon_actions() -> list[dict]:
|
||||
actions = []
|
||||
|
|
@ -1057,7 +1230,8 @@ def _dungeon_actions() -> list[dict]:
|
|||
round(sum(foe["xp"] for _name, pack in spec["pulls"] for foe in pack)),
|
||||
enemy={"name": spec["name"], "level": spec["level"], "boss": True, "variants": variants},
|
||||
group=spec["area"], dungeon=key, together=GROUP_SIZE, personal_loot=True,
|
||||
gold=[spec["bonus_gold"], spec["bonus_gold"]], drops=[list(d) for d in _boss_drops(spec["tier"])],
|
||||
gold=[spec["bonus_gold"], spec["bonus_gold"]],
|
||||
drops=[list(d) for d in _boss_drops(spec["tier"])] if spec["tier"] else bosses[-1].get("drops", []),
|
||||
pulls=[name for name, _pack in spec["pulls"]]))
|
||||
return actions
|
||||
|
||||
|
|
@ -3065,7 +3239,7 @@ def _clear_bonus(world: dict, player: dict, spec: dict, now: float, rng: random.
|
|||
player["gold"] += spec["bonus_gold"]
|
||||
summary["gold"] += spec["bonus_gold"]
|
||||
found = [trophy(rng.choice(list(STYLES)), spec["tier"]), *(reagent(rng.choice(list(REAGENT_NOUNS)), spec["tier"])
|
||||
for _ in range(2))]
|
||||
for _ in range(2))] if spec["tier"] else []
|
||||
for item in found:
|
||||
kept = bank_add(world, player, item, 1, now, summary)
|
||||
if kept:
|
||||
|
|
@ -5463,7 +5637,10 @@ BUILDING_GLYPHS = {
|
|||
ACTION_GLYPHS = {
|
||||
"fight_wolves": ("wolf-head", "#9aa1ab"), "fight_scouts": ("hooded-assassin", "#a08060"),
|
||||
"fight_ruins": ("castle-ruins", "#a8a29e"), "fight_stronghold": ("castle", "#8a8f98"),
|
||||
"dungeon_watchtower": ("watchtower", "#d1a46a"),
|
||||
"dungeon_watchtower": ("watchtower", "#d1a46a"), "dungeon_goblin_warren": ("cave-entrance", "#7fbf5a"),
|
||||
"dungeon_bandit_stronghold": ("guarded-tower", "#a08060"), "dungeon_barrow_crypts": ("tombstone", "#8fb8f0"),
|
||||
"dungeon_deep_forge": ("anvil-impact", "#ff8a3a"), "dungeon_frozen_hold": ("frozen-orb", "#8fd0e0"),
|
||||
"dungeon_dragons_lair": ("dragon-spiral", "#e05a5a"),
|
||||
"fight_green_dragon": ("dragon-head", "#5fae5a"), "fight_blue_dragon": ("dragon-head", "#4f86d6"),
|
||||
"fight_red_dragon": ("dragon-head", "#d0503c"), "fight_black_dragon": ("dragon-head", "#8a8f98"),
|
||||
"sabotage": ("fire-bomb", "#e0703a"), "drill_militia": ("sword-brandish", "#e0a050"), "recon_roads": ("spyglass", "#6f8fec"), "recon_camps": ("spyglass", "#8a7fd0"),
|
||||
|
|
@ -5492,6 +5669,17 @@ ABILITY_GLYPHS = {
|
|||
"fire_breath": ("dragon-breath", "#ff8a3a"), "tail_swipe": ("spiked-tail", "#c08850"),
|
||||
"stone_curse": ("evil-hand", "#a77be8"), "ground_pound": ("earth-crack", "#c08850"),
|
||||
"shatter": ("shattered-glass", "#d1a46a"), "shriek": ("sonic-shout", "#a77be8"),
|
||||
"hex_storm": ("lightning-storm", "#a77be8"), "crushing_decree": ("crown", "#e0b04a"),
|
||||
"royal_stomp": ("crush", "#c08850"), "witchfire": ("witch-flight", "#5fae5a"),
|
||||
"cheap_shot": ("thrown-daggers", "#d4dae2"), "execute": ("decapitation", "#e06a6a"),
|
||||
"whirlwind": ("whirlwind", "#d4dae2"), "rune_blast": ("rune-stone", "#8fb8f0"),
|
||||
"venom_spray": ("poison-cloud", "#5fae5a"), "grave_chill": ("tombstone", "#8fb8f0"),
|
||||
"soul_rend": ("skull-bolt", "#a77be8"), "forge_blast": ("furnace", "#ff8a3a"),
|
||||
"war_cry": ("shouting", "#e06a6a"), "acid_spit": ("acid-blob", "#5fae5a"),
|
||||
"acid_breath": ("acid", "#5fae5a"), "deep_freeze": ("frozen-block", "#8fd0e0"),
|
||||
"wail": ("screaming", "#a77be8"), "frost_lance": ("ice-spear", "#8fd0e0"),
|
||||
"frost_breath": ("snowflake-2", "#8fd0e0"), "void_bolt": ("vortex", "#a77be8"),
|
||||
"flame_wave": ("fire-wave", "#ff8a3a"), "inferno": ("fire-ring", "#ff6a2a"),
|
||||
}
|
||||
PRAYER_GLYPHS = {"thick_skin": ("shield", "#a8a29e"), "burst_of_strength": ("biceps", "#e06a6a"),
|
||||
"rapid_heal": ("heart-plus", "#e06a8a"), "steel_skin": ("armor-upgrade", "#d4dae2"),
|
||||
|
|
@ -5623,6 +5811,14 @@ ORDER_RECIPES, ORDER_RAW = _order_sources()
|
|||
# What changed, shown on the Patch notes page. Newest first; every shipped change adds a
|
||||
# line here (new / balance / fix), and a new release a new entry on top.
|
||||
PATCH_NOTES = [
|
||||
{"date": "2026-10-24", "title": "A dungeon in every area", "notes": [
|
||||
("new", "Six more dungeons for 2–4, seven pulls each with two mini-bosses and a final boss: Goblin Warren "
|
||||
"(Greenwood, combat 8, best with 3–4), Barrow Crypts (Sunken Barrows, 35), Bandit Stronghold (Frontier, 40), "
|
||||
"The Deep Forge (Iron Hills, 50), Frozen Hold (Frostpeak, 65) and Dragon's Lair (Dragon's Spine, 80)."),
|
||||
("new", "Every boss has its own: curses to interrupt, shrieks, slams to brace for, adds at half health and an "
|
||||
"enrage timer. As in the Watchtower, trash falls on auto and the bosses need your own hands."),
|
||||
("new", "Clearing pays 30–750 gold by area, plus a trophy and 2 reagents (Goblin Warren: gold only)."),
|
||||
]},
|
||||
{"date": "2026-10-24", "title": "Gold", "notes": [
|
||||
("balance", "Raids hit about twice as hard and grow with the guild: they add half the combat power of everyone "
|
||||
"active in the last 2 days. Pay the guards, drill, stand guard and sabotage the camp, or expect losses. "
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue