2019-10-18 20:35:51 +00:00
|
|
|
-- Copyright (c) 2019 David Vogel
|
|
|
|
--
|
|
|
|
-- This software is released under the MIT License.
|
|
|
|
-- https://opensource.org/licenses/MIT
|
|
|
|
|
2019-11-01 01:40:21 +00:00
|
|
|
CAPTURE_PIXEL_SIZE = 1 -- Screen to virtual pixel ratio
|
|
|
|
CAPTURE_GRID_SIZE = 420 -- in ingame pixels. There will always be 3 to 6 images overlapping
|
|
|
|
CAPTURE_DELAY = 15 -- in frames
|
2019-11-02 20:37:10 +00:00
|
|
|
CAPTURE_BIGJUMP_DELAY = 20 -- in frames. Additional delay after doing a "larger than grid jump"
|
2019-11-01 01:40:21 +00:00
|
|
|
CAPTURE_FORCE_HP = 4 -- * 25HP
|
2019-10-18 20:35:51 +00:00
|
|
|
|
2019-11-02 20:37:10 +00:00
|
|
|
CAPTURE_LEFT = -25000 -- in ingame pixels. Left edge of the full map capture rectangle
|
|
|
|
CAPTURE_TOP = -36000 -- in ingame pixels. Top edge of the full map capture rectangle
|
|
|
|
CAPTURE_RIGHT = 25000 -- in ingame pixels. Right edge of the full map capture rectangle (Pixels are not included in the rectangle)
|
|
|
|
CAPTURE_BOTTOM = 36000 -- in ingame pixels. Bottom edge of the full map capture rectangle (Pixels are not included in the rectangle)
|
|
|
|
|
2019-10-18 20:35:51 +00:00
|
|
|
local function preparePlayer()
|
|
|
|
local playerEntity = getPlayer()
|
|
|
|
addEffectToEntity(playerEntity, "PROTECTION_ALL")
|
|
|
|
|
|
|
|
addPerkToPlayer("BREATH_UNDERWATER")
|
|
|
|
addPerkToPlayer("INVISIBILITY")
|
|
|
|
addPerkToPlayer("REMOVE_FOG_OF_WAR")
|
|
|
|
addPerkToPlayer("REPELLING_CAPE")
|
|
|
|
addPerkToPlayer("WORM_DETRACTOR")
|
|
|
|
|
|
|
|
setPlayerHP(CAPTURE_FORCE_HP)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function resetPlayer()
|
|
|
|
setPlayerHP(CAPTURE_FORCE_HP)
|
|
|
|
end
|
|
|
|
|
2019-11-02 23:58:03 +00:00
|
|
|
local xOld, yOld = 0, 0
|
|
|
|
local function captureScreenshot(x, y, rx, ry)
|
|
|
|
-- "Larger than grid jump" delay
|
|
|
|
local delay = CAPTURE_DELAY - 1
|
|
|
|
if math.abs(x - xOld) > CAPTURE_GRID_SIZE or math.abs(y - yOld) > CAPTURE_GRID_SIZE then
|
|
|
|
delay = delay + CAPTURE_BIGJUMP_DELAY
|
|
|
|
end
|
|
|
|
xOld, yOld = x, y
|
|
|
|
|
|
|
|
-- Set pos several times, so that chunks will load even if nothing happens in the surrounding
|
|
|
|
-- This prevents black blocks in areas without entites
|
|
|
|
for i = 1, delay, 1 do
|
|
|
|
GameSetCameraPos(x, y)
|
|
|
|
wait(1)
|
|
|
|
end
|
|
|
|
GameSetCameraPos(x, y)
|
|
|
|
|
|
|
|
UiHide = true -- Hide UI while capturing the screenshot
|
|
|
|
wait(1)
|
|
|
|
if not TriggerCapture(rx, ry) then
|
|
|
|
UiCaptureProblem = "Screen capture failed. Please restart Noita."
|
|
|
|
end
|
|
|
|
UiHide = false
|
|
|
|
end
|
|
|
|
|
2019-11-02 20:37:10 +00:00
|
|
|
function startCapturingSpiral()
|
2019-10-25 15:29:52 +00:00
|
|
|
local ox, oy = GameGetCameraPos()
|
2019-10-20 14:28:17 +00:00
|
|
|
ox, oy = math.floor(ox / CAPTURE_GRID_SIZE) * CAPTURE_GRID_SIZE, math.floor(oy / CAPTURE_GRID_SIZE) * CAPTURE_GRID_SIZE
|
2019-10-18 20:35:51 +00:00
|
|
|
local x, y = ox, oy
|
|
|
|
|
2019-11-02 23:58:03 +00:00
|
|
|
local virtualWidth, virtualHeight =
|
|
|
|
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_X")),
|
|
|
|
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y"))
|
|
|
|
|
|
|
|
local virtualHalfWidth, virtualHalfHeight = math.floor(virtualWidth / 2), math.floor(virtualHeight / 2)
|
|
|
|
|
2019-10-18 20:35:51 +00:00
|
|
|
preparePlayer()
|
|
|
|
|
2019-10-20 14:28:17 +00:00
|
|
|
GameSetCameraFree(true)
|
2019-10-18 20:35:51 +00:00
|
|
|
|
|
|
|
-- Coroutine to calculate next coordinate, and trigger screenshots
|
|
|
|
local i = 1
|
|
|
|
async_loop(
|
|
|
|
function()
|
|
|
|
-- +x
|
|
|
|
for i = 1, i, 1 do
|
2019-11-02 23:58:03 +00:00
|
|
|
local rx, ry = x * CAPTURE_PIXEL_SIZE - virtualHalfWidth, y * CAPTURE_PIXEL_SIZE - virtualHalfHeight
|
2019-10-23 18:03:03 +00:00
|
|
|
if not fileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
2019-11-02 23:58:03 +00:00
|
|
|
captureScreenshot(x, y, rx, ry)
|
2019-10-23 18:03:03 +00:00
|
|
|
end
|
2019-10-18 20:35:51 +00:00
|
|
|
x, y = x + CAPTURE_GRID_SIZE, y
|
|
|
|
end
|
|
|
|
-- +y
|
|
|
|
for i = 1, i, 1 do
|
2019-11-02 23:58:03 +00:00
|
|
|
local rx, ry = x * CAPTURE_PIXEL_SIZE - virtualHalfWidth, y * CAPTURE_PIXEL_SIZE - virtualHalfHeight
|
2019-10-23 18:03:03 +00:00
|
|
|
if not fileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
2019-11-02 23:58:03 +00:00
|
|
|
captureScreenshot(x, y, rx, ry)
|
2019-10-23 18:03:03 +00:00
|
|
|
end
|
2019-10-18 20:35:51 +00:00
|
|
|
x, y = x, y + CAPTURE_GRID_SIZE
|
|
|
|
end
|
|
|
|
i = i + 1
|
|
|
|
-- -x
|
|
|
|
for i = 1, i, 1 do
|
2019-11-02 23:58:03 +00:00
|
|
|
local rx, ry = x * CAPTURE_PIXEL_SIZE - virtualHalfWidth, y * CAPTURE_PIXEL_SIZE - virtualHalfHeight
|
2019-10-23 18:03:03 +00:00
|
|
|
if not fileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
2019-11-02 23:58:03 +00:00
|
|
|
captureScreenshot(x, y, rx, ry)
|
2019-10-23 18:03:03 +00:00
|
|
|
end
|
2019-10-18 20:35:51 +00:00
|
|
|
x, y = x - CAPTURE_GRID_SIZE, y
|
|
|
|
end
|
|
|
|
-- -y
|
|
|
|
for i = 1, i, 1 do
|
2019-11-02 23:58:03 +00:00
|
|
|
local rx, ry = x * CAPTURE_PIXEL_SIZE - virtualHalfWidth, y * CAPTURE_PIXEL_SIZE - virtualHalfHeight
|
2019-10-23 18:03:03 +00:00
|
|
|
if not fileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
2019-11-02 23:58:03 +00:00
|
|
|
captureScreenshot(x, y, rx, ry)
|
2019-10-23 18:03:03 +00:00
|
|
|
end
|
2019-10-18 20:35:51 +00:00
|
|
|
x, y = x, y - CAPTURE_GRID_SIZE
|
|
|
|
end
|
|
|
|
i = i + 1
|
|
|
|
end
|
|
|
|
)
|
|
|
|
end
|
2019-11-02 20:37:10 +00:00
|
|
|
|
|
|
|
function startCapturingHilbert()
|
|
|
|
local ox, oy = GameGetCameraPos()
|
|
|
|
|
2019-11-02 23:58:03 +00:00
|
|
|
local virtualWidth, virtualHeight =
|
|
|
|
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_X")),
|
|
|
|
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y"))
|
|
|
|
|
|
|
|
local virtualHalfWidth, virtualHalfHeight = math.floor(virtualWidth / 2), math.floor(virtualHeight / 2)
|
|
|
|
|
2019-11-02 20:37:10 +00:00
|
|
|
-- Get size of the rectangle in grid/chunk coordinates
|
|
|
|
local gridLeft = math.floor(CAPTURE_LEFT / CAPTURE_GRID_SIZE)
|
|
|
|
local gridTop = math.floor(CAPTURE_TOP / CAPTURE_GRID_SIZE)
|
|
|
|
local gridRight = math.ceil(CAPTURE_RIGHT / CAPTURE_GRID_SIZE) + 1
|
|
|
|
local gridBottom = math.ceil(CAPTURE_BOTTOM / CAPTURE_GRID_SIZE) + 1
|
|
|
|
|
|
|
|
-- Size of the grid in chunks
|
|
|
|
local gridWidth = gridRight - gridLeft
|
|
|
|
local gridHeight = gridBottom - gridTop
|
|
|
|
|
|
|
|
-- Hilbert curve can only fit into a square, so get the longest side
|
|
|
|
local gridPOTSize = math.ceil(math.log(math.max(gridWidth, gridHeight)) / math.log(2))
|
|
|
|
-- Max size (Already rounded up to the next power of two)
|
|
|
|
local gridMaxSize = math.pow(2, gridPOTSize)
|
|
|
|
|
|
|
|
local t, tLimit = 0, gridMaxSize * gridMaxSize
|
|
|
|
|
|
|
|
UiProgress = {Progress = 0, Max = gridWidth * gridHeight}
|
|
|
|
|
|
|
|
preparePlayer()
|
|
|
|
|
|
|
|
GameSetCameraFree(true)
|
|
|
|
|
|
|
|
-- Coroutine to calculate next coordinate, and trigger screenshots
|
|
|
|
async(
|
|
|
|
function()
|
|
|
|
while t < tLimit do
|
|
|
|
local hx, hy = mapHilbert(t, gridPOTSize)
|
|
|
|
if hx < gridWidth and hy < gridHeight then
|
|
|
|
local x, y = (hx + gridLeft) * CAPTURE_GRID_SIZE, (hy + gridTop) * CAPTURE_GRID_SIZE
|
2019-11-02 23:58:03 +00:00
|
|
|
local rx, ry = x * CAPTURE_PIXEL_SIZE - virtualHalfWidth, y * CAPTURE_PIXEL_SIZE - virtualHalfHeight
|
2019-11-02 20:37:10 +00:00
|
|
|
if not fileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
2019-11-02 23:58:03 +00:00
|
|
|
captureScreenshot(x, y, rx, ry)
|
2019-11-02 20:37:10 +00:00
|
|
|
end
|
|
|
|
UiProgress.Progress = UiProgress.Progress + 1
|
|
|
|
end
|
|
|
|
|
|
|
|
t = t + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
)
|
|
|
|
end
|