From 854716a133824c4a279779878aa66a479cd98f07 Mon Sep 17 00:00:00 2001 From: elsid Date: Fri, 2 Jun 2023 19:33:17 +0200 Subject: [PATCH] Add scripts to benchmark cell border crossing --- scripts/data/cross_cell_border/README.md | 16 ++++ scripts/data/cross_cell_border/common.lua | 25 +++++ .../cross_cell_border.omwscripts | 2 + scripts/data/cross_cell_border/global.lua | 20 ++++ scripts/data/cross_cell_border/player.lua | 95 +++++++++++++++++++ scripts/data/cross_cell_border/setup.mwscript | 2 + 6 files changed, 160 insertions(+) create mode 100644 scripts/data/cross_cell_border/README.md create mode 100644 scripts/data/cross_cell_border/common.lua create mode 100644 scripts/data/cross_cell_border/cross_cell_border.omwscripts create mode 100644 scripts/data/cross_cell_border/global.lua create mode 100644 scripts/data/cross_cell_border/player.lua create mode 100644 scripts/data/cross_cell_border/setup.mwscript diff --git a/scripts/data/cross_cell_border/README.md b/scripts/data/cross_cell_border/README.md new file mode 100644 index 0000000000..dc236f1445 --- /dev/null +++ b/scripts/data/cross_cell_border/README.md @@ -0,0 +1,16 @@ +#Cross cell border benchmark + +A set of scripts to provide an automatic way to travel at high speed over multiple cells in the exterior world. +Use `"3,6"` as the start cell of an approximate center of the Morrowind default worldspace. +The player moves by a rectangular spiral with limit by simulation time. + +Simple usage: +```bash +"${OPENMW_BINARY_DIR:?}/openmw" \ + --skip-menu \ + --no-grab \ + --start "3,6" \ + --script-run "${OPENMW_SOURCE_DIR:?}/scripts/data/cross_cell_border/setup.mwscript" \ + --data "${OPENMW_SOURCE_DIR:?}/scripts/data/cross_cell_border" \ + --content cross_cell_border.omwscripts +``` diff --git a/scripts/data/cross_cell_border/common.lua b/scripts/data/cross_cell_border/common.lua new file mode 100644 index 0000000000..42329c313b --- /dev/null +++ b/scripts/data/cross_cell_border/common.lua @@ -0,0 +1,25 @@ +local core = require('openmw.core') + +local module = {} + +function module.makeCoroutineWithErrorReporting(fn) + local fatalErr = nil + local function coroutineImpl() + local ok, err = pcall(fn) + if ok then + return + end + fatalErr = err + end + local co = coroutine.create(coroutineImpl) + return function() + if coroutine.status(co) ~= 'dead' and not core.isWorldPaused() then + coroutine.resume(co) + if fatalErr then + error(fatalErr, 2) + end + end + end +end + +return module diff --git a/scripts/data/cross_cell_border/cross_cell_border.omwscripts b/scripts/data/cross_cell_border/cross_cell_border.omwscripts new file mode 100644 index 0000000000..7455690608 --- /dev/null +++ b/scripts/data/cross_cell_border/cross_cell_border.omwscripts @@ -0,0 +1,2 @@ +GLOBAL: global.lua +PLAYER: player.lua diff --git a/scripts/data/cross_cell_border/global.lua b/scripts/data/cross_cell_border/global.lua new file mode 100644 index 0000000000..f31b8f41a4 --- /dev/null +++ b/scripts/data/cross_cell_border/global.lua @@ -0,0 +1,20 @@ +local util = require('openmw.util') +local world = require('openmw.world') +local common = require('common') + +local function startMoveAcrossExteriorWorld() + player:teleport('', util.vector3(player.position.x, player.position.y, 10000), util.vector3(0, 0, 0)) + coroutine.yield() + player:sendEvent('startMoveAcrossExteriorWorld') +end + +local function setPlayer(value) + player = value +end + +return { + engineHandlers = { + onUpdate = common.makeCoroutineWithErrorReporting(startMoveAcrossExteriorWorld), + onPlayerAdded = setPlayer, + }, +} diff --git a/scripts/data/cross_cell_border/player.lua b/scripts/data/cross_cell_border/player.lua new file mode 100644 index 0000000000..93982a16db --- /dev/null +++ b/scripts/data/cross_cell_border/player.lua @@ -0,0 +1,95 @@ +local core = require('openmw.core') +local input = require('openmw.input') +local self = require('openmw.self') +local types = require('openmw.types') +local util = require('openmw.util') +local common = require('common') + +local started = false + +local function rotate90DegreesByZ(vector) + return util.vector2(-vector.y, vector.x) +end + +local function getRotationAngle(value) + -- for compatibility with 0.48 + return value.z or value:getYaw() +end + +local function streerTo(target) + self.controls.jump = false + self.controls.run = true + self.controls.sideMovement = 0 + local direction = target - self.position + local targetAngle = math.atan2(direction.x, direction.y) + local diffAngle = util.normalizeAngle(targetAngle - getRotationAngle(self.rotation)) + local maxYawChange = 0.05 + self.controls.yawChange = util.clamp(diffAngle, -maxYawChange, maxYawChange) + if math.abs(diffAngle) <= maxYawChange and direction:length() > 0 then + self.controls.movement = 1 + else + self.controls.movement = 0 + end +end + +local function toCellCenterPosition(x, y, z, cellSize) + return util.vector3((x + 0.5) * cellSize, (y + 0.5) * cellSize, z) +end + +local function toCellLocation(position, cellSize) + return util.vector2(math.floor(position.x / cellSize), math.floor(position.y / cellSize)) +end + +local function moveAcrossExteriorWorld() + local cellSize = 8192 + local currentCell = toCellLocation(self.position, cellSize) + local cellDirection = util.vector2(0, 1) + local visitedCells = {} + visitedCells[tostring(currentCell)] = true + types.Actor.stats.attributes.speed(self).base = 4096 + local endTime = core.getSimulationTime() + 60 + while core.getSimulationTime() < endTime do + local nextCell = currentCell + cellDirection + local target = toCellCenterPosition(nextCell.x, nextCell.y, self.position.z, cellSize) + while toCellLocation(self.position, cellSize) ~= nextCell and (target - self.position):length() > 1024 do + streerTo(target) + coroutine.yield() + end + visitedCells[tostring(nextCell)] = true + currentCell = nextCell + local newDirection = rotate90DegreesByZ(cellDirection) + if visitedCells[tostring(currentCell + newDirection)] ~= true then + cellDirection = newDirection + end + end + core.quit() +end + +local function startMoveAcrossExteriorWorld() + input.setControlSwitch(input.CONTROL_SWITCH.Fighting, false) + input.setControlSwitch(input.CONTROL_SWITCH.Jumping, false) + input.setControlSwitch(input.CONTROL_SWITCH.Looking, false) + input.setControlSwitch(input.CONTROL_SWITCH.Magic, false) + input.setControlSwitch(input.CONTROL_SWITCH.VanityMode, false) + input.setControlSwitch(input.CONTROL_SWITCH.ViewMode, false) + + started = true +end + +local function setUpMoveAcrossExteriorWorld() + local impl = common.makeCoroutineWithErrorReporting(moveAcrossExteriorWorld) + return function() + if started then + impl() + end + end +end + +return { + engineHandlers = { + onFrame = setUpMoveAcrossExteriorWorld(), + }, + eventHandlers = { + startMoveAcrossExteriorWorld = startMoveAcrossExteriorWorld, + }, +} diff --git a/scripts/data/cross_cell_border/setup.mwscript b/scripts/data/cross_cell_border/setup.mwscript new file mode 100644 index 0000000000..cd9a98f0ba --- /dev/null +++ b/scripts/data/cross_cell_border/setup.mwscript @@ -0,0 +1,2 @@ +player->SetFlying 1 +tcl