Visual Snippet Library
A collection of copy-paste ready Lua code blocks to speed up your modding workflow.
Add UI Button
When a player joins they get a button added to their hud that when pressed sends them a subtle message
function sendMessage(callbackData)
tm.playerUI.AddSubtleMessageForPlayer(callbackData.playerId, "Hello", tm.players.GetPlayerName(callbackData.playerId), 3, "")
end
function onPlayerJoined(player)
tm.playerUI.AddUIButton(player.playerId, "playerbtn" .. tostring(player.playerId), "Press for Message", sendMessage, player.playerId) -- When a user presses the button it calls the function sendMessage
end
-- Add new UI to the player that joins
tm.players.OnPlayerJoined.add(onPlayerJoined)
Melvin Shower
Spawns melvins above players in the sky at random intervals
local nextMelvinTime = 0
function UpdateMelvinShower()
local time = tm.os.GetTime()
if time > nextMelvinTime then
nextMelvinTime = time + (math.random() * 3.0) -- Spawn a melvin between immediately and 3 seconds
local players = tm.players.CurrentPlayers()
for _, p in pairs(players) do
local pPos = tm.players.GetPlayerTransform(p.playerId).GetPosition()
-- Random Position in sky
local x = pPos.x + math.random(-50, 50)
local y = pPos.y + math.random(50, 120)
local z = pPos.z + math.random(-50, 50)
local spawnPos = tm.vector3.Create(x, y, z)
-- Spawn Melvin
local melvin = tm.physics.SpawnObject(spawnPos, "PFB_Birdo_Medium")
-- Check if spawn was successful
if melvin.Exists() then
local transform = melvin.GetTransform()
-- 1. Random Rotation
-- Generate random angles for X, Y, Z axes
local rx = math.random(0, 360)
local ry = math.random(0, 360)
local rz = math.random(0, 360)
transform.SetRotation(rx, ry, rz)
-- 2. Random Size
local randomSize = 0.5 + (math.random() * 4.0)
transform.SetScale(randomSize)
end
end
end
end
function update()
UpdateMelvinShower()
end
Freeze Vehicle
Uses set drag and engine power to effectively freeze a vehicle
local savedPowerCache = {}
function ToggleVehicleFreeze(playerId, shouldFreeze)
local structure = tm.players.OccupiedStructure(playerId)
if structure ~= nil then
local blocks = structure.GetBlocks()
for _, block in pairs(blocks) do
if shouldFreeze then
-- 1. FREEZE VEHICLE
block.SetDragAll(999, 999, 999, 999, 999, 999)
-- 2. SAVE & CUT POWER
-- We store the original values in a table keyed by the block itself
local stats = {}
local needsSave = false
-- Engines
if block.IsEngineBlock() then
stats.engine = block.GetEnginePower()
block.SetEnginePower(0.0001) -- Never set the power to 0 as this will cause the game to crash
needsSave = true
end
-- Jets
if block.IsJetBlock() then
stats.jet = block.GetJetPower()
block.SetJetPower(0.0001)
needsSave = true
end
-- Propellers
if block.IsPropellerBlock() then
stats.prop = block.GetPropellerPower()
block.SetPropellerPower(0.0001)
needsSave = true
end
-- Gyros
if block.IsGyroBlock() then
stats.gyro = block.GetGyroPower()
block.SetGyroPower(0.0001)
needsSave = true
end
if needsSave then
savedPowerCache[block] = stats
end
else
-- 1. UNFREEZE VEHICLE
block.ResetDragAll()
-- 2. RESTORE POWER
local stats = savedPowerCache[block]
if stats then
if stats.engine then block.SetEnginePower(stats.engine) end
if stats.jet then block.SetJetPower(stats.jet) end
if stats.prop then block.SetPropellerPower(stats.prop) end
if stats.gyro then block.SetGyroPower(stats.gyro) end
savedPowerCache[block] = nil
end
end
end
local msg = shouldFreeze and "Frozen" or "Unfrozen"
tm.playerUI.AddSubtleMessageForPlayer(playerId, "VEHICLE", msg, 1, "")
end
end
-- Usage Example:
ToggleVehicleFreeze(0, true)
Get Vehicle Mass
Gets the mass of the vehicle that the player is currently in
function GetVehicleMass(playerId)
local structure = tm.players.OccupiedStructure(playerId)
local totalMass = 0
if structure ~= nil then
local blocks = structure.GetBlocks()
for _, block in pairs(blocks) do
totalMass = totalMass + block.GetMass()
end
end
return totalMass
end
Closest Player
Loops through all players and returns the ID of the one closest to a specific position, excluding the caller.
function GetClosestPlayer(originPos, ignoreId)
local players = tm.players.CurrentPlayers()
local closestId = -1
local closestDist = 999999
for _, p in pairs(players) do
if p.playerId ~= ignoreId then
local targetPos = tm.players.GetPlayerTransform(p.playerId).GetPosition()
local dist = tm.vector3.Distance(originPos, targetPos)
if dist < closestDist then
closestDist = dist
closestId = p.playerId
end
end
end
return closestId
end
Collectable Coin
Spawns a "Coin" (trigger). When a player hits it, they get a point and a sound plays.
local coinPos = tm.vector3.Create(10, 300, 10)
local coinTrigger = nil
local playerScores = {}
function SetupCoin()
-- Spawn Trigger
coinTrigger = tm.physics.SpawnBoxTrigger(coinPos, tm.vector3.Create(2, 2, 2))
-- Register Pickup Function
tm.physics.RegisterFunctionToCollisionEnterCallback(coinTrigger, "OnPickupCoin")
end
function OnPickupCoin(playerId)
-- 1. Add Score
if playerScores[playerId] == nil then playerScores[playerId] = 0 end
playerScores[playerId] = playerScores[playerId] + 1
-- 2. Feedback
tm.playerUI.AddSubtleMessageForPlayer(playerId, "COLLECTED", "Coins: " .. playerScores[playerId], 2, "")
tm.audio.PlayAudioAtPosition("UI_Reward_Gold_Coin_play", coinPos, 1)
end
SetupCoin()
Structure Turntable
Automatically rotates a player's vehicle slowly when within the radius of the center.
-- Configuration
local rotationSpeed = 0.5
local showroomCenter = tm.vector3.Create(0, 300, 0)
local showroomRadius = 10
function UpdateShowroom()
local players = tm.players.CurrentPlayers()
for _, p in pairs(players) do
-- Check if player is seated first
if tm.players.IsPlayerInSeat(p.playerId) then
local seatBlock = tm.players.GetPlayerSeatBlock(p.playerId)
local structure = seatBlock.GetStructure()
local pos = structure.GetPosition()
-- Check distance
if tm.vector3.Distance(pos, showroomCenter) < showroomRadius then
-- Apply Torque to the SEAT block
-- Y-axis torque spins it horizontally
seatBlock.AddTorque(0, rotationSpeed * 1000, 0)
end
end
end
end
function update()
UpdateShowroom()
end
Stats HUD
Shows the players current vehicle speed and altitude
local hudUpdateInterval = 0.2
local lastHudUpdate = 0
function SetupPlayerHUD(player)
-- Add the labels
tm.playerUI.AddUILabel(player.playerId, "lbl_speed", "SPD: 0 km/h")
tm.playerUI.AddUILabel(player.playerId, "lbl_alt", "ALT: 0 m")
end
function UpdateHUDValues()
local time = tm.os.GetTime()
if time > lastHudUpdate + hudUpdateInterval then
lastHudUpdate = time
local players = tm.players.CurrentPlayers()
for _, p in pairs(players) do
local structure = tm.players.OccupiedStructure(p.playerId)
if structure ~= nil then
local speed = math.floor(structure.GetSpeed() * 3.6)
local alt = math.floor(structure.GetPosition().y)
tm.playerUI.SetUIValue(p.playerId, "lbl_speed", "SPD: " .. speed .. " km/h")
tm.playerUI.SetUIValue(p.playerId, "lbl_alt", "ALT: " .. alt .. " m")
else
tm.playerUI.SetUIValue(p.playerId, "lbl_speed", "On Foot")
tm.playerUI.SetUIValue(p.playerId, "lbl_alt", "Ground Level")
end
end
end
end
function update()
UpdateHUDValues()
end
-- Hook into the join event
tm.players.OnPlayerJoined.add(SetupPlayerHUD)
Teleport Command
Teleport to a position by using a chat command
function OnTeleportCommand(senderName, message, color)
-- Pattern match for "/tp X Y Z"
-- Example: /tp 0 50 0
local x, y, z = string.match(message, "/tp (%-?%d+) (%-?%d+) (%-?%d+)")
if x and y and z then
-- Find the player who sent the command
local players = tm.players.CurrentPlayers()
for _, p in pairs(players) do
if p.playerName == senderName then
-- Create vector from parsed strings
local newPos = tm.vector3.Create(tonumber(x), tonumber(y), tonumber(z))
-- Set position
local transform = tm.players.GetPlayerTransform(p.playerId)
transform.SetPosition(newPos)
tm.playerUI.AddSubtleMessageForPlayer(p.playerId, "TELEPORT", "Moved to " .. x .. "," .. y .. "," .. z, 3, "")
return
end
end
end
end
tm.playerUI.OnChatMessage.add(OnTeleportCommand)
Heal Vehicle
Restores the health of a vehicle the player is currently in back to the start health
function HealVehicle(playerId)
local structure = tm.players.OccupiedStructure(playerId) -- We get the structure the player is currently seated in
if structure ~= nil then
local blocks = structure.GetBlocks()
for _, block in pairs(blocks) do
-- Get the original max health of the block
local maxHp = block.GetStartHealth()
-- Reset current health to max
block.SetHealth(maxHp)
end
tm.playerUI.AddSubtleMessageForPlayer(playerId, "REPAIR", "Structure Integrity Restored", 2, "")
end
end
Click to Jump
When a player clicks on another player thats in a vehicle, the target players vehicle will be forced to jump.
function SetupMouseInput(player)
-- Register a callback that fires when the player clicks
-- It passes the World Position of the click to "OnClickJump"
tm.playerUI.RegisterMouseDownPositionCallback(player.playerId, OnClickJump)
end
function OnClickJump(clickData)
local playerId = clickData.playerId
local targetPos = tm.vector3.Create(clickData.value)
-- Apply force to nearby players
local radius = 20
local jumpForce = 10000
local players = tm.players.CurrentPlayers()
for _, p in pairs(players) do
local struct = tm.players.OccupiedStructure(p.playerId)
if struct ~= nil then
local sPos = struct.GetPosition()
if tm.vector3.Distance(targetPos, sPos) < radius then
struct.AddForce(0, jumpForce, 0) -- Jumps them upwards
end
end
end
end
tm.players.OnPlayerJoined.add(SetupMouseInput)
Building Whitelist
Only allows building for users in the whitelist
-- Table of allowed Profile IDs
local whitelistedUsers = {
["1r81vc3f34d1ce0002f08a51"] = true -- Replace with an actual ID, add as many as you need
}
function EnforceBuilderWhitelist(player)
-- Get the unique profile ID of the player joining
local myProfileId = tm.players.GetPlayerProfileId(player.playerId)
-- Check if this ID exists in our allowed table
if whitelistedUsers[myProfileId] then
-- ALLOW: Enable builder for whitelisted
tm.players.SetBuilderEnabled(player.playerId, true)
tm.playerUI.AddSubtleMessageForPlayer(player.playerId, "WHITELISTED", "Builder Access Granted", 3, "")
else
-- DENY: Disable builder for non-whitelisted
tm.players.SetBuilderEnabled(player.playerId, false)
tm.playerUI.ShowIntrusiveMessageForPlayer(player.playerId, "RESTRICTED", "Building is whitelist only.", 5)
end
end
-- Run this check every time a player joins the server
tm.players.OnPlayerJoined.add(EnforceBuilderWhitelist)
Slow Motion
Toggles slow motion by changing the physics time scale
function ToggleSlowmo(isActive)
if isActive then
-- Set physics time scale to 30% speed
tm.physics.SetTimeScale(0.3)
tm.playerUI.ShowIntrusiveMessageForAllPlayers("SLOWMO", "Time Slowed!", 2)
else
-- Reset to normal speed (1.0)
tm.physics.SetTimeScale(1.0)
tm.playerUI.ShowIntrusiveMessageForAllPlayers("NORMAL TIME", "Time Restored", 2)
end
end
Rainbow Vehicle
Cycles the color of every block in a player's vehicle
function UpdateRainbowVehicle(playerId)
-- Get the vehicle
local structure = tm.players.OccupiedStructure(playerId)
if structure ~= nil then
-- Calculate a color based on current time
local time = tm.os.GetTime()
local hue = (time * 0.5) % 1.0 -- 0.5 controls speed
-- Convert HSV to RGB
local rainbowColor = tm.color.HSVToRGB(hue, 1, 1)
-- Apply to all blocks
local blocks = structure.GetBlocks()
for _, block in pairs(blocks) do
block.SetPrimaryColor(rainbowColor)
end
end
end
function update()
UpdateRainbowVehicle(0)
end
Welcome Message
Sends a welcome message in the chat when a player joins
function GreetNewPlayer(player)
-- Get the new player's name
local name = tm.players.GetPlayerName(player.playerId)
-- Create the welcome string
local msg = "Welcome " .. name .. " to the server!"
-- Send it to chat in Green
tm.playerUI.SendChatMessage("Server", msg, tm.color.Green())
end
-- Register the event
tm.players.OnPlayerJoined.add(GreetNewPlayer)
Chat Commands
Adds a /coords chat command that gives the player a subtle message with their coordinates.
-- Looks through all connected players and returns the playerId
local function GetPlayerIdByName(name)
-- Loop through the list of current players
for _, p in ipairs(tm.players.CurrentPlayers()) do
-- Check if this player's name is the one we're looking for
if p.playerName == name then
-- Found the correct player, return their ID
return p.playerId
end
end
return nil
end
-- This function runs whenever any player sends a chat message
function OnChat(senderName, message, color)
-- Check if the message is exactly "/coords"
if message == "/coords" then
-- Convert the sender's name into a usable playerId
local playerId = GetPlayerIdByName(senderName)
-- Get the player's transform
local transform = tm.players.GetPlayerTransform(playerId)
-- Read their world coordinates from the transform
local pos = transform.GetPositionWorld()
local msg = string.format("X=%.2f Y=%.2f Z=%.2f", pos.x, pos.y, pos.z)
-- Show the coordinates as a subtle on-screen message
tm.playerUI.AddSubtleMessageForPlayer(
playerId,
"Coordinates",
msg,
5, -- duration in seconds
"" -- no icon
)
end
end
-- Register our chat listener so the game actually uses it
tm.playerUI.OnChatMessage.add(OnChat)
Spawn a barrel above player
Spawns a barrel above the player
function SpawnBarrelAbovePlayer(playerId)
-- Get the player's transform (position/rotation)
local playerTransform = tm.players.GetPlayerTransform(playerId)
-- Get current position from the transform
local currentPos = playerTransform.GetPosition()
-- Create a vector 5 units up
local offset = tm.vector3.Create(0, 5, 0)
-- Calculate spawn position by adding the offset
local spawnPos = tm.vector3.op_Addition(currentPos, offset)
-- Spawn the object (e.g., PFB_Barrel)
tm.physics.SpawnObject(spawnPos, "PFB_Barrel")
end
Auto Assign Teams
Assigns players to team 1 or 2 when they join. Based on player id
function AutoAssignTeam(playerId)
-- Even IDs = Team 1, Odd IDs = Team 2
local teamIndex = (playerId % 2) + 1
-- Set the team
tm.players.SetPlayerTeam(playerId, teamIndex)
end
-- Hook this into the PlayerJoined event
tm.players.OnPlayerJoined.add(AutoAssignTeam)
Checkpoint System
When a player enters the checkpoint area itll set the spawn point for them to that checkpoint
-- Configuration: Set coordinates for the checkpoint
local checkpointPosition = tm.vector3.Create(0, 300, 100)
local checkpointTrigger = nil
function SetupCheckpoint()
-- Spawn a 15x15x15 trigger box at the position
checkpointTrigger = tm.physics.SpawnBoxTrigger(checkpointPosition, tm.vector3.Create(15, 15, 15))
-- Register the callback function.
-- The game will automatically pass the 'playerId' of the person entering the zone.
tm.physics.RegisterFunctionToCollisionEnterCallback(checkpointTrigger, "OnPlayerEnterCheckpoint")
end
function OnPlayerEnterCheckpoint(playerId)
-- 1. Define the spawn coordinates for the ID "Checkpoint_1"
-- We use the checkpointPosition so they respawn exactly where the trigger is
tm.players.SetSpawnPoint(playerId, "Checkpoint_1", checkpointPosition, tm.vector3.Create(0, 0, 0))
-- 2. Set "Checkpoint_1" as the active spawn location for this player
tm.players.SetPlayerSpawnLocation(playerId, "Checkpoint_1")
-- 3. Show a message only to the player who entered
tm.playerUI.ShowIntrusiveMessageForPlayer(playerId, "CHECKPOINT", "Progress Saved!", 2)
end
-- Initialize the checkpoint
SetupCheckpoint()
Spawning a blueprint
How to spawn a blueprint using tm.players.SpawnStructure() and tm.physics.AddTexture()
local position = tm.vector3.Create(0,0,0)
local rotation = tm.vector3.Create(0,0,0)
local playerId = 0
local structureId = 0
tm.physics.AddTexture("Blueprint.png", "Blueprint")
tm.players.DespawnStructure(structureId)
tm.players.SpawnStructure(playerId, "Blueprint", structureId, position, rotation)
Add UI to player that joins
This snippet adds a small label ui to every player that joins that says "Hello, [username]"
function onPlayerJoined(player)
tm.playerUI.AddUILabel(player.playerId, "playerlbl" .. tostring(player.playerId), "Hello, " .. player.playerName)
end
-- Add new UI to the player that joins
tm.players.OnPlayerJoined.add(onPlayerJoined)