revert battle locations temporarily

This commit is contained in:
DramaticShape
2026-08-06 19:56:39 -04:00
parent c8555e6820
commit 53fff766a4
14 changed files with 922 additions and 161 deletions
+205 -11
View File
@@ -451,20 +451,19 @@ T.eq(settingGame.mods.modOptions.DRAMATIC_SHAPE.grid, true,
grid.step(settingGame)
T.eq(grid.value(), "OFF", "stepping again toggles it back")
-- the curve is a four-rung ladder rather than a toggle, and wraps
-- the curve is a six-rung ladder rather than a toggle, and wraps
curve.step(settingGame, 1)
T.eq(curve.value(), "1", "stepping the curve climbs its ladder")
T.eq(settingGame.save.options.modOptions.DRAMATIC_SHAPE.curve, 1,
"the curve level persists alongside the grid, not over it")
T.eq(settingGame.save.options.modOptions.DRAMATIC_SHAPE.grid, false,
"and the grid it shares a bucket with is untouched")
curve.step(settingGame, 1)
curve.step(settingGame, 1)
T.eq(curve.value(), "3", "the ladder reaches its top rung")
for _ = 1, 4 do curve.step(settingGame, 1) end
T.eq(curve.value(), "5", "the ladder reaches its top rung")
curve.step(settingGame, 1)
T.eq(curve.value(), "OFF", "and wraps back to OFF")
curve.step(settingGame, -1)
T.eq(curve.value(), "3", "stepping down from OFF wraps to the top")
T.eq(curve.value(), "5", "stepping down from OFF wraps to the top")
curve.step(settingGame, 1)
-- the strength scales with the view height, so a rung looks the same at
@@ -474,9 +473,25 @@ T.eq(WorldCurve.k(154), 0, "an OFF curve bends nothing")
curve.step(settingGame, 1)
T.check(math.abs(WorldCurve.k(154) - WorldCurve.AMOUNTS[2] / 154) < 1e-9,
"rung 1's coefficient is its amount over the view height")
T.check(WorldCurve.AMOUNTS[2] < WorldCurve.AMOUNTS[3]
and WorldCurve.AMOUNTS[3] < WorldCurve.AMOUNTS[4],
"the ladder climbs")
for i = 2, #WorldCurve.AMOUNTS do
T.check(WorldCurve.AMOUNTS[i] > WorldCurve.AMOUNTS[i - 1],
"the ladder climbs at rung " .. (i - 1))
end
-- rung 5 is the HALF SPHERE, and that is arithmetic rather than taste: the
-- parabola y = k d^2 osculates a sphere of radius R at its pole when
-- k = 1 / 2R, so an amount of 1 puts the sphere's radius at half a view
-- height -- which is exactly where the diorama's box is cut, so the
-- model's own rim is that sphere's equator
T.eq(WorldCurve.AMOUNTS[#WorldCurve.AMOUNTS], 1.0,
"the top rung's amount is 1 -- the half sphere")
do
local Dio = run.loader.exports.DRAMATIC_SHAPE.lib.require("Diorama")
local vh = 288
local kTop = WorldCurve.AMOUNTS[#WorldCurve.AMOUNTS] / vh
T.check(math.abs(1 / (2 * kTop) - vh * Dio.BOX_FRAC) < 1e-6,
"whose radius is the diorama's own half-size: the model ends where "
.. "the dome does")
end
T.check(math.abs(WorldCurve.k(308) * 2 - WorldCurve.k(154)) < 1e-9,
"halving the zoom halves the coefficient, so the bend looks the same")
-- the CPU copy Voxel3D.project uses must agree with the shader's quadratic
@@ -488,9 +503,7 @@ T.check(math.abs(WorldCurve.drop(k, 0, 0, 3, 4) - 25 * k) < 1e-9,
T.check(WorldCurve.drop(k, 0, 0, 20, 0) > 4 * WorldCurve.drop(k, 0, 0, 10, 0)
- 1e-9,
"and accelerates, so the far edge rolls away faster than the near one")
curve.step(settingGame, 1)
curve.step(settingGame, 1)
curve.step(settingGame, 1)
for _ = 1, 5 do curve.step(settingGame, 1) end
T.eq(curve.value(), "OFF", "the curve is left off for the rows below")
-- ------- AA renders the pass larger and folds it back down
@@ -5206,6 +5219,187 @@ T.eq(type(VRMod.leave), "function",
end
vrRigSection()
-- ------- the DIORAMA modes
--
-- The VR row is a ladder now -- OFF / STANDARD / DIORAMA / DIORAMA-MR --
-- and the two diorama rungs are one presentation rather than a follow-on
-- from the VOXEL ladder: a viewport that cuts the world to a ball (a
-- pillar while a fight is staged), a base a tile deep under it, and grips
-- that carry, turn and resize the whole thing.
;(function()
local lib = run.loader.exports.DRAMATIC_SHAPE.lib
local VRM = lib.require("VR")
local D = lib.require("Diorama")
local V3 = lib.require("Voxel3D")
local Rig = lib.require("VRRig")
-- ------- the row
T.eq(#VRM.setting.values, 4, "the VR row carries four rungs")
T.eq(VRM.setting.values[2], true,
"STANDARD is still stored as `true` -- a save written when the row was "
.. "a toggle comes back on the rung it was left on")
T.eq(VRM.setting.labels[3] .. "/" .. VRM.setting.labels[4],
"DIORAMA/DIORAMA-MR", "and the two diorama rungs are labelled")
VRM.setting:sync(false)
T.eq(VRM.mode(), "off", "OFF is off")
VRM.setting:sync(true)
T.eq(VRM.mode(), "standard", "the stored true reads as STANDARD")
T.eq(VRM.dioramaMode(), false, "which is not a diorama")
VRM.setting:sync("diorama")
T.eq(VRM.mode(), "diorama", "and the diorama rungs read as themselves")
T.check(VRM.enabled() and VRM.dioramaMode(), "both on and a diorama")
VRM.setting:sync("diorama-mr")
T.check(VRM.dioramaMode(), "MR is a diorama too")
T.eq(VRM.setting:get(), "diorama-mr", "under its own stored value")
-- ------- the frame's own switches
T.eq(D.begin("standard"), false, "STANDARD opens no diorama frame")
T.eq(D.keyColor(), nil, "and keys nothing")
T.eq(D.begin("diorama"), true, "DIORAMA opens one")
T.eq(D.keyColor(), nil, "and still keys nothing -- it has a sky")
T.eq(D.begin("diorama-mr"), true, "MR opens one as well")
T.eq(D.keyColor()[2], 1, "and keys the background PURE green")
T.check(D.keyColor()[1] == 0 and D.keyColor()[3] == 0,
"no red and no blue in it: a keyer wants the colour the world cannot be")
-- ------- the viewport
--
-- A square BOX with a hard edge while the world is flat, and the ball
-- with the dissolved rim while V-CURVE bends it -- one click of the
-- left stick throws the row and swaps the whole reading.
local Curve = lib.require("WorldCurve")
local curveWas = Curve.setting:get()
Curve.setting:sync(0)
local box = D.viewport(100, 200, 288)
T.eq(box.kind, D.BOX, "a flat world is cut by a square BOX")
T.check(box.x == 100 and box.z == 200, "centred on the view")
T.check(math.abs(box.r - 288 * D.BOX_FRAC) < 1e-6,
"spanning exactly the view the standard rung would have framed, so "
.. "the zoom rows keep meaning what they mean")
T.check(1 / box.invFade <= 0.5,
"with a HARD edge: a flat world is a thing with sides")
T.eq(D.fadeFor(100, false), 0, "and no fade band to speak of")
Curve.setting:sync(3)
local ball = D.viewport(100, 200, 288)
T.eq(ball.kind, D.BALL, "V-CURVE turns the box into a BALL")
T.check(math.abs(1 / ball.invFade - ball.r * D.FADE_FRAC) < 1e-6,
"whose rim is a gradient fade into the sky rather than an edge")
T.check(ball.r > box.r,
"and which reaches further than the square did, so the throw curls "
.. "the same model rather than shaving its corners off")
local pillar = D.pillar({ mid = { 64, 96 },
player = { 64, 120 }, enemy = { 64, 72 } })
T.eq(pillar.kind, D.PILLAR, "a staged fight cuts a vertical PILLAR instead")
T.check(pillar.x == 64 and pillar.z == 96, "about the arena's midpoint")
T.check(math.abs(pillar.r - (24 + D.ARENA_APRON)) < 1e-6,
"wide enough for both mons and an apron -- the floating disc")
T.eq(D.pillar(nil), nil, "and no arena cuts nothing")
Curve.setting:sync(0)
local flatFight = D.pillar({ mid = { 0, 0 } })
T.eq(flatFight.kind, D.PILLAR,
"the fight stays round whatever the curve is doing: a square tile "
.. "floating in the air is not the picture")
T.check(1 / flatFight.invFade > 1,
"and keeps its dissolve with the curve off too -- a hard edge on "
.. "something hanging in the air reads as a cookie cutter")
Curve.setting:sync(curveWas)
-- the shader takes the volume through a plain field, so no pass can be
-- surprised by a cut world (Voxel3D never requires lib/Diorama)
T.eq(V3.cull, nil, "nothing has left a viewport on Voxel3D")
T.eq(V3.keyColor, nil, "nor a chroma key")
-- ------- the grips
D.reset()
local function hand(x, y, z) return { pos = { x, y, z } } end
T.eq(D.gesture({ gripL = 0, gripR = 0 }), false, "an open hand holds nothing")
-- one grip: the model follows that hand, metre for metre, and the first
-- frame of a squeeze moves nothing (there is no delta yet)
D.gesture({ gripL = 1, handl = hand(0, 1, 0) })
T.eq(D.offset[2], 0, "taking hold does not itself move the model")
D.gesture({ gripL = 1, handl = hand(0.1, 1.25, -0.2) })
T.check(math.abs(D.offset[1] - 0.1) < 1e-9
and math.abs(D.offset[2] - 0.25) < 1e-9
and math.abs(D.offset[3] + 0.2) < 1e-9,
"one grip carries it through the room in all three axes")
D.gesture({ gripL = 0, gripR = 0 })
D.gesture({ gripL = 1, handl = hand(5, 5, 5) })
T.check(math.abs(D.offset[2] - 0.25) < 1e-9,
"letting go and taking hold somewhere else never snaps it")
-- both grips: the turn and the resize, off the line between the hands
D.reset()
D.gesture({ gripL = 1, gripR = 1,
handl = hand(-0.2, 1, 0), handr = hand(0.2, 1, 0) })
local zoom0 = D.zoom
D.gesture({ gripL = 1, gripR = 1,
handl = hand(0, 1, 0.2), handr = hand(0, 1, -0.2) })
T.check(math.abs(D.yaw - math.pi / 2) < 1e-6,
"hand over hand turns the model by the same angle the mapping yaws by")
T.check(math.abs(D.zoom - zoom0) < 1e-6,
"a pure turn does not resize it")
D.gesture({ gripL = 1, gripR = 1,
handl = hand(0, 1, 0.4), handr = hand(0, 1, -0.4) })
T.check(math.abs(D.zoom - zoom0 * 2) < 1e-6,
"opening the hands opens the viewport by the same factor")
for _ = 1, 12 do
D.gesture({ gripL = 1, gripR = 1,
handl = hand(0, 1, 4), handr = hand(0, 1, -4) })
D.gesture({ gripL = 1, gripR = 1,
handl = hand(0, 1, 0.001), handr = hand(0, 1, -0.001) })
end
T.check(D.zoom >= D.SCALE_MIN and D.zoom <= D.SCALE_MAX,
"and it stays inside its stops however hard it is worked")
-- ------- and NO base under it
--
-- The ground was extruded a tile deep once, cut to the viewport's shape
-- and wearing Mt Moon's cave floor down its sides. It was removed at the
-- user's request; the cut ends at the ground plane. Pinned so nothing
-- puts a plinth back under the model by accident.
T.eq(D.drawBase, nil, "the diorama draws no base under the world")
T.eq(D.BASE_DEPTH, nil, "and keeps none of the arithmetic for one")
-- ------- and the curve reaches the eyes
--
-- It did not: eyeCamera hardcoded `curve = 0`, and Voxel3D reads that
-- field with `or` -- where 0 is TRUE in Lua -- so the bend was pinned
-- off for every VR frame and the diorama's own V-CURVE throw did
-- nothing at all. The rig takes it as a parameter now, and declining is
-- still the default for the modes that want to decline.
local POSE = { pos = { 0, 0, 0 }, quat = { 0, 0, 0, 1 } }
local FOV = { angleLeft = -0.7, angleRight = 0.7,
angleUp = 0.6, angleDown = -0.6 }
local plain = Rig.eyeCamera(POSE, FOV, { 0, 0, 0 }, { 0, 0, 0 }, 64)
T.eq(plain.curve, 0,
"an eye declines the curve unless it asks -- first person and the "
.. "battle seat both do")
local bent = Rig.eyeCamera(POSE, FOV, { 0, 0, 0 }, { 0, 0, 0 }, 64, nil,
0.004)
T.eq(bent.curve, 0.004,
"and a diorama's eye carries the bend it asked for, which is what "
.. "the left stick's throw is for")
-- ------- the mapping carries all three axes now
local a = Rig.dioramaAnchor(0, { 0.5, 0.25, -0.75 })
T.check(math.abs(a[1] - 0.5) < 1e-9 and math.abs(a[3] + 0.75) < 1e-9,
"the diorama anchor takes the carry in all three axes")
T.check(math.abs(a[2] - (0.25 - Rig.VIEW_DIST)) < 1e-9,
"with the height still riding the rung's own viewing line")
local b = Rig.dioramaAnchor(0, 0.25)
T.check(math.abs(b[2] - a[2]) < 1e-9 and b[1] == 0,
"and a bare number is still the height alone -- STANDARD's own drag")
-- ------- what the mode refuses
T.eq(VRM.DIORAMA_RUNG, 3,
"a diorama holds the VOXEL ladder on an orbit rung: there is no 2D "
.. "diorama, and no first-person one either")
T.eq(type(VRM.toggleCurve), "function",
"and the left stick's click throws V-CURVE instead of stepping views")
D.reset()
VRM.setting:sync(false)
T.eq(D.on, false, "and the frame shuts with the session")
end)()
-- ------- the skybox's checker and glow are the sky's own, not the screen's
--
-- The bands were already read by angle, but the DITHER between them kept