openrac.game
New 1.1openrac.game: stringopenrac.game, .version, .platform, .api: "rac1", "pal" or "ntsc", "macos-arm64" ..., the game's interface version ("1.1")
You are reading the docs of SDK 1.1.2, an older release. See the latest (1.11.0).
Reference · SDK 1.1.2
A script mod sees one global, openrac, and the safe parts of Luau's library. For autocomplete, point your editor's Luau language server at the SDK's types/rac1.d.luau.
openrac.game: stringopenrac.game, .version, .platform, .api: "rac1", "pal" or "ntsc", "macos-arm64" ..., the game's interface version ("1.1")
openrac.version: "pal" | "ntsc"openrac.game, .version, .platform, .api: "rac1", "pal" or "ntsc", "macos-arm64" ..., the game's interface version ("1.1")
openrac.platform: stringopenrac.game, .version, .platform, .api: "rac1", "pal" or "ntsc", "macos-arm64" ..., the game's interface version ("1.1")
openrac.api: stringopenrac.game, .version, .platform, .api: "rac1", "pal" or "ntsc", "macos-arm64" ..., the game's interface version ("1.1")
openrac.log: (...any) -> ()openrac.log(...), openrac.warn(...): a line in the game's log, after your mod's id (print does the same as log)
openrac.hook("rac1.player.set_planar_velocity", function(original, angle)
original(angle) -- the game's own, or the mod before yours
openrac.log(`moving along {angle}`)
end)
openrac.after("rac1.player.advance_animation", function()
-- runs after the game has moved the animation on
end)-- After each game tick (50 a second on PAL, 60 on NTSC-U).
openrac.on_frame(function()
ticks += 1
if ticks % (every * 50) == 0 then
openrac.log(`still here after {ticks} ticks`)
end
end)openrac.warn: (...any) -> ()openrac.log(...), openrac.warn(...): a line in the game's log, after your mod's id (print does the same as log)
openrac.setting: (key: string) -> anyopenrac.setting(key): one of your settings
--!strict
local swap = openrac.setting("pair") :: string
openrac.on_pad(function(port: number, report: buffer)
local buttons = buffer.readu16(report, 0) -- a bit is clear while its button is held
-- ... change buttons ...
buffer.writeu16(report, 0, buttons)
end)
openrac.on_frame(function()
-- after each game tick: 50 a second on PAL, 60 on NTSC-U
end)local every = openrac.setting("every") :: number -- the manifest's setting, as the launcher set it
local ticks = 0openrac.hook: (name: HookPoint, fn: (original: (...number) -> ...number, ...number) -> ...number) -> ()openrac.hook(id, fn): wrap or replace a hook point: fn(original, ...) gets its arguments; original(...) goes on down the chain and returns its result; original() with no arguments passes the call's own; return nothing to keep the original's result
openrac.hook("rac1.player.set_planar_velocity", function(original, angle)
original(angle) -- the game's own, or the mod before yours
openrac.log(`moving along {angle}`)
end)
openrac.after("rac1.player.advance_animation", function()
-- runs after the game has moved the animation on
end)-- A hook point by name, wrapped: the game's own call goes on through `original`.
-- openrac.hook("Hero_SetPlanarVelocity", function(original, angle: number)
-- original(angle)
-- end)openrac.before: (name: HookPoint, fn: (...number) -> ()) -> ()openrac.before(id, fn), openrac.after(id, fn): fn(...) before or after the rest of the chain, which runs whatever fn does
openrac.after: (name: HookPoint, fn: (...number) -> ()) -> ()openrac.before(id, fn), openrac.after(id, fn): fn(...) before or after the rest of the chain, which runs whatever fn does
openrac.hook("rac1.player.set_planar_velocity", function(original, angle)
original(angle) -- the game's own, or the mod before yours
openrac.log(`moving along {angle}`)
end)
openrac.after("rac1.player.advance_animation", function()
-- runs after the game has moved the animation on
end)openrac.on_frame: (fn: () -> ()) -> ()openrac.on_frame(fn): fn() after each game tick
--!strict
local swap = openrac.setting("pair") :: string
openrac.on_pad(function(port: number, report: buffer)
local buttons = buffer.readu16(report, 0) -- a bit is clear while its button is held
-- ... change buttons ...
buffer.writeu16(report, 0, buttons)
end)
openrac.on_frame(function()
-- after each game tick: 50 a second on PAL, 60 on NTSC-U
end)-- After each game tick (50 a second on PAL, 60 on NTSC-U).
openrac.on_frame(function()
ticks += 1
if ticks % (every * 50) == 0 then
openrac.log(`still here after {ticks} ticks`)
end
end)openrac.on_pad: (fn: (port: number, report: buffer) -> ()) -> ()openrac.on_pad(fn): fn(port, report) for each pad report before the game reads it; report is a buffer you may change
--!strict
local swap = openrac.setting("pair") :: string
openrac.on_pad(function(port: number, report: buffer)
local buttons = buffer.readu16(report, 0) -- a bit is clear while its button is held
-- ... change buttons ...
buffer.writeu16(report, 0, buttons)
end)
openrac.on_frame(function()
-- after each game tick: 50 a second on PAL, 60 on NTSC-U
end)-- Each pad report, before the game reads it: `report` is a buffer the script may change (rac1-mods'
-- button-swap shows its layout). Uncomment to see the buttons.
-- openrac.on_pad(function(port: number, report: buffer)
-- openrac.log(`port {port}: buttons {buffer.readu16(report, 0)}`) -- a bit clear for a button held
-- end)openrac.read: (kind: MemoryType, address: number) -> numberopenrac.read(type, address), openrac.write(type, address, value): game memory; type is u8 i8 u16 i16 u32 i32 f32; addresses in game RAM only (below 32 MB)
openrac.write: (kind: MemoryType, address: number, value: number) -> ()openrac.read(type, address), openrac.write(type, address, value): game memory; type is u8 i8 u16 i16 u32 i32 f32; addresses in game RAM only (below 32 MB)
openrac.fields: Fieldsopenrac.fields: game state by name, read and written as plain values: openrac.fields.bolts, openrac.fields.hero.position.x (experimental: see the reference)
openrac.pvars: (moby: number) -> { [string]: number }?openrac.pvars(moby): with the behaviour catalogue: the per-class variables of the moby at that address, by name (experimental)
require: (name: string) -> anyrequire(name): another .luau file of your mod's own folder: require("util"), require("lib/util")
type MemoryType = "u8" | "i8" | "u16" | "i16" | "u32" | "i32" | "f32"type Fields = {
hero: {
position: {
x: number, -- Where the hero is (gHeroPos).
y: number,
z: number,
},
facing: number, -- The way he faces (rot.z), in radians.
move_yaw: number, -- Where the stick moves him: the stick's angle plus the camera's yaw.
state: number, -- read-only; His state: 0 standing, 2 running, 7 jumping, ...
},
bolts: number, -- The player's bolts.
}rac1.pad.process_report (Pad_ProcessReport) void(u32,u32,i32): One pad report into the pad's state (PadState, at pad), each poll, before the tick reads it.
type Pad_ProcessReportFn = (pad: number, report: number, size: number) -> ()rac1.player.update_motion_input (Hero_UpdateMotionInput) void(): The stick read into the hero, early in his update each tick.
type Hero_UpdateMotionInputFn = () -> ()rac1.player.turn_to_heading (Hero_TurnToHeading) void(i32,f32,f32,f32): Eases the hero's facing toward his move yaw.
type Hero_TurnToHeadingFn = (mode: number, accel: number, damping: number, limit: number) -> ()rac1.player.set_planar_velocity (Hero_SetPlanarVelocity) void(f32): The hero's velocity at his ground speed along an angle; an angle above pi means his facing.
type Hero_SetPlanarVelocityFn = (angle: number) -> ()rac1.camera.follow.apply_overrides (FollowCamera_ApplyOverrides) void(u32): The follow camera's per-tick requests from the hero's state; the camera moby's update calls it before it places the eye.
type FollowCamera_ApplyOverridesFn = (camera: number) -> ()rac1.player.advance_animation (Hero_AdvanceAnimation) void(): Ratchet's animation moved on by his animation speed, once a tick after his state's update.
type Hero_AdvanceAnimationFn = () -> ()rac1.item.give (Item_Give) void(i32,i32): Gives the player item id (GiveItem): sets its owned and obtained bytes, shows its banner, gives its starting ammo, marks it bought in the vendor's stock and adds it to the quick select; equip non-zero also puts it in hand. Every item the game gives goes through it but the Persuader's.
type Item_GiveFn = (id: number, equip: number) -> ()rac1.planet.unlock (Planet_Unlock) void(i32): Unlocks a planet's coordinates (UnlockPlanet): its flag (one byte per level), the galaxy list, and its banner unless it is the planet the player is on.
type Planet_UnlockFn = (planet: number) -> ()rac1.vendor.init_level_stock (Vendor_InitLevelStock) void(): The vendor's stock at each level start (VendorStockLevelInit): gives the Bomb Glove while the player has none, keeps the stock's known items and adds the level's new weapon.
type Vendor_InitLevelStockFn = () -> ()rac1.vendor.build_item_list (Vendor_BuildItemList) void(i32): The vendor menu's list (VendorBuildItemList), from the stock and the items owned: each time the menu opens and after each purchase. skip_unflagged leaves out what is for sale (the menu opened from the pause screen).
type Vendor_BuildItemListFn = (skip_unflagged: number) -> ()rac1.gold_bolt.count_collected (GoldBolts_CountCollected) i32(): The gold bolts collected, at most 40 (count_nonzero_entries_up_to_40): what the pause screen shows; the unspent ones are this less 4 per gold weapon.
type GoldBolts_CountCollectedFn = () -> numberrac1.moby.<class>.update (experimental): (moby: number) -> (), or () -> () where it gets no moby.
type MobyUpdateFn = (moby: number) -> ()Generated from sdk/types/rac1.d.luau at sdk-v1.1.2. Edit this page or report a problem.