Page 2 of 2 FirstFirst 12
Results 26 to 36 of 36

Thread: Scripting Examples

  1. #26
    Quote Originally Posted by onelivesleft View Post
    Your shuffle mutates the input table *and* returns a copy of it; it should really only do one or the other.
    I have replaced it with another one form stackExchange... is this correct, if not can you post some working code?

  2. #27
    Join Date
    Sep 2017

    Turn Button

    I finally gave up on the integrated Turns system. Too hard to use unless you don't really need it all.

    This code goes in the script of a handy custom tile named "Turn Button". (or whatever else you have around to which you want to attach it, but fix the onLoad code in the global script accordingly...)
    If you want to use a fixed GUID, you can just skip the search, and set turnButton.obj to getObjectFromGUID(yourGUID).
    I spent many hours trying to find a way to make the button insert its GUID into the Global script. I was unsuccessful.

    Then you take the code in the initial comment and paste it into your global script, adjust sizes and shapes to your heart's content.
    If you just want either the big global button or the one in the button itself, just comment out the one you don't want...

    I made a test bed: [url][/url]

        -- turn button
        -- Insert this block of code into your global script:
        turnButton = {
            obj = nil, -- filled in in the onLoad script.  Could just use getObjectFromGUID("constant gid") instead.
            init = function()"initTurns") end, -- initialize the turn system
            start = function()"startTurns") end, -- sets order to getSeatedPlayers and chooses a random first player
            curPlayer = function() return"getCurPlayer") end, -- returns the current player
            setOrder = function(list) turnButton.obj.setTable(order, list) end, -- change the order.  This is an array of player colors.  There are no seating requirements.
            order = function() return turnButton.obj.getTable("order") end, -- returns the current order
            passTurn = function(color)"passTurn", {color = color}) end, -- ends the current player's turn as if the end turn button was pressed.  Useful for AIs
            setTurn = function(color)"setTurn", {color = color}) end, -- sets the current player who must be in the order array.
            previous = function() return"prev") end, -- returns the previous entry in order.
            next = function() return"next") end, -- returns the next entry in order.
            reset = function(stat)"onLoad", stat) end, -- clears all turns status
            toggleVerbose = function()"toggleVerbose") end, -- changes whether the button reports on turn changes.
        function onLoad()
            for _, obj in ipairs(getAllObjects()) do -- find the Turn Button.  
                if obj.getName() == "Turn Button" then
                    turnButton.obj = obj
            if not turnButton.obj then
                print("turnButton not initialized.")
                print("TurnButton " .. turnButton.obj.getGUID() .. " Initialized")
    order = {}
    curIndex = 0 -- control variable, indexed into order for curent player; 0 means turns disabled
    verbose = true -- set false to turn off information messages
    buttonXmlTable = {
        tag = "Button",
        attributes = { id="turnButton",
            width="250", height="120", position="0 0 -11", colors="#cccccc|#dddddd|#444444|#00000000",
            text="Start the Game", fontSize="40", fontStyle="Bold", textColor="Black", onClick = "initTurns",
    globalXmlTable = {
        tag = "Button",
        attributes = { id = "turnButton", position = "-500 500 0", width = "300", height = "50",
            text = "Start the Game", fontSize = "40", textColor = "Black",
            colors="#cccccc|#dddddd|#444444|#00000000", onClick = self.getGUID() .. "initTurns",
    function startTurns(player)
        if toggleVerbose then
            print("Game started by ", player.steam_name)
        order = getSeatedPlayers()
        curIndex = math.random(#order)
        local curPlayer = order[curIndex]
        sayTo(curPlayer, curPlayer .. ", it is your turn.")
        showTurns({color = curPlayer, text = "End " .. curPlayer .. "'s turn"})
    function initTurns(player) -- set up the buttons with "start the game".
        showTurns({color = "Black", text = "Start the game"})
    function showTurns(params)
        -- print("showTurns: ", params.color, " ", params.text)
        local baseUI = Global.UI.getXmlTable()
        local ui = {}
        for i, item in ipairs(baseUI) do
            if ~= "turnButton" then
                table.insert(ui, item)
        buttonXmlTable.attributes.textColor = params.color
        buttonXmlTable.attributes.text = params.text
        globalXmlTable.attributes.textColor = params.color
        globalXmlTable.attributes.text = params.text
        if params.color == "Black" then
            globalXmlTable.attributes.onClick = self.getGUID() .. "/startTurns"
            buttonXmlTable.attributes.onClick = "startTurns"
            globalXmlTable.attributes.onClick = self.getGUID() .. "/endTurn"
            buttonXmlTable.attributes.onClick = "endTurn"
        table.insert(ui, globalXmlTable)
        -- print(Global.UI.getXml())
        ui = {}
        baseUI = self.UI.getXmlTable()
        for i, item in ipairs(baseUI) do
            if ~= "turnButton" then
                table.insert(ui, item)
        table.insert(ui, buttonXmlTable)
        -- print(self.UI.getXml())
    function onLoad(JSONTurnState)
        if JSONTurnState and JSONTurnState ~= "" then
            local turnState = JSON.decode(JSONTurnState)
            -- print(JSONTurnState)
            curIndex = turnState.curIndex
            if curIndex ~= 0 then
                order = turnState.order
                verbose = turnState.verbose or true
                print("The game continues.")
                showTurns({color = order[curIndex], text = "End " .. order[curIndex] .. "'s turn"})
                print("No game")
    function onSave()
        turnState = { curIndex = curIndex, order = order, verbose = verbose }
        return JSON.encode(turnState)
    function sayTo(color, message)
        broadcastToAll(message, stringColorToRGB(color))
    function getCurPlayer()
        return order[curIndex]
    function next()
        local ix = curIndex + 1
        if ix > #order then
            ix = 1
        return order[ix]
    function prev()
        local ix = curIndex - 1
        if ix < 1 then
            ix = #order
        return order[ix]
    end -- of prev
    function passTurn(params)
    function setTurn(params)
        local curPlayer = params.color
        for i, color in ipairs(order) do
            if color == curPlayer then
                sayTo(curPlayer, Player[curPlayer].steam_name .. ", it is your turn.")
                curIndex = i
        print(curPlayer, " is not in the player list (order)")
    function toggleVerbose()
        verbose = not verbose
        return verbose
    function endTurn(player)
        local curPlayer = order[curIndex]
        if player.color ~= curPlayer then
            sayTo(player.color, "cannot end another player's turn (" .. (curPlayer or "nil") .. ")")
        if verbose then
            print("End of ", curPlayer, "'s turn")
        if Global.getVar("onTurnEnd") then
        curIndex = curIndex + 1
        if curIndex > #order then
            curIndex = 1
        curPlayer = order[curIndex]
        if verbose then
            print("Start of " .. curPlayer .. "'s turn.")
        showTurns({color = curPlayer, text = "End " .. curPlayer .. "'s turn"})
        if Global.getVar("onTurnStart") then

  3. #28
    Join Date
    Sep 2017
    While this seems to work ok, I have run into severe problems with data consistency between different scripts.
    I am making a variation that has all functions in the global script. This seems to be working better. Will post when testing done.

  4. #29
    Been a while... here is a new script!

    Custom Name and Description based on rotation of object
    ([url=]Original Idea by Mark[/url])

    The custom rotation value system allows you to set your own NAME tooltip very easily. Simply leave your default name space blank and then name your rotations. Now everytime you flip it, it will have the new name. Unfortunately this does not work at the moment for Descriptions as well.

    This is a little hack code that allows this behaviour but it requires the script be placed on all objects. I have no idea how this will affect performance if you have a billion objects with this script.

    **Leave All Rotation name Blank and leave Name and Description of object Blank.**

    The simply copy this code onto your object
    data = {}
        data[1]={n = 'City Garrison', d = ''}
        data[2]={n = 'Ice Catapult', d = 'Attack : 9 (Ice / Cumbersome)\nDefence : 6 (Fortified)\nFame : 7\n\n(Lost Legion)'}
        --data[3]={n='', d=''}
        --data[4]={n='', d=''}
    function onCollisionEnter()
        local face = self.getValue()
    How does it work?

    • What this does is everytime a object collides it will test the Rotation Value. This works on drop and flip and w/e.
    • You set these with the rotations via the "value gizmo"
    • Set your rotations but do not name them. This way they will return the numeric value for the rotation.
    • In the script there is a data variable at the top for easy editing. In my example I have set it up for 2 values (a coin) but it should work for any amount like say a 12 sided die. Just follow the template. Use LUA string stuff to add line breaks like in my example.
    • On collision it finds the current rotation's numeric value and then uses that as a key to find the correct data
    • Then it just assigns that data to the name and description
    Last edited by Tragic; 07-09-2019 at 03:18 AM.

  5. #30
    HandPosition Error (Work Around)

    As any TTS modder knows there is a annoying bug that is there but kind of trivial so it gets passed over for more important things in the dev cycle. I'm talking about, of course, the hand zones kind of "dropping" downward. So if you put a card in the handzone it falls under the default tables. I have no idea why this happens, but it does ALL the time. It is super anoying, as you constantly have to adjust the Y postion of the hands.

    No longer!

    Here is a small hack that can fix this up for you. Currently this particular code dose not handle multible hand zone, but that is just as I did not need this functionality when I wrote the hack. It would be easy to adjust it for multipule hand zones per colour, and even hand zones of diffrent hights.

    The Code!
    function onLoad()
    function FixHandZones()
        local Y = 3.91
        local playerList = Player.getAvailableColors()
        for _, colour in ipairs(playerList) do
            local pramsOLD = Player[colour].getHandTransform()
            pramsNew = {position={pramsOLD.position.x, Y, pramsOLD.position.z}
                       ,scale={15.50, 5.40, 0.82}
            Player[colour].setHandTransform(pramsNew, 1)
    How does this work

    Place this code inside the GOLBAL script of your mod and call in in your onLoad(), you can place it in any onLoad really, I actualy like using global control objects to store variables and functions nowadays. Anyway, by having it in GLOBAL onLoad() the function is called every time the mod is loaded. What it does is simply look through the avaliable player hands and adjust the Y height.

    All you need to do is paste this into your code and then changed the 'Y' variable to your desiered height.

    You can change the numeric value in setHandTransform() to some kind of variable and use if statments and stuff to make this code more complex so it can handle multipul hand zones and heights.

    Hope this helps!!

  6. #31
    SetUp Scripts

    Much of the current scripting in TTS mods is to speed up setup.. placing components and all that. This is particularly true for large expansion games. Most of my modding is around setup scripts and I thought I would share some of my code snips!

    Have Fun!

    Dynamic Setup Bags

    One of this issues with SetupScripts if coding all the GUIDs for all your components and bags and stuff. What a pain. Also if you change anything and a new GUID is loaded, it all breaks. I get around this by using a SetUPZone.. I usually put it under the table away form the sight of the players. What you do is then put anything you want in that scriptzone. Bags, Individual Tokens.. what'evs. I like to use bags or infinite bags. Then all you need to do is name them all uniquely.

    function onLoad()
    function SetGlobalVariables()
        SetUpScriptZone = getObjectFromGUID('9e3779').getObjects()
    function returnSetUpObj(d)
        for _, o in pairs(SetUpScriptZone) do
            if o.getName() == d then
                return o
    Here is an example of how I use this code... basically what I like to do is have a series of function in OnLoad inside GLOBAL. In it I do things like my FixHandZones() or MegaFreeze() functions.. but also I set any global variables I want to use as well. Global runs OnLoad after everything loads in.. so it is the perfect place to put sutff as you are sure to have it called after all objects are done loading.

    The actual meat of this code is the function returnSetUpObj(d). This is what we will be using. Here is an actual code snip form my new Arkham Horror mod I am working on..

    function onLoad(saved_data)
    function setSources()
        CommonBag ='returnSetUpObj', 'Gator Common Componants')
        NoInteractBag ='returnSetUpObj', 'Gator Non-Interactable Componants')
        StaminaBag ='returnSetUpObj', 'Stamina Markers')
        SanityBag ='returnSetUpObj', 'Sanity Markers')
        ClueBag ='returnSetUpObj', 'Clue Markers')
        MoneyBag ='returnSetUpObj', 'Money Markers')
        SkillsBag ='returnSetUpObj', 'Skill Markers')
        DieRollerBagLeft ='returnSetUpObj', 'Die Rollers (Left)')
        DieRollerBagRight ='returnSetUpObj', 'Die Rollers (Right)')
    This is a function I put in called setSources(), again I like to pull it out into a function.. it is placed in Onload... what this is doing is pretty simple. I am making a l variable inside the script, than calling the function returnSetUpObj(d) and sending it the name of the bag I want to use.

    And that is it! All I need to do now is in my setUPScripts use those bags... CommonBag ..takeObject({}) or w/e

    So the point here is that this is dynamic. I can simply drop anything into that zone and it is accessible, I can change things easily. I can set up the zone in a easy to access place during creation of the mod and then just mass move it to hide it after. I find it a great way of handling this stuff.

    In addition you can add the same script zone to your Interactive Code (I call it Mega Freeze, I should probably update my MegaFreeze code in this thread) to make all the items non-interactive for release pretty easy.

        for _, o in pairs(SetUpScriptZone) do
                o.interactable = false
    Setup Positions

    This is what I get asked the most.. how do you get everything to be placed exactly in the correct spot.. well it is actually super easy when you think in world coordinates. TTS like most 3D systems has a 0,0,0 world space coordinate, and it is pretty trivial to use that to easily make everything spawn at the correct spot. I use this code ALL the time for player areas, where you want say a card to be drawn to a certain location, or tokens on setup to go into a certain place, but then that same board could be anywhere on the table.

    Basically you first want to center your object to {0,0,0}.. so for example, if I wanted to put my tokens onto a playerboard during setup, I would simply make a temporary file and put that board at {0,?,0}. Usually I would take note of the Y value in my actual mod, as this can change... what you are trying to do here is have your player board centered at {0,0,0}.

    Then all you need to do place all your components on the board and record their positions. To do this just palce them were you want, then use the move tool and copy the data it shows you... an example of how I do this would be...

    z = {}
    z['Money Dispenser'] = {p={-11.89, 1.15, 6.77}, r={0, 180, 0}, s={0.3, 0.3, 0.3}}
    I have simply made a table, and used the NAME of the object I want to move as the Key and then copied the position, scale and rotation vales into it.

    Now I have all the information I need. Because the PlayerBoard is at {0,0,0} these values are actually how you would modify the boards dynamic position... For example... to place this Money Dispenser correctly on the board, all I need to do is this...

    local pos = playerboard.getPosition()
    pos.x = pos.x + z['Money Dispenser'].p[1]
    pos.y = pos.y + z['Money Dispenser'].p[2]
    pos.z = pos.z + z['Money Dispenser'].p[3]
    Now.. pos is the exact world space needed to place the token in the exact spot you wanted. So the setPostion() now places it correctly.

    Some example Code

    function setPrams(data, guid)
        local p = {}
        p.position = {pBoard.getPosition().x + data.p[1],
                      pBoard.getPosition().z + data.p[3]}
        p.rotation = data.r
        p.scale = data.s
        if guid ~= nil then p.guid = guid end
        return p
    This is a example code I am actually using in my current mod. This is a small bit of code that takes in table "z['Money Dispenser'] = {p={-11.89, 1.15, 6.77}, r={0, 180, 0}, s={0.3, 0.3, 0.3}}", then uses it to create the corrected positional data. The code also allows you to send guids as well if you wish.

    You use it like this...

    ocal prams = setPrams(PositionData['Money Dispenser'])
    --OR Something like this
    (you need to either have your playerbaord as a variable accessible, or you need to pass it ot the setPrams thing)

    Setup Stuff - Cloned bags and Infinite bags

    What I like to do is use the CLONE tool during my setups. This allows me to easily just copy stuff, rather than have separate things. For example if I have possible 10 players, I do not need 10 different bags, one for each player in the setUP zone.. I can simply have a single bag called something like "SetUP_CommonStuff" that I can clone ten times and give to every player.

    Here is the actual code from my current mod that places tokens from a common bag like I just spoke of...

    (OldBook is my player board Object)
    function setup_CommonBag()
        local ClonedBag = CommonBag.clone()
        for _, obj in pairs(ClonedBag.getObjects()) do
            for k, v in pairs(PositionData) do
                if == k then
                    local prams = setPrams(PositionData[k], obj.guid)
                    local o = ClonedBag.takeObject(prams)
    function PosAbove(OldBook)
        p = {OldBook.getPosition().x, 8, OldBook.getPosition().z}
        return p
    • So I have a function I call with setup_CommonBag()
    • It clones the bag in the first line, the bag found and set by the "dynamic setup bag" code at the top of the page.
    • I then have a small bit of code that puts the cloned bag above the player board it is sending items to. This way when they "move" to the correct spot they sorta fly down form above the player board to the correct spot.
    • I then loop through the cloned bag's contents
    • I then also loop through my position data variables which is a big string of these things... "z['Money Dispenser'] = {p={-11.89, 1.15, 6.77}, r={0, 180, 0}, s={0.3, 0.3, 0.3}}"
    • Then any items in the bag that match the KEY of the position data, in this case "Money Dispenser" is found it dose stuff.
    • It sets the correct position prams as I spoke of above, including the GUID
    • It then takes the object from the ClonedBag using those prams
    • Once you have the object itself out of the bag, you can scale it as well, rename it, lock it, set it intractable = false.. whatever
    • Then right at the end it now destroys the cloned bag completely.
    • this means that even though we have taken items and placed them, the "source bag" left untouched and can be used again by another playerboard during setup.

    An infinate bag is even easier as you do not need to clone it at all..
    function spawnSanity(num)
        local prams = setPrams(PositionData['Sanity'])
        local c = SanityBag.takeObject(prams)
        c.interactable = false

    This is probably my longest post in this thread.. hope it may be helpful to some people!

    Have Fun and ROLL HIGH

    Example - [url][/url]

  7. #32
    How To Perform Operations On A Select Set Of Objects:

    In my RPG Framework Workshop, I found that I need to perform an operation on a large set of objects but not all. For example, when loading the next section of the dungeon, I want to remove all contents of the current dungeon but not any of the framework objects.

    One possible way to achieve this is to store the object "category" in either the description or a Global var. For example, when I load my Framework without any dungeon content, I run a script to set all the objects' Descriptions to "Framework". Then when I load the dungeon content, I run a similar script that sets the Description of any objects, which don't have a Description, to "Content". Now if I want to delete all dungeon content, I can loop through all the objects and look at the Description of the object. If it is "Content", I delete it. If not, I keep it. Obviously this concept can be extended to any number of categories and is not limited to delete actions.

  8. #33
    Been a while... here is a new script.. TIP!

    How to perfectly time card drops? (Method 1)

    My main scripting is setup and then doing repetitive things, like clean up or deck resets or w/e.

    One of the big problems I have found is that computers run at different speeds. So say I have a scrip that discard a card and then shuffles the deck, if I wait for 2 seconds for it to fly across the table, on some systems that will be way to long and on others it will be way to short... I have two tricks to get around that... this is the first!

    How it works

    • There is a function in the API called OnDestroy() and onObjectDestroy(dying_object). These basically call a function as the object is destroyed. There is some timing that you may need to consider talked about in the API, but for most needs you use these codes and can call a function as a object is destroyed.
    • OnDestroy() is placed on a individual object and is just for that one obejct
    • onObjectDestroy(dying_object) is a global event that triggers when ANY object is destroyed. Much like the enter or leave script zone.
    • When a card enters a deck or an object enters a bag it is considered destroyed.
    • So all you need to do is add a function in the object destroy to do something as the card enters the deck

    A Method I like to use

    I like to use the, Table) to call a function on another object.. something like getObjectFromGUID('814513').call('ReShuffle').

    That is about it!

    So yeah.. not a lot of code here.. but this 1st method is a easy way to make perfect timing for things as the scipts activate based on events, rather than timing frames or seconds.

    EDIT : Oh yeah.. and you can get very simular effects by using onCollisionEnter(collision_info) as well.
    Last edited by Tragic; 12-17-2019 at 03:07 PM.

  9. #34
    Auto-shuffle Bags as things drop into them?

    Often during my setup scripts I need to shuffle a bag after dropping a ton of components into it. So what I want is a autoshuffle of some kind. Here are TWO ways to do it.. a easy and a slightly more complex!

    Method One : A Simple AutoShuffle on Component Entrance

    function onCollisionEnter(info)
        if info.collision_object.getName() == "ComponantName" then
    This is the simple method. All it does is shuffle the bag every time the correct component is dropped into it. You can test for any object tribute form Name or Description or texture or whatever. It is important to do the test as this will stop the autoshuffle happening on game load, as many games require a static component stack once the game is running. Otherwise as the game loads it will "collide" with what it is sitting on and trigger the shuffle. It also allows you to easily pull something out if ou acidently drop the wrong thing into the bag.

    This method works for many situations and is super easy to set up.

    Method Two : A Delayed AutoShuffle on Component Entrance

    function onCollisionEnter(info)
        if info.collision_object.getName() == "ComponantName" then
    function TimmerShuffle()
            identifier="Time_dShuffle"..self.getGUID(), delay=1,
            function_name="Delay_Shuffle", function_owner=self, --parameters = prams
    function Delay_Shuffle()
    function onDestroy()
    This is a slightly more complex method, but all you need to do is copy paste this into the bag, no editing required.

    What this does is use a timer to delay the shuffle until everything has fallen into the bag. The reason you would want to use this version is if during setup you are dropping 100s of components into many bags at once. The "Method One" code shuffles every single time something is dropped in, as soon as it is dropped in. This can cause ugly stuttering and slow down during setup scripts, particularly on slower computers. For example in one of my mods during setup 10 bags get filled, each with optional components that can be as high as 60 per bag. Shuffling 600 times super fast can make the screen freeze for a second during setup on slower computers and can break any wait code you have to do other setup functions.

    So what this dose is simply wait 1 second. If nothing else is dropped in during this time, it shuffles.

  10. #35
    Improved MegaFreeze (make Objects non-Intractable)

    One of the first scripts I posted into this thread was called "MegaFreeze". It was a script that you placed in global and simply set groups of objects as non-intractable, based on their GUID. Over time I have modified this script to be more dynamic, so thought I would post a update to it here!

    What is MegaFreeze?

    • MegaFreeze is what I called setting an object to "obj.intractable = false".
    • This means that the mod maker can build custom tables and be assured that no players can unlock them and move them about.
    • This also disables tooltips
    • This dose NOT however stop buttons or XML from functioning on that object.
    • If it is a bag, the players can not drop stuff into it or pull stuff out by acident, but scripting can still do that. This is a great way to have setup bags for your scripts and be assured no one futzzes with them.

    The Code

    Simply copy this and place it into your Global

    function onLoad()
        MegaFreeze() -- Call MegaFreeze - Place it here so you can disable it by just commenting out this alone.
    function MegaFreeze()
        local freezeByZone = {} -- Place GUIDs of script zones here
        local freezeByGUID = {} -- Place GUIDs of individual Objects here
        for _, obj in pairs(getAllObjects()) do
            if      obj.getName() == 'MegaFreeze' then
                    obj.interactable = false
            elseif  obj.getDescription() == 'MegaFreeze' then
                    obj.interactable = false
                for _, guid in pairs(freezeByGUID) do
                    if obj.getGUID() == guid then obj.interactable = false end
         -- Freeze Objects by Zone
        for _, zone in pairs(freezeByZone) do
            for _, obj in pairs(getObjectFromGUID(zone).getObjects()) do
                obj.interactable = false
    How Does it Work?

    Basically with my old MegaFreeze code you had to manually enter every single GUID into the script manually. This code is dynamic, so you can add things to be MegaFrozen without having to edit any code. Though I have kept the freeze by GUID as well, just in case it is needed.

    What is Does
    • Searches entire scene
    • Anything with the name "MegaFreeze" is MegaFrozen
    • Anything with the description "MegaFreeze" is MegaFrozen
    • It then checks to see if any objects are listed in the "freezeByGUID" list, and MegaFreezes them.
    • It then check to see if any Zones are in the freezeByZone, and then finds all the objects in those zones and MegaFreezes them.

    How Does I use it?

    • Just paste this code into your Global Script.
    • Now any object where you set the NAME or DESCRIPTION to "MegaFreeze" will be set non-Intractable onLoad().
    • freezeByGUID and freezeByZone are just lists of GUIDs. Either for Objects or for Script Zones. Just place the GUIDs between quotation marks and separate by a comma.

    The upshot of all this is that you can assign things to be frozen just by renaming them in the scene, no need to edit the code, or you can if you want add individual objects by GUID or add entire scrip zones that will just freeze everything in them.

    A Handy Tool to MegaThaw and MegaFreeze

    When editing and creating your mods you often need to make everything intractable now and then to move things about and other stuff. With the old version you needed to save, disable scripting then reload the mod, change things, enable scripting and then save and reload the mod.

    This handy little tool I made is just a single button. Click it to MegaThaw everything in the scene and click again to MegaFreeze. It dose not edit anything, so no matter what state you save the mod in the set objects will MegaFreeze at launch. Unfortunately you can not post links on this forum, but here is the link below.

    (Tool) - MegaFreeze (On/Off)

    Have fun and ROLL HIGH

  11. #36
    Simple Sounding Function

        function round2(num, numDecimalPlaces)
      return tonumber(string.format("%." .. (numDecimalPlaces or 0) .. "f", num))

    Anyone that has tried to do if obj.getPosition().x == somthing will know that while the tools return 2 decimal places the app reads to many decimal places.. so here is a neat rounding number function you can use.

    Have fun and ROLL HIGH
    Last edited by Tragic; 01-07-2020 at 04:17 PM.

Page 2 of 2 FirstFirst 12

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts