DramaticShapeVoxelMod archival mirror · read-only
99e18f7b5b0525f6d24e3899954425edfac89539

set viridian to night time lighting

DramaticShape · 2026-07-29 · parent 9c263f0937

set viridian to night time lighting

Changed files

CHANGELOG.md                  |  7 ++++++-
 README.md                     |  5 ++++-
 tests/daynight_shots.lua      | 12 ++++++++++++
 tests/dramatic_shape_test.lua | 18 ++++++++++++++++++
 4 files changed, 40 insertions(+), 2 deletions(-)

Diff

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 349753a..8056582 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -102,7 +102,12 @@
 
   **Outdoors only**, by the same `Map.isOutdoor` test the sky already rests
   on: indoors keeps the noon rig, the neutral tint and no sky -- a cave at
-  midnight is exactly as dark as a cave at noon. A battle staged on an
+  midnight is exactly as dark as a cave at noon. Viridian Forest is the case
+  between, a CANOPY map (DayNight.CANOPY): there is no sky to paint and no
+  sun to see, so the shadow rig stays the mod's fixed noon light -- all that
+  ever filtered through the leaves -- but night still FALLS in a forest, so
+  of everything the clock does, exactly one thing reaches it: the hour's
+  tint, in free-roam and staged battles alike. A battle staged on an
   outdoor map fights under the hour: the night sky behind the arena, the
   tint on the mons, the sunset taking the arena's shadows with it; an indoor
   arena is untouched. The engine's own `world.tod` hook is answered
diff --git a/README.md b/README.md
index b5c23f9..aa0e410 100644
--- a/README.md
+++ b/README.md
@@ -114,7 +114,10 @@ the sun, the shadow map and the hour's tint. The lamps come on through dusk,
 burn all night, and are mostly out again by dawn.
 
 **Outdoors only.** Indoors keeps the noon rig, the neutral tint and no sky:
-a cave at midnight is exactly as dark as a cave at noon. A battle staged on
+a cave at midnight is exactly as dark as a cave at noon. Viridian Forest is
+the case between — a **canopy** map: no sky and the light through the
+leaves stays at the mod's fixed noon angle, but the hour's *tint* still
+falls through, so night reaches the forest floor. A battle staged on
 an outdoor map fights under the hour — night void behind the arena, tinted
 mons, sunset taking the arena's shadows with it — and an indoor arena is
 untouched. The engine's `world.tod` hook is answered
diff --git a/tests/daynight_shots.lua b/tests/daynight_shots.lua
index 90e841e..08c3f83 100644
--- a/tests/daynight_shots.lua
+++ b/tests/daynight_shots.lua
@@ -92,6 +92,18 @@ return function(game)
     U.shot(game, DIR .. "/50_indoor_at_night.png")
   end
 
+  -- ------- the forest, where only the TINT of it reaches: night falls
+  -- through the canopy, but there is no sky and the noon light stays put
+  setTime("night")
+  if game.data.maps.VIRIDIAN_FOREST then
+    U.teleport(game, "VIRIDIAN_FOREST", 17, 20, "up")
+    U.wait(120)
+    U.shot(game, DIR .. "/51_forest_night.png")
+    setTime("day")
+    U.wait(30)
+    U.shot(game, DIR .. "/52_forest_day.png")
+  end
+
   setTime("day")
   U.log("done -- " .. DIR)
 end
diff --git a/tests/dramatic_shape_test.lua b/tests/dramatic_shape_test.lua
index c05eab1..e4a0c28 100644
--- a/tests/dramatic_shape_test.lua
+++ b/tests/dramatic_shape_test.lua
@@ -2106,6 +2106,24 @@ Voxel3D.tint = { 1, 1, 1 }
 Voxel3D.vp = nil
 end
 
+-- ------- night falls in the forest
+--
+-- Viridian Forest is not outdoor (no sky, and the light through the leaves
+-- has no direction to swing) and not a sealed room either. Of everything
+-- the clock does, exactly one thing reaches a canopy map: the hour's tint.
+-- The scenes wire it as tint(outdoor or isCanopy(map)) over the unchanged
+-- noon rig, so what is checked here is the classification itself.
+do
+local DayNight = run.loader.exports.DRAMATIC_SHAPE.lib.require("DayNight")
+T.check(DayNight.isCanopy({ id = "VIRIDIAN_FOREST" }),
+  "Viridian Forest stands under a canopy")
+T.check(not DayNight.isCanopy({ id = "MT_MOON_1F" }),
+  "a cave does not -- midnight there is exactly as dark as noon")
+T.check(not DayNight.isCanopy({ id = "PALLET_TOWN" }),
+  "and an outdoor town is already the clock's in full")
+T.check(not DayNight.isCanopy(nil), "no map, no canopy")
+end
+
 -- ------- a shadow keeps hold of the feet that throw it
 --
 -- The depth compare forgives `slack` world pixels so lit ground does not