Blackjack: [url]http://steamcommunity.com/sharedfiles/filedetails/?id=620967608[/url]
Chess Clock: [url]http://steamcommunity.com/sharedfiles/filedetails/?id=637944720[/url]
Blackjack: [url]http://steamcommunity.com/sharedfiles/filedetails/?id=620967608[/url]
Chess Clock: [url]http://steamcommunity.com/sharedfiles/filedetails/?id=637944720[/url]
I have created an introductory scripting guide to teach the basic functionality of LUA for use with Tabletop Simulator.
[url]http://steamcommunity.com/sharedfiles/filedetails/?id=714904631[/url]
And now I made an intermediate scripting guide to teach intermediate functionality of Lua for use with Tabletop Simulator.
[url]http://steamcommunity.com/sharedfiles/filedetails/?id=879449506[/url]
It has a companion workshop table which has various scripting examples included.
[URL="http://steamcommunity.com/sharedfiles/filedetails/?id=879494019"]http://steamcommunity.com/sharedfiles/filedetails/?id=879494019[/URL]
Here are some scripting snippets I used in nearly all my mods that others may like !!
NOTE: - the "code" BBcode screws up the TABS a little!
Make Objects non-interactable
This is a great way to make table extensions or other parts of your mod to be locked in place beyond the normal "lock" function. The object will be completely unable to be interactive with by the user, even the host. This includes the "alt+mouseover" zoom view thing. I started using this as I use a lot of custom table extentions and player board, and found that people often accidentally unlocked the table extension and it as well as everything on it falls into the abyss!!
This script snipet is a GLOBAL script.
• Place this snipet at the top of your global script outside of any function.
• The list here is just an example and The numbers are just GUIDs of objects.
• To get the GUIDs, right click on the objects you want to freeze in your TTS scene and select scripting/guid from the context menu to copy the GUID to clipboard and then paste into the script.
• Rest of the Code looks like this...Code:--List for non-intractable objects! megaFreezeIT= { 'fc8017', '19d56d', 'a0d75b', 'cbf656', '3d4319', '0b829f', '5c9b8c', '9feb46'}
• I have made the actual function separate and called it megaFreeze()
• You need to the megaFreeze() function called fron onLoad()
Hint!!Code:function onLoad() megaFreeze() -- Make objects non-interactive end function megaFreeze() --megaFreeze ACTIVATE! for i=1, #megaFreezeIT, 1 do obj = getObjectFromGUID(megaFreezeIT[i]) if obj ~= nil then obj.interactable = false obj.tooltip = false end end end
• You can break up your megaFreezeIT list with comments to make the GUIDs understandable... like this!!
Code:megaFreezeIT = { 'fc8017', '19d56d', 'a0d75b', -- Table Extensions 'cbf656', '3d4319', '0b829f', '5c9b8c', '9feb46' -- Player Boards 1-5 }
--== REDUNDANT SO DELETED ==--
found a much better way to handle what this page was about, so I thought I would delete this to avoid confusion.
Last edited by Tragic; 09-02-2017 at 01:18 AM.
@Tragic
You could rewrite that like:
to save some keystrokesCode:buttons = { DescriptiveName = { index = index_DescriptiveName click_function = 'buttonFunctionName' function_owner = self label = 'Press me' position = {0, 0.6, 1.5} rotation = {0, 0, 0} width = 500 height = =500 font_size = 200 }, AnotherButton = { index = index_AnotherButton click_function = 'buttonAnotrherFunction' function_owner = self label = 'Or Me!' position = {0, 0.6, -1.5} rotation = {0, 0, 0} width = 500 height = =500 font_size = 200 } } function createAllButtons() for _, button in pairs(buttons) do self.createButton(button) end end
By the way, "index" field is ignored when creating buttons. They get a new index value anyway.
Coroutines:
[url]http://steamcommunity.com/sharedfiles/filedetails/?id=1094593362[/url]
Here are some scripting snippets I used in nearly all my mods that others may like !!
NOTE: - the "code" BBcode screws up the TABS a little!
Dynamic Button Index Finding
When you build a series of buttons upon a single object you need to track the button INDEX values. This is so if you press a button you can edit another button or whatever, and so on.. Each time you have more than 1 button the "index" needs to be reference so it knows which button you are using. The problem is that while indexes are dynamically assigned in acceding numerical order, as you add buttons, delete buttons edit buttons through scripts as well as adding new buttons physically in the code, this "index" order can become rather convoluted.
This code will dynamically 'find" the index for any given button allowing you to find it and edit whatever button in on your object with ease!
This code snip-it works like this
- It will search "self" for all buttons and add them to a list.
- It will then look at each "button.label" for each button it finds and compare them to the given string. By finding this string it has found the specified button the string is form.
- It then returns the index of that button
The Code
Usage ExampleCode:function findButtonIndex(label) local aButtons = self.getButtons() for _, B in pairs(aButtons) do --print(tostring(but.click_function)) if B.click_function == label then return B.index end end end
Code:button_example = { click_function = 'addTen', function_owner = self, label = '10', position = {1.2, 0.6, 1.64}, rotation = {0, 0, 0}, width = 350, height = 800, font_size = 650}Code:button_example = {index=findButtonIndex('addTen'), label = 20} self.editButton(button_example )
- In this example i have only added 1 new parameters, increasing the value of the readout +10 with luck this will make it clear as it is just the way to use the findButtonIndex() function.
- If you do not know you edit a button by redefining the table you originally used to create it. Change fonts, button sizes, whatever you like AND you need to include the correct index value. The top code is the original button.
Well, that is that!
You can now add as many buttons as you like, place them in any order, even copy and paste and move them and you never need to worry about indexs again!
Hope you like it!
Finding Object Tags from ScriptZones and Bags
Not really sure where I got this code snip from.. I "borrow" a lot from other mods... but i think this is from MrStump...
Anyway, this is a small function to "find" objects by tag in script zones. You can enter multiple types as well.
simply call it like this....Code:function getObjectTypesInZone(zone, ...) local foundTypes, tagList = {}, {...} for _, object in ipairs(zone.getObjects()) do for _, tag in ipairs(tagList) do if object.tag == tag then table.insert(foundTypes, object) break end end end return foundTypes end
That will return a table with containing any "decks" sound the zone....Code:getObjectTypesInZone(scriptZone, 'Deck')
Working Example
This is a super simple "deal" button using this code...
that is called like thisCode:function deal(num,player,hand,GUID) for _, deck in ipairs(getObjectTypesInZone(getObjectFromGUID(GUID), 'Deck', 'Card')) do if deck.tag == 'Deck' then deck.deal(num, player, hand) elseif deck.tag == 'Card' then local prams = {p={0.15, 3.03, -5.67},r={0.00, 180.00, 0.00}} deck.setPositionSmooth(prams.p) deck.setRotationSmooth(prams.r) end end end
Code:deal(2,'Green',1,5a4700)
Last edited by Tragic; 09-06-2017 at 08:00 AM.
Trimmed down version of Eskanders code - when a card leaves a deck, clones it back to the deck
Code:function onObjectLeaveContainer(container, object) local desc = object.getDescription() if string.find(desc, 'archive') then if container then local params = {} local destination = {} destination = container.getPosition() destination.y = destination.y + 2 params.position = destination local clone = object.clone(params) desc = string.gsub(desc, 'archive', 'copy') object.setDescription(desc) end end end
Using the inputs to create a search engine for card decks or bags. Type in the search field what you want to look for, click search and it will get it.
Code:function createInput() self.createInput({ input_function = "dud", label = "Search", function_owner = self, alignment = 3, position = {0,0.2,0}, width = 1500, height = 350, font_size = 250, color = {0,0,0}, font_color = {1,1,1}, value = "" }) end function dud() end function createButton() self.createButton({ click_function = "get_Card", function_owner = self, label = "Search for Card", position = {0, 0.2, 1.5}, width = 2500, height = 350, font_size = 250, color = {0,0,0}, font_color = {1,1,1} }) end function get_Card() local pos = self.getPosition() local inputs = self.getInputs() for i, v in pairs(inputs) do search_param = v.value end for _, card in ipairs(deck.getObjects()) do if card.nickname == search_param then deck.takeObject({position = {pos.x, pos.y, pos.z + 4}, guid = card.guid}) end end end
This is my "button creation code"... I find it very easy to use and I use it in nearly every mod.. so I need a place to be able to quickly copy and paste it lol.. so thought this thread would be a good location!
The way this works is that you have all the button code, which can be really large and ugly, in a function at the bottom of the script nice and out of the way. You place the makeButtons() call in the onload() as normal but can call it at any time.Code:function onload() makeButtons() end function makeButtons(set) local buttons = {} -- DEFAULT START BUTTONS if set == nil then button = { click_function = 'functionName', function_owner = self, label = 'Button Lable', position = {0, 0.5, 0.5}, rotation = {0, 180, 0}, width = 1300, height = 350, font_size = 200} table.insert(buttons, button) end -- Create Buttons for _, button in ipairs(buttons) do self.createButton(button) end end
The makeButtons() function can take a string input, I use this to allow the same function to be used for all my buttons for that object. I simply can add a "if statement" testing the "set" variable to load different buttons at different times. If nothing is passed as the "set" then it will default to the "== nil" that I have added to this example code.
Check out my "find button index" code as well for more button madness that I find useful. - [url=http://www.berserk-games.com/forums/showthread.php?1990-Scripting-Examples&p=19667#post19667]Find button index code snippet[/url] @Beserk Forum
Last edited by Tragic; 11-21-2018 at 08:06 PM.
I wanted to add this code, even though i didn't write it.
onelivesleft's "wait" function
This is a cool code snip I was given by the man, the myth, the legend OneLivesLeft.
Basically it is a "after a time period, do this function"... so ti is another "wait: function.. but little easier to use. Basically add this function anywhere in your object script and then call it as needed.
example:Code:function after(delay, func, ...) local params = {...} function after_routine() local after_time = os.clock() + delay repeat coroutine.yield(0) until os.clock() >= after_time func(unpack(params)) return 1 end startLuaCoroutine(self, 'after_routine') endThis code will delete the object after a .05 second delay.Code:after(0.5,self.destruct)
I'll do you an upgrade, related to [URL="http://www.berserk-games.com/forums/showthread.php?4826-Need-help-modifying-one-of-Stumps-Die-Rollers&p=21220#post21220"]this post[/URL].
Does what the last one did, but can also take a function as the delay parameter; it triggers after the function stops being true.Code:function after(delay, func, ...) local params = {...} function after_routine() if type(delay) == 'function' then repeat coroutine.yield(0) until not delay() else local after_time = os.clock() + delay repeat coroutine.yield(0) until os.clock() >= after_time end func(unpack(params)) return 1 end startLuaCoroutine(self, 'after_routine') end
So for instance, you can:
Code:-- die is the die object die.setPositionSmooth({1, 2, 3}) after(die.isSmoothMoving, die.roll)
Remove Duplicates from Table
I had a terrible time finding this code snipit last night.. much googling and stack exchanged reading until I finally found a bit of code I could get working AND understand lol...
The above code will go through a table and remove duplicated in that table.... the usage is something like this...Code:-- Remove duplicates from a table array function table_unique(tt) function table_count(tt, item) local count count = 0 for ii,xx in pairs(tt) do if item == xx then count = count + 1 end end return count end local newtable newtable = {} for ii,xx in ipairs(tt) do if(table_count(newtable, xx) == 0) then newtable[#newtable+1] = xx end end return newtable end
This code is particularly useful when using overlapping scriptzones and getObjects() as an object touching 2 zones will be picked up twice. So you can grab contents off all the scriptzones, then remove duplicates and have a list of only the things you want, and only have them listed once.Code:local noDupes = table_unique(tableWithDupes)
Example Pickup Code
This mod has a series of script zones on the table that cover all the spots players can place cards.. but the script zones over lap. So cards in two or more zones will get "added" to the table twice.
Code:-- Loop through a series of zones and store data for each "Card" found in a table called "cardPickup". local pickupZones = {'06b0c8','ce9f84','85d23e','defe97','f7cae4','5007be','1d0f53'} local Y = 1.3 local cardPickup = {} for _, zone in ipairs(pickupZones) do for _, obj in ipairs(getObjectFromGUID(zone).getObjects()) do if obj.tag == 'Card' then table.insert(cardPickup, obj) end end end local noDupes = table_unique(cardPickup) -- remove duplicates. --Move found cards form cleaned list to discard pile, and increment the Y value between them so they stack well. for _, card in ipairs(noDupes) do card.setPositionSmooth({14.78, Y, 21.57}) Y = Y + 0.3 end
script snip that was in THIS reply ( not the one above) has been removed
--- Found a bug after some more testing... shouldn't have been so quick to post!
Last edited by Tragic; 01-07-2018 at 03:34 PM.
@Tragic
That table_unique function is doing a lot of unnecessary iteration. Try something like
That's for arrays (number keyed tables).Code:function table_unique(orig) local out = {} local present = {} for _,v in ipairs(orig) do if not present[v] then out[#out+1] = v end present[v] = true end return out end
Health Meter: [URL="http://steamcommunity.com/sharedfiles/filedetails/?id=1339242748"]http://steamcommunity.com/sharedfiles/filedetails/?id=1339242748[/URL]
Script for calculating setting a button width that matches the width of the text: [URL="http://steamcommunity.com/sharedfiles/filedetails/?id=1350180011"]http://steamcommunity.com/sharedfiles/filedetails/?id=1350180011[/URL]
Toggle Button: [URL="http://steamcommunity.com/sharedfiles/filedetails/?id=1350189058"]http://steamcommunity.com/sharedfiles/filedetails/?id=1350189058[/URL]
Configurable clock: [URL="http://steamcommunity.com/sharedfiles/filedetails/?id=1308351284"]http://steamcommunity.com/sharedfiles/filedetails/?id=1308351284[/URL]
Last edited by Confederate In Blue; 04-02-2018 at 08:14 AM. Reason: Added Configurable Clock
@Tragic, in your megaFreeze() function, do you really need to set obj.tooltip = false?
It has been my experience that once obj.interactable = false, the tooltip is not displayed even if obj.tooltip is set to true (and there is tooltip text defined, of course).
no not anymore.
I am occasionally caught by Lua's table handling...
When I wrote this in a naive way, I wrote:
this puts each card farther over than the last rather than placing them evenly.Code:function spread(player) local deck = Player[player].getHoverObject() local anchor = deck.getPosition() local pos = anchor local offx = 4 local offz = 0 for i, _ in ipairs(deck.getObjects()) do pos.x = anchor.x - offx pos.z = anchor.z + offz deck.takeObject({position=pos}) offx = offx + 4 if offx > 32 then offx = 4 offz = offz + 6 end end end
Reason is, tables are references, not values. changing pos.x is also changing anchor.x.
I had to use variables, like this.
Code:function spread(player) local deck = Player[player].getHoverObject() local anchor = deck.getPosition() local basex = anchor.x local basez = anchor.z local pos = {x = 0, y = anchor.y, z = 0} local offx = 4 local offz = 0 for i, _ in ipairs(deck.getObjects()) do pos.x = basex - offx pos.z = basez + offz deck.takeObject({position=pos}) offx = offx + 4 if offx > 32 then offx = 4 offz = offz + 6 end end end
Reverse a Table
Shuffle a TableCode:--Reverses a table function reverseTable(t) local reversedTable = {} local itemCount = #t for k, v in ipairs(t) do reversedTable[itemCount + 1 - k] = v end return reversedTable end
make sure you use math.randomseed(os.time())
Code:--shuffle function shuffle(tbl) for i = #tbl, 1, -1 do local j = math.random(i) tbl[i], tbl[j] = tbl[j], tbl[i] end return tbl end
Last edited by Tragic; 11-22-2018 at 04:42 PM.
Your shuffle mutates the input table *and* returns a copy of it; it should really only do one or the other.