Drawbridges (down, up, automatic), frost spell and obsidian over cooled lava

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-05 21:52:12 +01:00
1 parent 76c23a06f0
commit 34b4640d85
32 files changed
+869 -31

No files matched your search

+54 -1
View File
@@ -722,12 +722,54 @@ fn build_chunk(map: &Map, amb: &[f32], glow: &[f32], cx: i32, cz: i32, atlas: &T
[inward; 4],
);
}
if t.kind == Kind::Obsidian {
// a crust of cooled lava just above the glowing river
let (oa, ob) = cell_uv(T_OBSIDIAN + (t.var as u32 & 3));
let oc = col(lava_lit(Vec3::splat(amb_at(amb, xf + 0.5, zf + 0.5).max(0.45)), lg), 1.0);
let y = -0.02;
mb.quad([vec3(xf, y, zf), vec3(xf + 1.0, y, zf), vec3(xf + 1.0, y, zf + 1.0), vec3(xf, y, zf + 1.0)], [vec2(oa.x, oa.y), vec2(ob.x, oa.y), vec2(ob.x, ob.y), vec2(oa.x, ob.y)], [oc; 4], [Vec3::Y; 4]);
continue;
}
if t.raised() {
// a raised drawbridge: the flap stands upright at the bank it is hinged on
let tex = if lava { T_STONEBRIDGE } else { T_BRIDGE };
let (ba, bb) = cell_uv(tex);
let fc = col(lava_lit(Vec3::splat(amb_at(amb, xf + 0.5, zf + 0.5).max(if lava { 0.6 } else { 0.0 }) * 0.85), lg), 1.0);
for (d, &(dx, dz)) in DIR4.iter().enumerate() {
if !map.get(x + dx, z + dz).map_or(false, |o| o.walkable() && !o.bridge()) {
continue;
}
// the hinge edge, from p to q
let (p, q) = match d {
0 => (vec3(xf, 0.0, zf), vec3(xf + 1.0, 0.0, zf)),
1 => (vec3(xf + 1.0, 0.0, zf), vec3(xf + 1.0, 0.0, zf + 1.0)),
2 => (vec3(xf + 1.0, 0.0, zf + 1.0), vec3(xf, 0.0, zf + 1.0)),
_ => (vec3(xf, 0.0, zf + 1.0), vec3(xf, 0.0, zf)),
};
let inward = vec3(-dx as f32, 0.0, -dz as f32);
let off = inward * 0.12;
let up = Vec3::Y * 1.0;
// both faces of the flap, a little in front of the bank
mb.quad([p + off, q + off, q + off + up, p + off + up], [vec2(ba.x, bb.y), vec2(bb.x, bb.y), vec2(bb.x, ba.y), vec2(ba.x, ba.y)], [fc; 4], [inward; 4]);
mb.quad([q + off, p + off, p + off + up, q + off + up], [vec2(ba.x, bb.y), vec2(bb.x, bb.y), vec2(bb.x, ba.y), vec2(ba.x, ba.y)], [fc; 4], [-inward; 4]);
ln.strip(p + off + up, q + off + up, inward, OUTLINE_W, OUTLINE_C);
// the chains from the top of the flap down to the bank
let chain = col(Vec3::splat(0.55), 1.0);
for e in [p, q] {
let a = e + off + up + (if e == p { (q - p) * 0.1 } else { (p - q) * 0.1 });
let b = e - inward * 0.6 + Vec3::Y * 1.3;
ln.strip(a, b, inward, OUTLINE_W * 0.7, chain);
}
}
continue;
}
if t.bridge() {
// deck: planks across the direction of the bridge, rails along it
let run_x = |dx: i32| map.get(x + dx, z).map_or(false, |o| o.bridge() || (o.walkable() && !o.bridge()));
let run_z = |dz: i32| map.get(x, z + dz).map_or(false, |o| o.bridge() || (o.walkable() && !o.bridge()));
let along_x = (run_x(-1) as i32 + run_x(1) as i32) > (run_z(-1) as i32 + run_z(1) as i32);
let (ba, bb) = cell_uv(tex);
// a drawbridge over lava is made of stone
let (ba, bb) = cell_uv(if t.kind == Kind::Drawbridge && lava { T_STONEBRIDGE + (t.var as u32 & 1) } else { tex });
let dc = col(lava_lit(Vec3::splat(amb_at(amb, xf + 0.5, zf + 0.5).max(if lava { 0.6 } else { 0.0 })), lg), 1.0);
let uv = if along_x {
[vec2(ba.x, ba.y), vec2(ba.x, bb.y), vec2(bb.x, bb.y), vec2(bb.x, ba.y)]
@@ -735,6 +777,14 @@ fn build_chunk(map: &Map, amb: &[f32], glow: &[f32], cx: i32, cz: i32, atlas: &T
[vec2(ba.x, ba.y), vec2(bb.x, ba.y), vec2(bb.x, bb.y), vec2(ba.x, bb.y)]
};
mb.quad([vec3(xf, DECK_Y, zf), vec3(xf + 1.0, DECK_Y, zf), vec3(xf + 1.0, DECK_Y, zf + 1.0), vec3(xf, DECK_Y, zf + 1.0)], uv, [dc; 4], [Vec3::Y; 4]);
if t.kind == Kind::Drawbridge {
// iron bands across the planks mark a drawbridge
let iron = col(Vec3::splat(0.32), 1.0);
for f in [0.18, 0.82] {
let (a, b) = if along_x { (vec3(xf + f, DECK_Y + 0.005, zf), vec3(xf + f, DECK_Y + 0.005, zf + 1.0)) } else { (vec3(xf, DECK_Y + 0.005, zf + f), vec3(xf + 1.0, DECK_Y + 0.005, zf + f)) };
ln.strip(a, b, Vec3::Y, OUTLINE_W * 1.6, iron);
}
}
// deck edges above open river
for (d, &(dx, dz)) in DIR4.iter().enumerate() {
if !map.get(x + dx, z + dz).map_or(false, |o| o.liquid()) {
@@ -994,6 +1044,7 @@ fn chunk_sig(map: &Map, cx: i32, cz: i32) -> u64 {
let extra = match t.kind {
Kind::Farm => t.food as u64,
Kind::Treasury => (t.gold / 50) as u64 | (t.res as u64) << 5,
Kind::Drawbridge => t.res as u64,
_ => 0,
};
let shown = map.shown(idx(x, z)) as u64;
@@ -3030,6 +3081,8 @@ pub fn minimap_color(tile: &Tile) -> [u8; 4] {
Kind::Lava => [250, 110, 30, 255],
Kind::Bridge => [150, 110, 60, 255],
Kind::LavaBridge => [130, 120, 115, 255],
Kind::Drawbridge => [120, 80, 50, 255],
Kind::Obsidian => [60, 40, 70, 255],
Kind::Shard => [255, 60, 120, 255],
Kind::Aerie => [170, 140, 90, 255],
Kind::Steel => [150, 160, 180, 255],