Pluto API Documentation

FAQ

Q: What is Pluto?

A: Pluto is a superset of Lua with a focus on general-purpose programming.
More On Pluto

Q: Where are Pluto scripts stored?

A: You can place Pluto script files (.lua, .pluto) here:
%appdata%/spooky/scripts/
and start them from Settings -> Pluto

Q: How do I learn Pluto?

A: You can learn Lua first which will teach you 90% of Pluto
Learn Lua

Q: Where do I get started?

A: You can base your first scripts off of developer made example scripts
View Example Scripts

Q: Why did my old loop script suddenly stop?

A: Scripts now run on the game thread, one step per frame, and cooperate with the game. A script that loops without ever calling Yield() is aborted after roughly 100ms so it can never freeze the game. Add Yield() inside any long loop.

Functions

LOG(?number LogState = LogState.Info, string Content)

Log(?number LogState = LogState.Info, string Content)

allows you to print information to the console, LogState can be any of the following:


LogState.Brand or 1,
LogState.Info or 2,
LogState.Error or 3,
LogState.Event or 4,
LogState.Warning or 5
        

Content is a string that contains your message.

void LOG(LogState.Info, "Hello World!")

Notify(string Content, ?number Duration = 3)

allows you to notify information to the screen, will appear in the top right.

Content is a string that contains your message, Duration is how long (in seconds) it stays on screen.

void Notify("Hello World!")

void Yield(?number milliseconds = 1)

cooperatively pauses the script: it hands control back to the game and resumes after the provided number of milliseconds (or on the next frame if none is provided).

Because scripts run on the game thread, use Yield() inside any long or repeating loop, otherwise the script is aborted after ~100ms.

while true do -- do a little work Yield(100) -- resume in 100ms end

string GetGameVersion()

returns the current Phasmophobia version as a string

string GetSpookyVersion()

returns the current Spooky version as a string

number GetAccountTier()

returns the Spooky account tier of the current user as any of:


AccountTier.Premium or 0,
AccountTier.Standard or 1,
AccountTier.Free or 2
        

string GetAccountName()

returns the Spooky account nickname of the current user

bool IsGameLoaded()

returns a boolean corrosponding to if the game is properly loaded in, we recommend using this before interacting with world objects or trying to find them, otherwise crashes can occur.

bool IsInMainMenu()

returns if you are currently in the main lobby / main menu

bool AmIHost()

returns if you are the host of the current Phasmophobia room

string GetSceneName()

returns the name of the currently active Unity scene

string GetMapName()

returns the friendly name of the current map (e.g. "6 Tanglewood Drive")

number GetPing()

returns your current latency to the Photon server, in milliseconds

number GetPlayerSanity()

returns your current sanity (0 to 100)

void SetPlayerSanity(number sanity)

sets your current sanity (0 to 100)

number GetTimeScale()

void SetTimeScale(number scale)

get / set the Unity time scale (1 is normal speed)

number GetDeltaTime()

returns the current frame delta time in seconds

void Teleport(number x, number y, number z)

void Teleport(Vector3 position)

teleports the local player to the given world position

userdata GetObjectByName(string Name)

returns a CComponent userdata (see below) by finding an object that contains the provided name string

userdata GetObjectByTypeName(string TypeName)

returns a CComponent userdata (see below) by finding the first object of the provided component type, e.g. "Player"

table GetObjectsOfType(string TypeName)

returns a table containing every object of the provided component type, e.g. "Door"


for _, door in ipairs(GetObjectsOfType("Door")) do
    if door:IsValid() then
        LOG(LogState.Info, door:GetName())
    end
end
        

userdata GetLocalPlayer()

returns a CComponent userdata (see below) that contains the local players world object

table GetPlayerList()

returns a table of tables, one per player in the room, each containing:


player.Name,       -- string
player.ActorNumber, -- number
player.IsHost,      -- bool
player.IsMe,        -- bool
player.IsDead,      -- bool
player.Position     -- Vector3
        

string GetServerAddress()

returns the current Photon server IP Address, or an empty string

void SetCursorVisible(bool visible)

sets if the Phasmophobia cursor should be visible

void SetCursorLockState(number state)

sets if the Phasmophobia cursor should be restricted to the window, or even the centre of the screen, state can be any of:


LockStates.Non or 0, -- can be moved anywhere
LockStates.Locked or 1, -- locked to the centre of the screen
LockStates.Confined or 2 -- locked to the window
        

number GetCursorLockState()

returns the current cursor lock state (see above)

UserDatas and Tables

Vector3

a Vector3 table contains 3 floats (x, y, z) that typically represent a position

Vector

The Vector class contains functions to assist with Vector math

All Vector math functions can be used with any Vector type as they are dynamic

For example if your table contains just one "x" field, it will do the math just for it.

If your table contains "x", "y", "z", and "w", it will do the math for all of them.

If the second vector does not contain any/some of those elements then that element will be skipped

VectorType Vector.GetType(table Vector)


VectorType.Non or 0, -- not a vector
VectorType.V1 or 1, -- vector containing x
VectorType.V2 or 2, -- vector containing x and y
VectorType.V3 or 3, -- vector containing x, y, and z
VectorType.V4 or 4, -- vector containing x, y, z, and w
        

table Vector.New(?number x = 0, ?number y = 0, ?number z = 0, ?number w = 0)

table Vector.Add(table VectorA, table VectorB)

If the second vector is smaller than the first, the first's elements will be added, example:


local VecA = Vector.New(1, 0, 1)
local VecB = Vector.New(5, 0)

Notify(Vector.ToString(Vector.Add(VecA, VecB))) -- Result: X: 6, Y: 0, Z: 1
        

table Vector.Multiply(table VectorA, table VectorB)

Similar logic to Add

table Vector.Multiply(table VectorA, number Multiplier)

table Vector.Divide(table VectorA, table VectorB)

Similar logic to Add

table Vector.Divide(table VectorA, number Divisor)

Quaternion

a Quaternion table contains 4 floats (x, y, z, w) that typically represent a rotation

CComponent

a CComponent userdata represents an object or an objects component in the world, it has the following functions:

string GetName()

returns the name of the object, or nil if the object no longer exists

bool IsValid()

returns true while the underlying object still exists, always check this before using a handle you stored a while ago

userdata GetTransform()

GetTransform returns a CTransform userdata (see below)

userdata GetGameObject()

returns a CGameObject userdata (see below)

userdata GetComponent(string TypeName)

returns a CComponent userdata for the first component of the given type on this object, or nil

table GetComponents(string TypeName)

returns a table of every component of the given type on this object

void SetName(string NewName)

renames the object

void Destroy()

destroys the object

any CallMethod(string MethodName, ...)

invokes a method on this component and discards the return value. It accepts up to 3 arguments, each a number, bool, string, or another object userdata.

number CallMethodFloat(string MethodName, ...)

number CallMethodInt(string MethodName, ...)

bool CallMethodBool(string MethodName, ...)

string CallMethodString(string MethodName, ...)

the same as CallMethod, but return the method's result as the matching type. Use these for in-game getters (e.g. renderer:CallMethodBool("get_enabled")).

you should consult game data to find these methods, and ensure the arguments you pass and receive are valid.

CGameObject

a CGameObject userdata represents a game object in the world (returned by CComponent:GetGameObject()), it has the following functions:

string GetName()

bool IsValid()

userdata GetTransform()

userdata GetComponent(string TypeName)

table GetComponents(string TypeName)

bool GetActive()

void SetActive(bool active)

any CallMethod(string MethodName, ...)

number CallMethodFloat / number CallMethodInt / bool CallMethodBool / string CallMethodString

as with CComponent, the CallMethod family invokes an in-game method (up to 3 arguments) and the typed variants return the result.

CTransform

a CTransform userdata is a type of component which holds an objects position, scale, and rotation, it has the following functions:

string GetName()

userdata GetGameObject()

GetGameObject returns a CGameObject userdata (see above)

userdata GetComponent(string TypeName)

Vector3 GetPosition()

void SetPosition(number x, number y, number z)

void SetPosition(Vector3 position)

Vector3 GetLocalPosition()

void SetLocalPosition(number x, number y, number z)

void SetLocalPosition(Vector3 position)

Quaternion GetRotation()

void SetRotation(number x, number y, number z, number w)

void SetRotation(Quaternion rotation)

Vector3 GetScale()

void SetScale(number x, number y, number z)

void SetScale(Vector3 scale)

userdata GetParent()

returns the parent CTransform, or nil if there is none

userdata GetRoot()

returns the top-most CTransform in the hierarchy

number GetChildCount()

userdata GetChild(number index)

returns the child CTransform at the given index, or nil

any CallMethod(string MethodName, ...)

as with CComponent, you can invoke any in-game method on the transform (e.g. t:CallMethod("LookAt", player:GetTransform())), and the typed variants return the result.