Skip to content

TAS Movie API

Eddio0141 edited this page Nov 18, 2024 · 23 revisions

API for the extra functionality availiable in the TAS movie scripts

MOVIE_CONFIG

  • All movie config options are in the MOVIE_CONFIG table
  • All options MUST be defined in the first frame of the movie (so before the first movie.frame_advance)
  • For advanced options: make sure if the is_global_scope option is enabled, the options are defined in the global scope and not in the main script coroutine

Example

MOVIE_CONFIG = {
    fps = 60, -- same as setting frame
    start_time = "march 28th 2024", -- the game time is now set to this!
    seed = 12345, -- some RNG manipulating stuff
    window = {
        -- I want to force the game resolution for this TAS
        width = 900,
        height = 600,
    }
}

MOVIE_CONFIG.fps

  • Default: 100
  • The FPS of the movie
    • Explanation of this and frametime is explained in the frametime field

MOVIE_CONFIG.frametime

  • Default: 0.01
  • The frametime of the movie, this is applied to the first frame of the movie
  • You can set this OR fps, the only difference is this is the time (in seconds) between frames
    • So a frametime of 0.05 is same as 20 fps
    • You can calculate this by doing 1 / fps to get frametime, and 1 / frametime to get fps

MOVIE_CONFIG.start_time

  • Default: "jan 1st 0001"
  • Using a string to set this will use the invariant DateTime format to start the movie in that system time
  • Using a number will set the time by ticks, starting from the lowest possible date time (default value)
    • There are 10,000 ticks in 1 millisecond and 10,000,000 ticks in a second

MOVIE_CONFIG.seed

  • Default: 0
  • The seed to use for the random number generator on soft restart
  • Seed is only applied at the start of the game, and it's not something you can change during runs

MOVIE_CONFIG.window

  • This sets the game's window properties

Example

MOVIE_CONFIG = {
    window = {
        -- the width and height of the game window at start
        width = 1920,
        height = 1080,
        -- doesn't affect TAS, it usually almost never matters
        -- unless the game wants this info for something...
        refresh_rate = 144,
        -- extra "fallback resolutions" to generate
        -- some games want those extra monitor resolutions
        -- 100 means it will generate resolutions every 100th pixels
        -- not 100 extra resolutions
        fallback_res_closest = 100,
        -- extra supported monitor resolutions
        -- unless you want those to appear in the game resolution settings,
        -- isn't really needed
        resolutions = {
            {
                width = 900,
                height = 1000,
                refresh_rate = 60,
            },
            {
                width = 1000,
                height = 100,
                -- this calculates refresh rate by doing 600 / 9
                -- if you want a very specific refresh rate for some reason...
                refresh_rate = {
                    numerator = 600,
                    denominator = 9
                }
            }
        }
    }
}

MOVIE_CONFIG.window.width

  • Default: 1920
  • The initial game window's width

MOVIE_CONFIG.window.height

  • Default: 1080
  • The initial game window's height

MOVIE_CONFIG.window.refresh_rate

  • Default: 60
  • The monitor refresh rate
  • Usually doesn't matter, this doesn't limit the TAS fps or anything, but the game could use this info for something
  • You can also specify a numerator and denominator and use it instead of a number
refresh_rate = {
    numerator = 500,
    denominator = 9
}

MOVIE_CONFIG.window.fallback_res_closest

  • Default: 100
  • UniTAS generates a number of "fallback monitor resolutions" to stop some games from breaking, since a monitor usually has a number of resolutions you can switch to.
  • A value of 100 means UniTAS creates fallback resolutions to the nearest of 100 pixels for a number of different aspect ratios

MOVIE_CONFIG.window.resolutions

  • Default: {}
  • A list of monitor resolutions to add to the "fallback monitor resolutions"
  • Each entry has width, height, refresh_rate

movie.update_type

  • Default: "Update"
  • The type of update to use on frame advance, it is case insensitive
  • This can be changed at any point in the run with env.update_type
  • Types
    • Update - Updates before frame update either MonoBehaviour.Update or input system update
    • FixedUpdate - Updates before fixed update either MonoBehaviour.FixedUpdate or input update
    • Both - Both of the above

movie.is_global_scope

  • Default: false
  • You will almost never use this unless you are writing very specific lua scripts
  • Enabling this will unwrap the main script coroutine into the global scope, basically letting you use the lua script in its raw form
    • Make sure to return a coroutine function from the main script, which will be used as the main script coroutine

concurrent

Contains functions used to register / unregister a concurrent function

concurrent.register(function, post_update, arg0, arg1, arg2, ...) -> register_uid

Registers a function to run along with the main script
This will also run the function for the current frame if post_update is false

Args

  • function
    • The function to run
  • post_update
    • default: false
    • true would make the function run after frame advancing, false to make it run before frame advancing
  • arg0, arg1, ...
    • Default arguments to pass to the function
    • You don't have to put anything if your function needs nothing
    • If you don't match the number of arguments as same as the function signature, it will throw an exception usually

Return

  • An identifier for that registered concurrent function

concurrent.register_once(function, post_update, arg0, arg1, arg2, ...) -> register_uid

Registers a function to run along with the main script, but will only run once
Same arguments and returning value as register()

concurrent.unregister(register_uid)

Unregisters a concurrently running function

Args

  • register_uid
    • The identifier that was returned from concurrent.register or concurrent.register_once

key

Used for manipulating the keyboard

key.hold(key)

Holds a key down

Args

  • key
    • The key to hold down
    • A string of the key name which is a value from here or here or here
    • Guessing what the key is called usually works

key.release(key)

Releases a key

Args

  • key
    • The key to release
    • A string of the key name which is the value from here or here or here
    • Guessing what the key is called usually works

key.clear()

Clears all keys that are currently held down

mouse

Used for manipulating the mouse

mouse.left(hold)

Holds the left mouse button

Args

  • hold
    • default: true
    • true to hold left click, false to release

mouse.right(hold)

Holds the right mouse button

Args

  • hold
    • default: true
    • true to hold right click, false to release

mouse.middle(hold)

Holds the middle mouse button

Args

  • hold
    • default: true
    • true to hold middle click, false to release

mouse.move(x, y)

Moves the mouse to a position

Args

  • x
    • The x position to move to
  • y
    • The y position to move to

move_rel(x, y)

Moves the mouse to a position relative to the current position

Args

  • x
    • The x offset to move to
  • y
    • The y offset to move to

mouse.set_scroll(x, y)

Sets the scroll speed

Args

  • x
    • The x scroll speed
  • y
    • The y scroll speed

controller

Used for manipulating the controller

controller.x_axis(value)

⚠️ NOTE: This will be eventually replaced after better legacy input system support for unity

Sets the x axis of the controller

Args

  • value
    • a value ranging from -1 to 1 to be used for the x axis

controller.y_axis(value)

⚠️ NOTE: This will be eventually replaced after better legacy input system support for unity

Sets the y axis of the controller

Args

  • value
    • a value ranging from -1 to 1 to be used for the y axis

controller.axis(axis, value)

⚠️ NOTE: This will be eventually replaced after better legacy input system support for unity

Sets the value of an axis

Args

  • axis
    • The axis to control, ranging from 1 to 28
  • value
    • The value to set the axis to, ranging from -1 to 1

controller.hold(button)

⚠️ NOTE: This will be eventually replaced after better legacy input system support for unity

Holds a controller button down

Args

  • button
    • The button to control, ranging from 0 to 19

controller.release(button)

⚠️ NOTE: This will be eventually replaced after better legacy input system support for unity

Releases a controller button

Args

  • button
    • The button to control, ranging from 0 to 19

controller.add_player()

Adds a controller to the game
You can use hold, release, and other controller functions on the added controller

Example

player2 = controller.add_player()
player3 = controller.add_player()

player2.hold(0)
player2.axis(1, 0.07)

player3.x_axis(0.75)
player3.y_axis(-0.75)

env

Game environment, used for changing the game environment

env.fps

The current FPS of the game, you can read / write to this
NOTE: Setting this will apply the change on the next frame (so after the next movie.frame_advance call)

Example

env.fps = 60

-- later...
env.fps = 144

-- what is the fps? print it to find out!
print("fps now is: " .. env.fps)

env.frametime

The current frametime of the game, you can read / write to this
NOTE: Setting this will apply the change on the next frame (so after the next movie.frame_advance call)

This is the same as changing env.fps, but frametime is the number of seconds between frames

To get the frametime from a fps value, you can do this: 1 / fps, and fps from the frametime: 1 / frametime

env.update_type(type)

The type of update to use on frame advance
Same as MOVIE_CONFIG.update_type, but lets you change this at any point in time

Args

  • type
    • The update type to set the game to
    • Types
      • Update - Stops before MonoBehaviour.Update
      • FixedUpdate - Stops before MonoBehaviour.FixedUpdate
      • Both - Both of the above

movie

Used to control movie playback

movie.playback_speed(speed_multiplier)

Sets the current playback speed of the movie

Args

  • speed_multiplier
    • The speed multiplier to set the playback speed to
    • Setting this to 0 will run the game as fast as possible
    • Setting this to 1 will run the game at 1x speed
    • Setting this to 0.5 will run the game at 0.5x speed, etc

movie.frame_advance(count)

Frame advances the movie by count frames
Technically, it's an alias for coroutine.yield()

Args

  • count
    • Default: 1
    • The number of frames to frame advance
    • If you don't set count, it will frame advance once

Example

-- press some inputs before this
movie.frame_advance(100)
-- more stuff before the next single frame advance
movie.frame_advance()

movie.start_capture(args)

Starts capturing the movie
You don't need to call movie.stop_capture() at the end of the script, it will automatically stop the capture when the script ends

Args

  • args
    • A table of arguments to pass to the capture
    • If you give this function nothing, it will have the default values
    • Table args
      • fps
        • Default: 60
        • The FPS to capture the movie at
      • width
        • Default: 1920
        • The width of the rendered movie
      • height
        • Default: 1080
        • The height of the rendered movie
      • path
        • Default: "output.mp4"
        • The path to save the movie to
        • Accepts relative path from the game directory, or an absolute path

Example

-- starts capturing with default settings
movie.start_capture()

-- after a while...

movie.stop_capture()

-- start another recording with a crazy file size!
movie.start_capture({ fps = 120, width = 3840, height = 2160, path = "epic movie.mp4" })

movie.stop_capture()

Stops capturing the movie

unity

Provides read only access to unity side

unity.find_objects_by_type(type_name)

Finds unity objects by type

Args

  • type_name
    • The C# type name of the object to find. It would be ideal to include the namespace, but should be fine with just the type name

Example

-- finds all game objects
found_objs = unity.find_objects_by_type("UnityEngine.GameObject")