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:
1 parent
f98f05f0d2
commit
3e17bdf52d
27 files changed
+555
-5
No files matched your search
+79
-2
@@ -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() {
|
||||
|
||||
Reference in new issue
Block a user