Five new rooms: prison, graveyard, guard post, arena, sacrifice altar; new creature: the revenant

- prison: captured heroes sit in cells apart from the torture chamber, do not defect and starve in time; the hand can move prisoners between cells and torture
- graveyard: the fallen are buried there; after a while some rise as revenants (undead: no food, no sleep, life drain from level 5)
- guard post: creatures hold the position and attack whatever comes into view
- arena: creatures spar in pairs for fast, free experience, at the cost of bruises
- sacrifice altar: creatures dropped on it are sacrificed; certain pairs bring a rare creature, otherwise a blessing (mood and mana)
- researched in the library, campaign unlocks, textures, furniture, texts EN/DE, bestiary

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:35:12 +01:00
1 parent 2c8db33a69
commit a58497e3a9
14 files changed
+606 -28

No files matched your search

+59 -1
View File
@@ -73,6 +73,11 @@ pub const I_RUNE: u32 = 143; // rune forge tower
pub const T_FORGE: u32 = 144; // 4 variants: sooty flagstones with glowing cracks
pub const I_TRAPS: u32 = 148; // 10 icons in TRAP_KINDS order
pub const I_SPELLS: u32 = 158; // 8 icons in SPELLS order
pub const T_PRISON: u32 = 166; // 4 variants each
pub const T_GRAVEYARD: u32 = 170;
pub const T_GUARDPOST: u32 = 174;
pub const T_ARENA: u32 = 178;
pub const T_ALTAR: u32 = 182;
pub struct Gfx {
pub atlas: Texture2D,
@@ -765,6 +770,40 @@ fn gen_atlas() -> Image {
}
});
}
// prison: dark flagstones with drain grates
for v in 0..4u32 {
cv.cell(T_PRISON + v, |x, y| {
if (5..=10).contains(&x) && (5..=10).contains(&y) && (x == 5 || x == 10 || y == 5 || y == 10 || x % 2 == 0) && v % 2 == 0 {
Some(c(30, 30, 34))
} else {
Some(stones(x, y, v + 310, (58, 56, 60), (28, 26, 30), 6))
}
});
// graveyard: dark earth, moss and pebbles
cv.cell(T_GRAVEYARD + v, |x, y| {
let r = rnd(x, y, v + 320);
Some(if r > 0.86 { c(70, 96, 52) } else if r > 0.8 { c(110, 106, 100) } else { shade((52, 40, 34), (rnd(x / 2, y / 2, v + 321) * 16.0) as i32 - 8) })
});
// guard post: flagstones with a red border
cv.cell(T_GUARDPOST + v, |x, y| {
if x == 0 || y == 0 || x == 15 || y == 15 {
Some(c(120, 30, 34))
} else {
Some(stones(x, y, v + 330, (76, 66, 62), (36, 30, 30), 8))
}
});
// arena: raked sand with dark stains
cv.cell(T_ARENA + v, |x, y| {
let rake = (y + (x / 4 + v as i32) % 2) % 3 == 0;
let stain = rnd(x / 3, y / 3, v + 340) > 0.9;
Some(if stain { c(110, 60, 40) } else if rake { c(170, 140, 96) } else { shade((196, 164, 112), (rnd(x, y, v + 341) * 14.0) as i32 - 7) })
});
// altar: black marble with red veins
cv.cell(T_ALTAR + v, |x, y| {
let vein = ((x as f32 * 0.7 + (y as f32 * 0.5 + v as f32).sin() * 3.0) as i32 + y) % 11 == 0;
Some(if vein { c(150, 20, 30) } else { shade((30, 26, 32), (rnd(x, y, v + 350) * 10.0) as i32 - 5) })
});
}
// trap and door icons
let icons: [fn(i32, i32) -> Option<Color>; 10] = [
// spikes
@@ -1226,6 +1265,19 @@ fn sprite_rows(k: EK) -> [&'static str; 10] {
"...kO.Ok..",
"...kk.kk..",
],
// revenant: a pale, hollow-eyed corpse with a rusty blade and green grave-light
EK::Revenant => [
"...kkkk...",
"..kwwwwk..",
"..kwgwgk..",
"..kwwwwk.S",
"...kCCk..S",
"..kCcCCk.S",
".kCkcCkCkb",
"..kCcCCk..",
"..kCk.kCk.",
"..kk...kk.",
],
EK::Wyrm => [
"R.......kw",
"RR....krrk",
@@ -1295,7 +1347,7 @@ fn pal(ch: char) -> Option<Color> {
})
}
pub const SPRITE_KINDS: [EK; 18] = [
pub const SPRITE_KINDS: [EK; 19] = [
EK::Worker,
EK::Kobold,
EK::Spider,
@@ -1314,6 +1366,7 @@ pub const SPRITE_KINDS: [EK; 18] = [
EK::Owl,
EK::Wyrm,
EK::Cogling,
EK::Revenant,
];
// width of the sprite texture in pixels
pub const SPRITE_TEX_W: f32 = (SPRITE_KINDS.len() * 12) as f32;
@@ -1727,6 +1780,11 @@ impl Gfx {
Kind::ManaSpring => T_PORTALFLOOR + v,
Kind::RuneChest => T_FLOOR + v,
Kind::Forge => T_FORGE + v,
Kind::Prison => T_PRISON + v,
Kind::Graveyard => T_GRAVEYARD + v,
Kind::GuardPost => T_GUARDPOST + v,
Kind::Arena => T_ARENA + v,
Kind::Altar => T_ALTAR + v,
Kind::Door => {
if claimed {
T_CLAIM + v