Three new heroes: giant, fairy spy, battle mage

- giant (from wave 6): slow and enormous, smashes doors three times as hard and wrecks traps by standing next to them
- fairy spy (from wave 3): flies, finds the dungeon's traps (marked with a glint) so the heroes wreck them, and heals heroes around it
- battle mage (from wave 4): throws fireballs with splash and blasts reinforced walls (steel resists him better)
- sprites, bestiary texts EN/DE, test: fairies find traps, giants wreck them

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-04 07:40:20 +01:00
1 parent a58497e3a9
commit 4ce2c2919e
7 files changed
+186 -15

No files matched your search

+43 -5
View File
@@ -109,6 +109,10 @@ pub enum EK {
Wyrm, // big aerie + treasury: rare, very strong, fire breath
Cogling, // forge: a sooty little tinkerer, builds traps and doors fastest
Revenant, // rises from the graveyard: undead, needs no food and no bed
// more heroes
Giant, // slow, huge, smashes doors and traps
Fairy, // flies, finds the dungeon's traps and heals heroes a little
BattleMage, // blasts reinforced walls from afar, throws fireballs
}
pub struct St {
@@ -147,12 +151,15 @@ pub fn st(k: EK) -> St {
EK::Wyrm => s("unit.wyrm", 650.0, 30.0, 3.0, 2.5, 1.4, 380, 0),
EK::Cogling => s("unit.cogling", 90.0, 9.0, 1.0, 2.4, 0.9, 70, 0),
EK::Revenant => s("unit.revenant", 160.0, 14.0, 1.0, 1.9, 1.2, 30, 0),
EK::Giant => s("unit.giant", 900.0, 34.0, 1.1, 1.3, 1.6, 200, 600),
EK::Fairy => s("unit.fairy", 70.0, 5.0, 3.5, 3.2, 1.2, 60, 150),
EK::BattleMage => s("unit.battlemage", 120.0, 18.0, 5.0, 1.8, 1.8, 120, 250),
}
}
// flying creatures cross water and lava and sleep in the aerie
pub fn flies(k: EK) -> bool {
matches!(k, EK::Bat | EK::Gargoyle | EK::Owl | EK::Wyrm)
matches!(k, EK::Bat | EK::Gargoyle | EK::Owl | EK::Wyrm | EK::Fairy)
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
@@ -1599,6 +1606,13 @@ impl Game {
}
if w >= 3 {
pool.push((Priest, 2));
pool.push((Fairy, 1));
}
if w >= 4 {
pool.push((BattleMage, 1));
}
if w >= 6 {
pool.push((Giant, 1));
}
let boss = if w % 5 == 0 { Some(Paladin) } else { None };
let base_level = 1 + (w - 1) / 3;
@@ -1822,15 +1836,27 @@ impl Game {
e.timer = 0.0;
let pow = match e.kind {
EK::Dwarf => 3.0,
EK::Paladin => 2.0,
EK::Paladin | EK::Giant => 2.0,
_ => 1.0,
} * if tile.kind == Kind::Steel {
} * if e.kind == EK::BattleMage && (tile.reinforced || tile.kind == Kind::Steel) {
// the battle mage blasts reinforced walls (steel resists better)
if tile.kind == Kind::Steel {
0.4
} else {
1.6
}
} else if tile.kind == Kind::Steel {
0.05
} else if tile.reinforced {
0.2
} else {
1.0
};
if e.kind == EK::BattleMage {
let (sx, sy) = (e.x, e.y);
self.shot(sx, sy, 0.6, tx as f32 + 0.5, ty as f32 + 0.5, 0.5, 0.3, 0xff3080ff);
self.style_last_fx(crate::particles::ST_FIRE);
}
self.fx(6, tx as f32 + 0.5, ty as f32 + 0.5, 0.0, 0.0, 0.4, 0xff3a5a7a);
self.sfx(Sfx::Dig, tx as f32 + 0.5, ty as f32 + 0.5);
let t = &mut self.map.t[next];
@@ -2020,7 +2046,7 @@ impl Game {
EK::Archer => ST_ARROW,
EK::Mage => ST_SHADOW,
EK::Priest => ST_HOLY,
EK::Priestess | EK::Wyrm => ST_FIRE,
EK::Priestess | EK::Wyrm | EK::BattleMage => ST_FIRE,
EK::Owl => ST_ARCANE,
_ => ST_PLAIN,
});
@@ -2051,7 +2077,7 @@ impl Game {
}
}
}
if e.kind == EK::Priestess || e.kind == EK::Wyrm {
if e.kind == EK::Priestess || e.kind == EK::Wyrm || e.kind == EK::BattleMage {
// fireball / fire breath: half damage to enemies around the target
let me = e.side();
let splash: Vec<usize> = self
@@ -3746,6 +3772,18 @@ impl Game {
// ---------------------------------------------------------------- heroes
fn hero_ai(&mut self, e: &mut Ent, dt: f32) {
if e.kind == EK::Fairy {
// fairy dust: the heroes around are healed a little all the time
for o in self.ents.iter_mut() {
if o.alive && o.active_hero() && o.hp < o.max_hp && (o.x - e.x).powi(2) + (o.y - e.y).powi(2) < 9.0 {
o.hp = (o.hp + 6.0 * dt).min(o.max_hp);
}
}
if self.vrng.f() < 5.0 * dt {
let vx = self.vrng.f() * 0.6 - 0.3;
self.part(crate::particles::EMBER, (e.x, e.y, 0.9), (vx, 0.0, 0.2), 1.0, crate::particles::abgr(255, 240, 180), 0.03);
}
}
if e.think <= 0.0 {
e.think = 0.5;
if e.kind == EK::Priest && e.cd <= 0.0 {