Rivers and bridges: water and lava tiles, bridge tool, burning in lava

- New tile kinds (appended for the savegame codec): water, lava, wooden bridge, stone bridge, core shard
- Sunken river beds with banks, bridge decks with rails, lava glow and lights
- Bridge tool (key U, rooms category): bridges grow from own ground, 30 gold/tile over water, 75 over lava
- Selling a bridge drops the units on it into the river (water: swim to the bank, lava: burn)
- Cannon blasts and punches knock units back; into lava = burnt (heroes still pay their bounty)
- Heroes cannot path through rivers; texts EN/DE; tests for bridges and lava

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-03 10:32:40 +01:00
1 parent af6be62805
commit 75dc445d3b
9 files changed
+536 -22

No files matched your search

+22 -2
View File
@@ -155,10 +155,11 @@ pub enum Tool {
Heal,
Summon,
Tower(TowerKind),
Bridge,
}
// New tools are appended so that existing key bindings ("tool<i>") keep their meaning
pub const TOOLS: [Tool; 17] = [
pub const TOOLS: [Tool; 18] = [
Tool::Dig,
Tool::Hand,
Tool::Room(0),
@@ -176,6 +177,7 @@ pub const TOOLS: [Tool; 17] = [
Tool::Tower(TowerKind::Arrow),
Tool::Tower(TowerKind::Cannon),
Tool::Tower(TowerKind::Magic),
Tool::Bridge,
];
@@ -205,6 +207,7 @@ pub fn tool_info(t: Tool) -> ToolInfo {
Tool::Lightning => ("lightning", I_BOLT, None),
Tool::Heal => ("heal", I_HEAL, None),
Tool::Summon => ("summon", I_SUMMON, None),
Tool::Bridge => ("bridge", I_BRIDGE, None),
};
let name = match room {
Some(r) => tr(ROOM_NAMES[r]),
@@ -219,6 +222,7 @@ pub fn tool_cost(t: Tool, g: &Game) -> String {
Tool::Lightning => trf("cost.mana", &["50".into()]),
Tool::Heal => trf("cost.mana", &["60".into()]),
Tool::Summon => trf("cost.mana", &[(g.summon_cost() as i32).to_string()]),
Tool::Bridge => trf("cost.bridge", &[BRIDGE_COST[0].to_string(), BRIDGE_COST[1].to_string()]),
Tool::Tower(k) => {
let s = tower_stats(k);
let mut c = trf("cost.tower", &[s.cost[0].to_string(), s.cost[1].to_string(), s.cost[2].to_string()]);
@@ -235,7 +239,7 @@ pub fn tool_cost(t: Tool, g: &Game) -> String {
pub const CATS: [(&str, &[usize]); 6] = [
("cat.dig", &[0]),
("cat.hand", &[1]),
("cat.rooms", &[2, 3, 4, 5, 6, 12, 13]),
("cat.rooms", &[2, 3, 4, 5, 6, 12, 13, 17]),
("cat.towers", &[14, 15, 16]),
("cat.spells", &[9, 10, 11]),
("cat.orders", &[8, 7]),
@@ -992,6 +996,22 @@ pub fn hover_info(g: &Game, ent: Option<usize>, tile: Option<(i32, i32)>) -> Vec
}
}
}
Kind::Water => {
out.push((tr("tile.water"), BLUE));
out.push((tr("tile.water_info"), DIM));
}
Kind::Lava => {
out.push((tr("tile.lava"), RED));
out.push((tr("tile.lava_info"), DIM));
}
Kind::Bridge | Kind::LavaBridge => {
out.push((tr(if t.kind == Kind::Bridge { "tile.bridge" } else { "tile.lavabridge" }), FRAME_HI));
out.push((tr(owner), DIM));
}
Kind::Shard => {
out.push((tr("tile.shard"), RED));
out.push((tr("tile.shard_info"), DIM));
}
Kind::Gate => {
out.push((tr("tile.gate"), BLUE));
out.push((trf("info.hp", &[(g.gate_hp as i32).to_string(), (GATE_HP as i32).to_string()]), BLUE));