1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2026-01-24 13:30:55 +00:00
openmw/files/data/scripts/map_extractor/global.lua
2026-01-02 20:05:50 +03:00

177 lines
No EOL
5.3 KiB
Lua

local util = require("openmw.util")
local world = require("openmw.world")
local async = require("openmw.async")
local core = require("openmw.core")
local types = require("openmw.types")
local visitedCells = {}
local cellCount = #world.cells
local i = cellCount
local lastTimestamp = core.getRealTime() - 100
local timeFromLast = 100
local function getExCellId(gridX, gridY)
return string.format("(%d,%d)", gridX, gridY)
end
local function getCellId(cell)
if not cell then return end
if cell.isExterior then
return getExCellId(cell.gridX, cell.gridY)
else
return (cell.id or ""):gsub(":", "")
end
end
local function showCompletionMessage()
if world.isMapExtractionActive() then
async:newUnsavableSimulationTimer(0.1, showCompletionMessage)
return
end
local pl = world.players[1]
pl:sendEvent("builtin:map_extractor:updateMenu", {
line1 = "Map extraction complete.",
line2 = "",
line3 = "",
})
end
local function generateTilemap()
if world.isMapExtractionActive() then
async:newUnsavableSimulationTimer(0.1, generateTilemap)
return
end
local pl = world.players[1]
pl:sendEvent("builtin:map_extractor:updateMenu", {
line1 = "Generating tile world map...",
line2 = "The game may freeze for a short time.",
line3 = "",
})
async:newUnsavableSimulationTimer(0.2, function ()
world.generateTileWorldMap(util.color.rgb(0.255, 0.224, 0.180))
showCompletionMessage()
end)
end
local function processAndTeleport(skipExtraction)
local pl = world.players[1]
if not skipExtraction then
world.extractLocalMaps()
end
local function func()
if world.isMapExtractionActive() then
async:newUnsavableSimulationTimer(0.05, func)
return
elseif skipExtraction then
pl:sendEvent("builtin:map_extractor:updateMenu", {
line1 = "Generating local maps...",
})
end
repeat
if i % 50 == 0 then
local currentTime = core.getRealTime()
timeFromLast = (timeFromLast + currentTime - lastTimestamp) / 2
lastTimestamp = currentTime
end
local res, cell = pcall(function ()
return world.cells[i]
end)
if not res then cell = nil end
i = i - 1
local pos
local customCellId = getCellId(cell)
if not cell or not customCellId or visitedCells[customCellId] then goto continue end
visitedCells[customCellId] = true
if cell.isExterior then
for j = cell.gridX - 1, cell.gridX + 1 do
for k = cell.gridY - 1, cell.gridY + 1 do
visitedCells[getExCellId(j, k)] = true
end
end
end
if cell.isExterior then
pos = util.vector3(cell.gridX * 8192 + 4096, cell.gridY * 8192 + 4096, 0)
else
pos = util.vector3(0, 0, 0)
end
do
local estimatedTimeLeft = math.max(timeFromLast, 1) / 50 * i
local hours = math.floor(estimatedTimeLeft / 3600)
estimatedTimeLeft = estimatedTimeLeft % 3600
local minutes = math.floor(estimatedTimeLeft / 60)
local seconds = estimatedTimeLeft % 60
pl:sendEvent("builtin:map_extractor:updateMenu", {
line2 = string.format("Processed %d / %d cells", cellCount - i, cellCount),
line3 = string.format("Estimated time left: %d:%02d:%02.0f", hours, minutes, seconds),
})
print(string.format('Teleporting to cell #%d: "%s"', i, customCellId))
pl:teleport(cell, pos)
break
end
::continue::
until i <= 0
if i <= 0 then
generateTilemap()
end
end
async:newUnsavableSimulationTimer(0.05, func)
end
async:newUnsavableSimulationTimer(0.1, function ()
local pl = world.players[1]
pl:sendEvent("builtin:map_extractor:updateMenu", {line1 = "Generating world map..."})
world.enableExtractionMode()
types.Player.setControlSwitch(pl, types.Player.CONTROL_SWITCH.Controls, false)
types.Player.setControlSwitch(pl, types.Player.CONTROL_SWITCH.Fighting, false)
types.Player.setControlSwitch(pl, types.Player.CONTROL_SWITCH.Jumping, false)
types.Player.setControlSwitch(pl, types.Player.CONTROL_SWITCH.Looking, false)
types.Player.setControlSwitch(pl, types.Player.CONTROL_SWITCH.Magic, false)
types.Player.setControlSwitch(pl, types.Player.CONTROL_SWITCH.VanityMode, false)
types.Player.setControlSwitch(pl, types.Player.CONTROL_SWITCH.ViewMode, false)
async:newUnsavableSimulationTimer(0.1, function ()
world.extractWorldMap()
if not world.getOverwriteFlag() then
for _, cellId in pairs(world.getExistingLocalMapIds() or {}) do
visitedCells[cellId] = true
end
end
processAndTeleport(true)
end)
end)
return {
eventHandlers = {
["builtin:map_extractor:teleport"] = function (pl)
processAndTeleport()
end,
}
}