Tabletop Simulator Guide

TTS LUA Code Snippets for Tabletop Simulator

TTS LUA Code Snippets

Overview

Some code snippets that demonstrate various functions/calls for Tabletop Simulator. And then some.

Introduction

A lot of actual code that should be easy to copy, paste, and modify to fit your own scripting needs. I assume anyone reading this understands the basics of programming along with the most basic of Tabletop Simulator functions, mainly getObjectFromGUID(guid). I do not guarantee the code is free of error, or that it is the best code. In fact, I only learned LUA because of TTS.

Tables

Tables make up a large part of TTS scripting. There are several ways of handling them that I’ll list in this section because it’s important to understand how to do this properly.

Here is a table:

mytable = {}

You can imagine it like this:

key/index
value

There are no keys/indexes and no values. However by doing something like this

mytable.thisisakey = ‘value’

or

mytable[‘thisisakey’] = ‘value’

The table now looks like this

key/index
value
thisisakey
‘value’

Tables can store whatever value along with whatever key. Keys are unique but values are not. Try to figure out what the table looks like after the following code.

mytable.thisisakey2 = ‘value’ mytable.thisisakey = 1 mytable.thisisalsoakey = 1
key/index
value
thisisakey
1
thisisakey2
‘value’
thisisalsoakey
1

However, you can use indexes instead of keys. The following 2 snippets make the same table.

mytable = {‘data’, ‘moredata’}
mytable = {} mytable[1] = ‘data’ mytable[2] = ‘moredata’
key/index
value
1
‘data’
2
‘moredata’

There are several ways to get the information out of a table. If you have a table with key-value pairs, you can do it like this. The k is the key while the v is the value for that key in the table.

for k,v in pairs(mytable) do print(k,v) end

If you have a table with indexes instead of keys, you can go through it this way also. #mytable is the length of the table. This only works for tables with indexes.

for i=1,#mytable do print(mytable[i]) end

Also as a final note, you can have tables in tables

mytable = {} mytable.table = {} mytable.something = ‘data’ mytable.table.table = {} mytable.table.table.table = {‘hello’}

This is how it looks

key/index
value
table
key/index
value
table
key/index
value
table
key/index
value
1
‘hello’
something
‘data’

Sometimes you’ll see someone doing something like this

mytable = {[‘something’] = ‘value’, [‘somethingelse’] = ‘value2’}

That is the same as

mytable = {something = ‘value’, somethingelse = ‘value2’}

The only difference is there’s extra text to type and if you don’t use the brackets, you cannot use numbers in your key

mytable = {[‘123key’] = 1} — ok mytable = {123key = 1} — not ok

Keywords

There are two important keywords, Global and self. Global refers to anything in the main script while self refers to the object that the script is located on.

— on a deck print(self.name) Global.call(‘myFunction’) — in global script print(deck.name) myFunction()

Callbacks/Functions in Parameters

Sometimes you’ll see a callback parameter on some functions. Callbacks are functions that will be called when the current function is completed. There are up to two other parameters that influence the callback function.

params.callback = ‘theFunctionName’ params.callback_owner = Global — this is where function theFunctionName() is located params.params = {1,2,3}

You can imagine this as

— some function that utilizes the callback parameter i.e. spawnObject or takeObject theFunctionName({1,2,3}) — this will only run once spawnObject or takeObject has completed

Sometimes when you have a callback function or a function in the parameters table and you’re wondering what gets passed to it automatically, just try sending print.

button.click_function = ‘print’

Consider that as

print(parameter,parameter,parameter…)

And any print statement with commas in it just concatenates the strings (puts them together) so you would see in the chat log something like

Custom_Object (LuaGameScriptObject)White — or something like that

Taking that apart, you will have two things:
1. The object
2. The color of who pressed the button
This means that there are two parameters passed to the function of a button, the object it’s on and the color of the player who pressed it.

—-API—-

API[berserk-games.com]

Collisions

function onCollisionEnter(collision_info) print(‘The object that hit me’s name is’ .. collision_info.collision_object.getName()) for i=1,#collision_info.contact_points do print(‘Collision point:’) for k,v in pairs(collision_info.contact_points[i]) do print(k .. ‘=’ .. v) end end print(‘Relative velocity values’) print(‘x=’ .. collision_info.relative_velocity.x) print(‘y=’ .. collision_info.relative_velocity.y) print(‘z=’ .. collision_info.relative_velocity.z) end

function onCollisionExit(collision_info) print(‘The object that left me’s name is’ .. collision_info.collision_object.getName()) for i=1,#collision_info.contact_points do print(‘Collision point:’) for k,v in pairs(collision_info.contact_points[i]) do print(k .. ‘=’ .. v) end end print(‘Relative velocity values’) print(‘x=’ .. collision_info.relative_velocity.x) print(‘y=’ .. collision_info.relative_velocity.y) print(‘z=’ .. collision_info.relative_velocity.z) end

function onCollisionStay(collision_info) print(‘The object is hitting me’s name is’ .. collision_info.collision_object.getName()) for i=1,#collision_info.contact_points do print(‘Collision point:’) for k,v in pairs(collision_info.contact_points[i]) do print(k .. ‘=’ .. v) end end print(‘Relative velocity values’) print(‘x=’ .. collision_info.relative_velocity.x) print(‘y=’ .. collision_info.relative_velocity.y) print(‘z=’ .. collision_info.relative_velocity.z) end

Picked Up/Dropped

function onDropped(player_color) print(player_color .. ‘ dropped ‘ .. self.getName()) end

function onPickedUp(player_color) print(player_color .. ‘ dropped ‘ .. self.getName()) end

function onObjectPickedUp(player_color, object) print(player_color .. ‘ dropped ‘ .. object.getName()) end

function onObjectDropped(player_color, object) print(player_color .. ‘ dropped ‘ .. object.getName()) end

Save/Load

function onSave() return JSON.encode({savedSomething=true}) end function onLoad(save_state) print(‘Everythings loaded!’) if JSON.decode(save_state).savedSomething then print(‘Something was saved from before’) end end

Comments: onSave() must return a string. JSON.encode() turns tables into strings. JSON.decode() turns those strings back into tables.

Destroy

function onDestroy() print(‘I’m dying!! (‘ .. self.getName() .. ‘)’) end

function onObjectDestroyed(dying_object) print(dying_object.getName() .. ‘is dying!!’) end

destroyObject(obj)

Scripting Zones

function onObjectEnterScriptingZone(zone, enter_object) print(enter_object.getName() .. ‘ has entered zone ‘ .. zone.getGUID()) end

function onObjectLeaveScriptingZone(zone, exit_object) print(leave_object.getName() .. ‘ has left zone ‘ .. zone.getGUID()) end

Player Color Change

onPlayerChangedColor(player_color) print(‘Someone moved to ‘ .. player_color) end

Player Turns

onPlayerTurnEnd(player_color_end, player_color_next) print(player_color_end .. ‘ just ended his turn. Now it is ‘ .. player_color_next .. ”s turn.’) end

onPlayerTurnStart(player_color_start, player_color_previous) print(player_color_previous .. ‘ just ended his turn. Now it is ‘ .. player_color_start .. ”s turn.’) end

Notebook Tabs

local params = {} params.title = ‘myNewNotebookTab’ params.body = ‘myNewNotebookTabContentsnHere’s a new line’ params.color = ‘White’ addNotebookTab(params) params.title = ‘myNewNotebookTab2’ addNotebookTab(params)

local params = {} params.index = 1 params.title = ‘myNewTitle’ params.body = ‘myNewBodynAnd Other’ params.color = ‘Red’ editNotebookTab(params)

local tabs = getNotebookTabs() for i=1,#tabs do print(tabs[i].index) print(tabs[i].title) print(tabs[i].body) print(tabs[i].color) end

removeNotebookTab(1)

Copy, Paste, and Spawn

local objects = {} objects[1] = obj1 objects[2] = obj2 copy(objects) paste({position={0, 0, 0}, snap_to_grid=false})

local params = {} params.type = ‘myObjectType’ params.position = {0, 0, 0} params.rotation = {0, 0, 0} params.scale = {0, 0, 0} params.callback = ‘myCallbackFunction’ params.callback_owner = Global params.snap_to_grid = false params.params = {‘myCallbackParams1’, ‘myCallbackParams2’} spawnObject(params)

Notes

local notesText = getNotes() print(notesText)

setNotes(‘These are the notes’)

Printing

print(‘Only host can read this’)

printToAll(‘Everyone can read this’, {1, 1, 1})

printToColor(‘Only white can read this’, ‘White’, {1, 1, 1})

Misc.

flipTable()

getAllObjects()

getObjectFromGUID(‘objguid’)

local seated = getSeatedPlayers() for i=1,#seated do print(seated[i]) end

function update() print(‘frame gone by’) end

clearPixelPaint() clearVectorPaint()

startLuaCoroutine(Global, ‘myFunction’)

local color_table = stringColorToRGB(‘White’) print(‘White’s R value is ‘ .. color_table.r) print(‘White’s G value is ‘ .. color_table.g) print(‘White’s B value is ‘ .. color_table.b)

—-Objects—-

Objects[berserk-games.com]

Clone

myclonedobject = obj.clone({position={0,0,0},snap_to_grid=false}) — is the same as copy({obj}) myclonedobject = paste({position={0,0,0},snap_to_grid=false})[1]

Buttons

Method 1:

local button_parameters = {} button_parameters.click_function = ‘myFunction’ button_parameters.function_owner = Global button_parameters.label = ‘myTextHere’ button_parameters.position = {0, 0, 0} button_parameters.rotation = {0, 0, 0} button_parameters.width = 500 button_parameters.height = 500 button_parameters.font_size = 20 object.createButton(button_parameters) button_parameters.click_function = ‘myOtherFunction’ object2.createButton(button_parameters)

Method 2:

local button_parameters = {click_function = ‘myFunction’, function_owner = Global, label = ‘myTextHere’, position = {0, 0, 0}, rotation = {0, 0, 0}, width = 500, height = 500, font_size = 20} object.createButton(button_parameters) button_parameters.click_function = ‘myOtherFunction’ object2.createButton(button_parameters)

Method 3:

object.createButton({click_function = ‘myFunction’, function_owner = Global, label = ‘myTextHere’, position = {0, 0, 0}, rotation = {0, 0, 0}, width = 500, height = 500, font_size = 20}) object2.createButton({click_function = ‘myOtherFunction’, function_owner = Global, label = ‘myTextHere’, position = {0, 0, 0}, rotation = {0, 0, 0}, width = 500, height = 500, font_size = 20})

All of these snippets do the same thing, but in different ways. Choose what is best for your script.

function myFunction(object, player) print(player .. ‘ pressed the button on ‘ .. object.getName()) end

Taking out of Containers

myBag.takeObject({position={0,1,0}, rotation={0,0,180}, callback=’myFunction’, callback_owner = Global, params = {self,1}, flip = false, top = false}) function myFunction(paramstable) for k,v in pairs(paramstable) do print(k,v) end end

—-Notable Functions/Classes—-

Somewhat more indepth.

spawnObject( Table parameters )

At first glance, you might think spawnObject is not that impressive, however with it, you can make two impressive things, text tools, scripting zones, and even tables… like physical tables. Wait that’s three things.

I’ll just go over the general idea of working with spawnObject. First, make an object that you want to be able to spawn then print its name. Now you know the type and you can spawn it.

guid = 297853 — pretend this is the guid of a scripting zone print(getObjectFromGUID(guid).name) — this will print ‘ScriptingTrigger’ spawnObject({type=’ScriptingTrigger’}) — this will spawn a scripting zone

This works for tables also and text tools also (I believe the text tools name is 3DText), however you can’t get the guid of a table, so instead you can use onCollisionEnter to get the table object.

function onCollisionEnter(info) print(info.collision_object.name) end

The best part about spawning in tables is you can scale them. I think.

–my huge table spawnObject({type=’table_custom’,scale={10,1,10}})

One other thing you can spawn is hidden zones. However, maybe you’re wondering how I got the name of a hidden zone. An alternative way of finding the name field for an object is to go directly into the .JSON save files and look at the name fields. If you make a save file with only a hidden zone in it, you will notice the line

“Name”: “FogOfWarTrigger”,

What’s that? That’s the hidden zone.

spawnObject({type=’FogOfWarTrigger’})

And now you have a hidden zone you can mess around with.

onDestroy()

While it is called onDestroy(), destroy is not as simple as you think it is. It will be called when you delete an object, but it will also be called when the object ‘disappears’ i.e. enters a deck or a bag. I’m not sure how to get the deck or bag though.

function onDestroy() print(‘I’ve disappeared into a container’) end

Timer

Timer is a way to delay the calling of a function for a while.

Timer.create({identifier=’uniqueGUID’, function_name=’myFunction’, function_owner=Global, delay=2}) function myFunction() print(‘2 seconds have passed since the Timer was created’) end

—-Random Snippets—-

Some random bits of code I use in my mods

Getting Player Count

#getSeatedPlayers()

String Manipulation

function split(input, split) local returnarr = {} local i = 1 for str in string.gmatch(input, ‘([^’ .. split .. ‘]+)’) do returnarr[i] = str i = i + 1 end return returnarr end options = split(‘option1=val1′,’=’) print(options.option1) — val 1

Couldn’t find the default string split function for LUA so I made my own.

Color Manipulation

function onetotfs(rgbtableone) rgbtableone.r = dechex(rgbtableone.r * 255) rgbtableone.g = dechex(rgbtableone.g * 255) rgbtableone.b = dechex(rgbtableone.b * 255) return ‘[‘ .. rgbtableone.r .. rgbtableone.g .. rgbtableone.b .. ‘]’ end function dechex(number) local base=16 local hexvals=’0123456789ABCDEF’ local returnval = ” local remainder while number>0 do number,remainder=math.floor(number/base),number%base+1 returnval=string.sub(hexvals,remainder,remainder)..returnval end return returnval end function niceColorName(color) return onetotfs(stringColorToRGB(color[1])) .. Player[color[1]].steam_name .. ‘[-]’ end print(dechex(255)) — ff print(niceColorName({‘White’})) — [ffffff]reimu[-] : note bb tags will just color the text

Changes numbers from base 10 to base 16. You can change to any base but this is specifically for changing the RGB tables that TTS uses (max value 1) to bbcode tags.

Searching Containers

function getIndexOf(col,table) for i=1,#table do if table[i] == col then return i end end return -1 end table = {1,2,3} print(getIndexOf(2,table)) — 2

That is for searching a table/array

function searchForIn(object, containerguid, params2) params2.guid = ‘000000’ local deckorbag local guids = {} if type(containerguid) == ‘string’ then deckorbag = getObjectFromGUID(containerguid) else deckorbag = containerguid end local obj = nil for k,v in pairs(deckorbag.getObjects()) do if string.find(string.lower(v.name==nil and v.nickname==nil and ” or v.name or v.nickname), string.lower(object)) then table.insert(guids, v.guid) end end if #guids > 0 then params2.guid = guids[math.random(#guids)] return deckorbag.takeObject(params2) else return false end end

Somewhat complicated function that will search a bag for all objects with matching names, then take out a random one:
Parameters:
String object – the name of the object you are searching for
String/Object containerguid – the guid of the container/deck you want to search or the actual container/deck object
Table params2 – the parameters when taking out the object
Returns – false if object not found in container/deck, reference to object if object found in container/deck

—-Player Control—-

Several functions that are not listed in the documentation on the official site that deal with players.

Kick, promote

These are things you can do with scripting

print(Player.white.promoted) Player.white.promote() Player.white.kick()
SteamSolo.com