mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-25 07:14:41 +01:00
- skater.read: reskate.skater.get() (position, heading, speed, vertical speed, airborne, air time) and position, heading, speed and on_ground on their own; nil without a skater. From the trainer's telemetry. The heading is radians, -pi to pi: 0 faces +Z, pi/2 faces +X, and a higher heading is turned to the skater's left (checked in game). - skater.teleport: reskate.skater.teleport(at, heading?) through teleport_local_skater_heading; false and why when the host has turned teleporting off (as the console's tp), there is no skater, or it is asked more than twice a second. Positions must be finite and within 100 km. - world.raycast: reskate.world.raycast(from, to) is where the line first meets the world's collision (local_surface_hit), or nil; 64 a tick, 1000 m at most. - The host passes the game to plugins through Environment, so the tests fake a skater and flat ground. reskate-test has a skater module (skipped without a skater; the harness counts skips) and ptest tp; reskate-hostile has teleport-spam and raycast-flood. Checked in game: teleporting, the two-a-second cap and the raycast cap. ptest skater's heading check failed there (0 to 2 pi from the trainer) and is fixed, not yet rerun in game.
57 lines
2.9 KiB
Lua
57 lines
2.9 KiB
Lua
local h = require("harness")
|
|
local t = h.module("skater")
|
|
|
|
local function skater()
|
|
return reskate.skater.get()
|
|
end
|
|
|
|
t.check("get is nil without a skater, else its state", function()
|
|
local s = skater()
|
|
if s == nil then return h.skip("no skater (in the menu or a load)") end
|
|
assert(typeof(s.position) == "vector", "position is a vector")
|
|
assert(type(s.heading) == "number" and math.abs(s.heading) <= math.pi + 0.01, "heading in radians: " .. tostring(s.heading))
|
|
assert(type(s.speed) == "number" and s.speed >= 0 and type(s.vertical_speed) == "number")
|
|
assert(type(s.airborne) == "boolean" and type(s.air_time) == "number")
|
|
end)
|
|
t.check("the single readers agree with get", function()
|
|
local s = skater()
|
|
if s == nil then return h.skip("no skater") end
|
|
assert(reskate.skater.position() == s.position and reskate.skater.heading() == s.heading)
|
|
assert(reskate.skater.on_ground() == not s.airborne)
|
|
end)
|
|
t.check("a ray down from the skater meets the ground under it", function()
|
|
local s = skater()
|
|
if s == nil then return h.skip("no skater") end
|
|
if s.airborne then return h.skip("the skater is in the air") end
|
|
local hit = reskate.world.raycast(s.position + vector.create(0, 2, 0), s.position - vector.create(0, 5, 0))
|
|
assert(hit, "nothing under the skater")
|
|
assert(math.abs(hit.y - s.position.y) < 1.5, string.format("the ground is %.2f m from the skater", hit.y - s.position.y))
|
|
end)
|
|
t.check("a ray through the air meets nothing", function()
|
|
local s = skater()
|
|
if s == nil then return h.skip("no skater") end
|
|
local up = s.position + vector.create(0, 400, 0)
|
|
assert(reskate.world.raycast(up, up + vector.create(0, 50, 0)) == nil, "something 400 m up")
|
|
end)
|
|
t.check("bad positions and long rays are refused", function()
|
|
h.refused(reskate.skater.teleport, vector.create(0 / 0, 0, 0))
|
|
h.refused(reskate.skater.teleport, vector.create(1e7, 0, 0))
|
|
h.refused(reskate.skater.teleport, {1, 2, 3})
|
|
h.refused(reskate.skater.teleport, vector.create(0, 0, 0), 0 / 0)
|
|
h.refused(reskate.world.raycast, vector.create(0, 0, 0), vector.create(2000, 0, 0))
|
|
h.refused(reskate.world.raycast, vector.create(0, 0, 0), "up")
|
|
end)
|
|
|
|
-- By hand, since it moves you: ptest tp teleports the skater 3 m ahead, turned a quarter turn to
|
|
-- the right. A higher heading turns the skater left, so a right turn takes a quarter off.
|
|
reskate.console.command("ptest tp", "Teleports the skater 3 m ahead, a quarter turn to the right", function()
|
|
local s = skater()
|
|
if s == nil then
|
|
reskate.console.print("ptest tp: no skater")
|
|
return
|
|
end
|
|
local ahead = vector.create(math.sin(s.heading), 0, math.cos(s.heading)) * 3
|
|
local ok, why = reskate.skater.teleport(s.position + ahead + vector.create(0, 0.5, 0), s.heading - math.pi / 2)
|
|
reskate.console.print("ptest tp: " .. (ok and "sent" or ("refused: " .. tostring(why))))
|
|
end)
|