Tabletop Simulator Guide

Advanced Scripting for Tabletop Simulator

Advanced Scripting

Overview

This is a guide on more advanced scripting topics. Some familiarity with Lua / TTS Scripting is expected.

Overview

This guide is meant to cover some of the more advanced things you can do with scripting in TTS. The code snippets listed herein aren’t meant to be copy pasted wholesale into a project and immediately do something useful, but rather to demonstrate how a thing can be done.

While the examples here are generally written with one specific task in mind, many of the techniques will be applicable to other scenarios. Use your imagination!

What’s On Top of Me – Dynamic Scripting Zones

Sometimes you want to find objects based on where their located on the table, relative to some other object. Perhaps the most common example is finding what’s on top of yourself. Fortunately, Tabletop Simulator provides a great tool for finding objects based on location, in the form of Scripting Zones. Unfortunately, scripting zones are fixed and won’t move with your objects, so they’re only really useful for looking at areas that always stay in place. Unless, of course, you create them on demand.

function buttonClicked() pos = self.getPosition() pos.y = pos.y + 1 zoneSpawn = {position = pos , scale = { 10, 1, 10 } , type = ‘ScriptingTrigger’ , callback = ‘zoneCallback’ , callback_owner = self , rotation = self.getRotation() } spawnObject(zoneSpawn) end function zoneCallback(zone) for _,o in ipairs(zone.getObjects()) do –do something with the objects end zone.destruct() –destroy the zone when you’re done with it, to avoid clutter. end

You could of course also loop through every object on the table and compare positions. This method should be much lighter on processing, especially for tables with lots of objects, but comes with it’s own downsides as well. As is often the case in programming, you’ll have to decide what works best for your specific situation.

Dynamic Button Creation – Button Parameters

One thing that causes many people difficulty when trying to do particularly advanced tasks with buttons is the fact that you can’t provide custom parameters to the button’s callback function. Fortunately, there is a way around this, by using the power of Closures and scripts’ ability to modify themselves.

function onLoad() for i = 1, 10 do local buttonNum = tostring(i) local funcName = “buttonFunc” .. tostring(i) local params = { click_function = funcName , function_owner = self , label = buttonNum , position = {1.25 + 0.5 * i,0,0} , width = 200 , height = 200 , font_size = 200 } local func = function() print(“Clicked Button #” .. buttonNum) end self.setVar(funcName, func) self.createButton(params) end end

Basically, if you have a local variable and define an anonymous function that references that local variable, the value of the variable gets stored along with the function so that it can keep using it. Then because functions on objects are just variables that store a function, you can store that anonymous function on your object with setVar and it’ll work just as if you’d written the function with that name normally.

If you want to learn more about Closures in Lua, I suggest the [link].

Also be aware that the anonymous function works just like any other button callback, so it’ll get the object the button is attached to and the color of the player who clicked it as parameters.

Putting Things in Front of Players – How to Use hand.trigger_…

You may want to place an object in front of where a player is sitting. This is actually pretty simple to do, but it’s not entirely intuitive how if you’re not familiar with vector math, so I thought an example would be useful.

function sendHome(obj, col) local offset = 4 local hand = Player[col].getPlayerHand() local target = { hand.pos_x + hand.trigger_forward_x * offset , hand.pos_y + hand.trigger_forward_y * offset , hand.pos_z + hand.trigger_forward_z * offset } obj.setPositionSmooth(target) obj.setRotationSmooth( {hand.rot_x , hand.rot_y + 180 –make object look out from hand , hand.rot_z } ) end

You can also use trigger_right_* and trigger_up_* to adjust positions vertically or horizontally based on the direction the hand is facing.

More

It’s likely there are other topics I could cover in this guide but haven’t yet. If there’s anything in particular you’d be interested, let me know in the comments. 🙂

Also, remember you can check the api reference: [link] . It can be a bit confusing at times, and doesn’t always cover everything in as much detail as I’d like, but it’s a great resource nonetheless. Once you get the hang of scripting in general the easiest way to figure out how to do something new is usually to scan the api for anything relevant and then try stuff out. At least, that’s how I always go about it.

SteamSolo.com