from __future__ import annotations from .plants import HP_MULT from .skills import Skill, TARGET_ENEMY from .types import TYPE_GARDEN from .unit import TEAM_ENEMY, Unit # A boss appears every BOSS_FLOOR_STEP floors (20, 40, 60, ...). Bosses are # fought alone (1 vs the player's team) and have far bigger stats than normal # floor enemies. BOSS_FLOOR_STEP = 20 # Chance (0..1) a defeated boss drops one of its signature runes — much higher # than the ~5-15% rune drop chance anywhere else. BOSS_RUNE_DROP_CHANCE = 0.80 BOSS_SPECS = { "Stones": { "type": TYPE_GARDEN, # (attack, speed, defense, health) — medium attack, very low speed, # medium defense, high health (before HP_MULT). "stats": (110, 30, 90, 380), "sprite": "stones", "drop_runes": ("ruby", "amethyst"), "desc": "A slow, rocky guardian. Each Pebble Throw stacks its power " "(up to 3); at 3 stacks it unleashes Landslide for huge damage.", }, } def is_boss(name: str) -> bool: return name in BOSS_SPECS def boss_for_floor(floor: int): """The boss that appears on `floor`, or None if it's a normal floor.""" if floor > 0 and floor % BOSS_FLOOR_STEP == 0: return "Stones" return None def boss_type(name: str) -> str: return BOSS_SPECS[name]["type"] def boss_stats(name: str) -> tuple: return BOSS_SPECS[name]["stats"] def boss_sprite(name: str) -> str: return BOSS_SPECS[name]["sprite"] def boss_drop_runes(name: str) -> tuple: return BOSS_SPECS[name]["drop_runes"] def boss_floor_level(floor: int) -> int: """Display level for a boss at `floor` (scales with each boss appearance).""" return 1 + floor // BOSS_FLOOR_STEP def make_boss(name: str, floor: int) -> Unit: """Build the boss unit for `floor`. Boss stats are already far above normal enemies and grow a little with each appearance so they stay threatening.""" spec = BOSS_SPECS[name] atk, spd, dfn, hp = spec["stats"] lvl = boss_floor_level(floor) mult = 1 + 0.06 * (lvl - 1) atk = int(atk * mult) dfn = int(dfn * mult) hp = int(hp * mult) pebble = Skill("Pebble Throw", power=60, target=TARGET_ENEMY, cooldown=0, mechanic="boss_stack", priority=2, description="Medium damage; stacks the boss's power (up to 3).") landslide = Skill("Landslide", power=140, target=TARGET_ENEMY, cooldown=0, mechanic="boss_landslide", priority=1, description="Huge damage, releases all stacks. Needs 3 stacks.") u = Unit(name, TEAM_ENEMY, spec["type"], max_hp=int(hp * HP_MULT), attack=atk, speed=spd, defense=dfn, skills=[pebble, landslide], role="tank", crit=0.05) u.hp = u.max_hp return u