83 lines
2.7 KiB
Python
83 lines
2.7 KiB
Python
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 |