Weather above ground: rain puts out fires, fog shortens sight, storms strike with lightning

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-06 12:11:19 +01:00
1 parent f98f05f0d2
commit 3e17bdf52d
27 files changed
+555 -5

No files matched your search

+79 -2
View File
@@ -512,6 +512,11 @@ fn room_level_at(map: &Map, t: &Tile) -> u8 {
}
// Ambient light field: own territory is lit, foreign areas are dim
thread_local! {
// daylight above ground (bad weather dims it), in tenths
static SKY_LIGHT: std::cell::Cell<u32> = const { std::cell::Cell::new(16) };
}
fn ambient_field(map: &Map) -> Vec<f32> {
let mut f = vec![0.0f32; n()];
for (i, t) in map.t.iter().enumerate() {
@@ -522,7 +527,7 @@ fn ambient_field(map: &Map) -> Vec<f32> {
};
// daylight above ground (cliffs and trees too)
if map.sky(i) {
f[i] = 1.6;
f[i] = SKY_LIGHT.with(|s| s.get()) as f32 / 10.0;
}
// rooms of a higher level shine brighter
let lv = room_level_at(map, t);
@@ -1279,6 +1284,14 @@ impl R3d {
fn update_chunks(&mut self, g: &Game, gfx: &Gfx, m: &Mat4) {
self.ensure_chunks();
let side = g.me.side().min(7);
// the weather dims the daylight: the chunks above ground are lit again in steps
let sky = ((1.6 * (1.0 - g.weather.gloom())) * 10.0).round() as u32;
if SKY_LIGHT.with(|s| s.get()) != sky {
SKY_LIGHT.with(|s| s.set(sky));
for ch in self.chunks.iter_mut() {
ch.sig = 0;
}
}
if view_side() != side {
// another master looks: the marks change colour
VIEW_SIDE.with(|v| v.set(side));
@@ -1609,6 +1622,7 @@ impl R3d {
}
draw_traps_glow(g, t);
draw_parts_glow(g);
draw_weather(g, cam, t);
gl_use_default_material();
crate::ui::begin_ui();
if let (Some((_, _, k)), Some((rt, tw, th))) = (pix, self.target.as_ref()) {
@@ -1629,7 +1643,7 @@ impl R3d {
let (ix, iz) = (x as i32, z as i32);
let own = g.map.get(ix, iz).map_or(false, |t| matches!(t.owner, Owner::Player | Owner::Rival1 | Owner::Rival2 | Owner::Rival3));
if inb(ix, iz) && g.map.sky(idx(ix, iz)) {
0.95
0.95 * (1.0 - 0.6 * g.weather.gloom())
} else if own {
0.75
} else {
@@ -2489,6 +2503,69 @@ fn draw_landmarks_solid(g: &Game, t: f32) {
let _ = t;
}
// rain streaks and fog veils over the land above ground near the camera; a storm's lightning
// lights the sky up for a moment
fn draw_weather(g: &Game, cam: &Cam, t: f32) {
let w = &g.weather;
if w.level <= 0.01 || g.map.sky.is_empty() {
return;
}
let (cx, cz) = (cam.rx as i32, cam.rz as i32);
let reach = (cam.view_h() * 1.2) as i32 + 4;
let sky = |x: i32, z: i32| inb(x, z) && g.map.sky(idx(x, z));
// fog: veils at two heights, one plane per run of open sky tiles in a row
let fog = w.fog();
if fog > 0.01 {
for (h, a) in [(0.7f32, 0.22f32), (1.6, 0.16)] {
let col = Color::new(0.75, 0.78, 0.8, a * fog);
for z in cz - reach..=cz + reach {
let mut x = cx - reach;
while x <= cx + reach {
if !sky(x, z) {
x += 1;
continue;
}
let x0 = x;
while x <= cx + reach && sky(x, z) {
x += 1;
}
let len = (x - x0) as f32;
let drift = (t * 0.2 + z as f32 * 0.7).sin() * 0.15;
draw_plane(vec3(x0 as f32 + len * 0.5 + drift, h, z as f32 + 0.5), vec2(len * 0.5, 0.5), None, col);
}
}
}
}
// rain: slanted streaks falling over the open land
let rain = w.rain();
if rain > 0.01 {
let n = (1100.0 * rain) as u32;
let col = Color::new(0.75, 0.82, 0.95, 0.8);
let span = (2 * reach + 1) as u32;
for k in 0..n {
let h = k.wrapping_mul(2654435761) ^ 0x9e37_79b9;
let x = cx - reach + (h % span) as i32;
let z = cz - reach + ((h >> 11) % span) as i32;
if !sky(x, z) {
continue;
}
let fx = x as f32 + ((h >> 3) % 100) as f32 / 100.0;
let fz = z as f32 + ((h >> 17) % 100) as f32 / 100.0;
let fall = (t * 1.6 + (h % 1000) as f32 / 1000.0).fract();
let y = 3.0 * (1.0 - fall);
line3(vec3(fx, y + 0.5, fz - 0.08), vec3(fx + 0.05, y, fz + 0.08), 0.035, col);
}
}
// the flash of a lightning bolt
let since = g.time - w.flash;
if w.flash > 0.0 && (0.0..0.25).contains(&since) {
let a = 0.35 * (1.0 - since / 0.25);
for z in (cz - reach..=cz + reach).step_by(4) {
draw_plane(vec3(cx as f32, 0.05, z as f32 + 2.0), vec2(reach as f32, 2.0), None, Color::new(0.9, 0.92, 1.0, a));
}
}
}
// growth stage of a giant mushroom: 0 a sprout .. 4 fully grown (felling only then)
fn mushroom_stage(t: &Tile) -> u32 {
if t.grown() {