1. Tabletop Simulator
  2. News
  3. Update v12.1 Music Player, PDF support, and tons of other great improvements!

Update v12.1 Music Player, PDF support, and tons of other great improvements!

Hey everyone, we got another great update for you today! We have added 2 very long requested features a Music Player and PDF support! There are also a ton of great additions and improvements listed below in the patch notes.



Music Player
  • The music player let's you play audio files (.mp3, .wav, .ogg, ogv) which are synced for all players.
  • Great for room music or so your DnD campaign has the right mood!
  • Supports playlists with ordering, shuffling, and looping.


Custom PDF
  • New object Custom PDF, that allows you import a PDF onto a tile.
  • This converts the PDF into a series of images, to make it easy to import your rule books!
  • Supports multiple pages: swap between them with the contextual menu, next/previous state hotkeys, or the buttons on the left and right side.
  • Can popout the PDF to the screen by hitting the hidden UI button on the top left of the PDF object.
  • You can joint this to any objects to add any visual flair you would like to match the game.


Cloud Manager Folders
  • Cloud manager now supports folders just like Saved Games/Objects.
  • When you import all loaded assets into cloud it puts them in a folder defaulting to the Game name.
  • Can now name files that are uploaded to the Cloud instead of just using the file name on disk.


Sound Improvements
  • Custom Objects that are set to dice or coin will now get that correct sounds for their selected material type.
  • Improved sounds for objects interacting with locked objects.
  • Added glass material type for Custom AssetBundle and Custom Model.


Alpha Transparency Support
  • Added alpha support to the color picker.
  • Can now draw with semi tranparency.
  • Can color tint objects to have alpha transparency, which goes nicely with the new glass material type.
  • Objects with alpha transparency will not cast shadows.


Magnify Revamp
  • Magnify (hotkey m) overhauled to be round.
  • Scroll up or down to control the zoom level of the magnify.
  • Fixed visual issues with previous magnify.


General Improvements
  • Added loading percent next to the player names on the top right.
  • For the top bar in-game the Scripting, Workshop Upload, and Cloud Manager menus have been moved under "Modding".
  • Improved auto-raise to work better with overhangs.
  • Added a workshop indicator next to the chat window that you can hover over and get info about how far along the workshop subscription check is at.
  • Moved physics mode (semi-lock, locked, etc) from Configuration to Server Options.
  • Greatly improved compatibility with old AssetBundles shaders. This will fix a lot of broken DLCs.
  • Improved Fog of War performance.
  • File Browser now remembers the last opened path.
  • Updated Voice Chat plugin.
  • Voice chat is now using a higher quality setting.
  • Added hidden zone opacity sliders to Misc settings.


Scripting Improvements
  • New global class Vector:

Constructors:

Vector(num, num, num) --> return a vector with specified (x, y, z) components

Vector(table) --> return a vector with x/y/z or 1/2/3 conponents from source table (x/y/z first)

Vector.new(...) --> same as Vector(...)



Vector.max(vec1, vec2) --> return a vector with max components between vec1 and vec2

Vector.min(vec1, vec2) --> return a vector with min components between vec1 and vec2

Vector.between(vec1, vec2) --> return a vector pointing from vec1 to vec2

vec:copy() --> copy self into a new vector and retur it



Component access:

vec.x, vec.y, vec.z --> read/write component

v[1], v[2], v[3] --> read/write component

vec:get() => num, num, num --> returns x, y, z components of self





Methods modifying self and returning self:

vec:setAt(key, num) --> same as "vec[key] = num"

vec:set(num, num, num) --> set x, y, z components to passed values

vec:add(otherVec) --> adds components of otherVec to self

vec:sub(otherVec) --> subtracts components of otherVec from self

vec:scale(otherVec) --> multiplies self components by corresponding compnents from otherVec

vec:scale(num) --> multiplies self components by a numeric factor

vec:clamp(num) --> if self magnitude is higher than provided limit, scale self down to match it

vec:normalize() --> scale self to magnitude of 1

vec:project(otherVec) --> make self into projection on another vector

vec:reflect(otherVec) --> reflect self over a plane defined through a normal vector arg

vec:inverse() --> multiply self components by -1

vec:moveTowards(otherVec, num) --> move self towards another vector, but only up to a provided distance limit

vec:rotateTowards(otherVec, num) --> rotate self towards another vector, but only up to a provided angle limit

vec:projectOnPlane(otherVec) --> project self on a plane defined through a normal vector arg



Methods not modifying self:

vec:dot(otherVec) --> return a dot product of self with otherVec

vec:magnitude() --> return self magnitude (length)

vec:sqrMagnitude() --> return self magnitude (length) squared

vec:distance(otherVec) --> returns distance between self and otherVec

vec:sqrDistance(otherVec) --> returns squared distance between self and otherVec

vec:equals(otherVec, num) --> returns true if otherVec same as self (optional numeric tolerance param), false otherwise

vec:string(str) --> return string describing self, optional string prefix

vec:angle(otherVec) --> return an angle between self and otherVec, in degrees [0, 180]

vec:cross(otherVec) --> return a cross-product vector of self and otherVec

vec:lerp(otherVec, num) --> return a vector some part of the way between self and otherVec, numeric arg [0, 1] is the fraction

vec:normalized() --> return a new vector that is normalized (length 1) version of self

vec:orthoNormalize() --> return three normalized vectors perpendicular to each other, first one being in the same dir as self

vec:orthoNormalize(otherVec) --> same as vec:orthoNormalize(), but second vector is guranteed to be on a self-otherVec plane



Operators:

vecOne + vecTwo --> return a new vector with added components of vecOne and vecTwo

vecOne - vecTwo --> return a new vector with subtracted components of vecTwo from vecOne

vecOne * vecTwo --> return a new vector with multiplied components of vecOne and vecTwo, NOT a dot product (!)

vec * number --> return a new vector with all components from vec scaled by a numeric factor

number * vec --> same as "vec * number"

vecOne == vecTwo --> return true if both vectors identical or within a small margin of each other, false otherwise

tostring(vec) --> return a string description of a vector
  • New global class Color:




Constructors:

Color(num, num, num) --> return a color with specified (r, g, b) components

Color(num, num, num, num) --> return a color with specified (r, g, b, a) components

Color(table) --> return a color with r/g/b/a or 1/2/3/4 components from source table (letter keys prioritized)

Color.new(...) --> same as Color(...)



Color.fromString(colorStr) --> return a color from a color string ('Red', 'Green' etc), capitalization ignored

Color.fromHex(hexStr) --> return a color from a hex representation string (e.g. '#ff112233'), hash sign and alpha are optional

col:copy() --> copy self into a new color and return it



Color.Purple [etc] --> shorthand for Color.fromString('Purple'), works for all player and added colors, capitalization ignored



Component access:

col.r, col.g, col.b, col.a --> read/write component

col[1], col[2], col[3], col[4] --> read/write component

col:get() => num, num, num, num --> returns r, g, b, a components of self



col:toHex(includeAlpha) --> returns a hex string for self, boolean parameter

col:toString(num) --> returns a color string if matching this instance, nil otherwise, optional numeric tolerance param



Methods modifying self and returning self:

col:setAt(key, num) --> same as "col[key] = num"

col:set(num, num, num, num) --> set r, g, b, a components to passed values



Methods not modifying self:

col:equals(otherCol, num) --> returns true if otherCol same as self, false otherwise, optional numeric tolerance param

col:lerp(otherCol, num) --> return a color some part of the way between self and otherCol, numeric arg [0, 1] is the fraction



Operators:

colOne == colTwo --> return true if both colors identical or within a small margin of each other, false otherwise

tostring(col) --> return a string description of a color



Other:

Color.list --> table of all color strings

Color.Add(name, yourColor) --> add your own color definition to the class (string name, Color instance yourColor)
  • Added an overload to UI.setXml() and UI.setXmlTable() to take a CustomAssets as the last param.
  • Music Player exposed to Lua.
  • Added logString function, which returns a string representation of a lua object (the same representation the log function uses)
  • Fixed cleanup issue with Xml custom assets UI from lua for clients.
  • Fixed turns not network syncing for Lua.


VR
  • Improved movement - added movement inertia. Can be calibrated or disabled in VR settings.
  • Grid overlay now renders in VR.
  • Fog of War now renders in VR.
  • Added VR documentation to api website: https://api.tabletopsimulator.com/vr/


Spectator Mode
  • Spectator window may now display the view grey players have (for example, cards in your hand will be hidden). Enable with +spectator_restrict_view
  • Spectator window now renders the grid. May be turned off with -spectator_show_grid


System Console


  • Added documentation for system console to tabletop api website: https://api.tabletopsimulator.com/systemconsole/
  • Inline variable evaluation changed to use { and } (instead of < and >). See above page for details.
  • You may now use alias to run commands when a toggle variable's value is changed.
  • skip now allows for various comparisons, and fuzzy equality check.
  • Added ui_anchor, ui_label and ui_toggle commands (to accompany ui_button), allowing you more options for easily running commands / changing setting during play.


New commands: (for more info see above page, or use help )

  • append - Adds text, or the last entered command, to a text variable.
  • camera_reset_on_load - Whether the camera resets its position when you do a Save & Play in Atom.
  • chat_input - Activates chat input box.
  • component_examine - Sets game component currently being examined.
  • component_move, component_rotate, component_position, component_rotation - Apply movements to components.
  • eval - Evaluates an expression and stores it in a variable.
  • examine_position, examine_rotation - Return information on the currently examined component.
  • hidden_zone_showing_opacity, hidden_zone_hiding_opacity - Set visual opacity of hidden zones.
  • lua - Execute a lua statement.
  • music_add, music_mute, music_next, music_pause, music_play, music_prev, music_repeat, music_shuffle, music_timecode - Commands to control new music player.
  • spectator_restrict_view - Whether the spectator window shows your view, or that of a grey player.
  • spectator_show_grid - Whether the grid is rendered in the spectator window.
  • team - Stores / sets team you are currently on.
  • ui_anchor - Sets position UI elements are made relative to (default is 0,0 - the center of the screen)
  • ui_label - Add static text UI element.
  • ui_toggle - Add checkbox UI element.
  • vector_x, vector_y, vector_z - Return an individual axis from a vector variable.
  • vr_move_with_inertia - Whether you have inertia in VR.
  • vr_move_friction - When you have inertia, how quickly you slow down.
  • vr_scale_rotate_rate - How much smoothing is applied during scaling/rotating.


Fixes
  • Fixed scroll wheel being inverted for Linux.
  • Fixed Components menu chess Wood White King being missing.
  • Fixed search and expand for Games menu.
  • Fixed misc issues with spectator camera.