diff --git a/config.json b/config.json index afbade21..c05aa993 100644 --- a/config.json +++ b/config.json @@ -56,7 +56,7 @@ "BlockRectangle.612072", "Cluetokens.11e0cf", "Doomtokens.b015d8", - "AgendaDeck.85c4c6", + "DoomCounter.85c4c6", "Custom_Tile.2eca7c", "Custom_Tile.fb09d4", "3DText.65eb7e", @@ -208,7 +208,7 @@ "ReturntoTheCircleUndone.757324", "Playermat4Red.0840d5", "Playermat3Green.383d8b", - "MiscDoominplay.652ff3", + "OtherDoominPlay.652ff3", "Playermat1White.8b081b", "Playermat2Orange.bd0ff4", "CustomDataHelper.2547b3", diff --git a/modsettings/SnapPoints.json b/modsettings/SnapPoints.json index 80bfe8fc..d7ddb647 100644 --- a/modsettings/SnapPoints.json +++ b/modsettings/SnapPoints.json @@ -20,8 +20,8 @@ }, { "Position": { - "x": -5.316, - "y": 1.588, + "x": -5.3, + "y": 1.583, "z": 0.378 } }, @@ -522,8 +522,8 @@ }, { "Position": { - "x": -5.369, - "y": 1.587, + "x": -5.3, + "y": 1.583, "z": -5.1 } }, @@ -4190,4 +4190,4 @@ "z": 0 } } -] +] \ No newline at end of file diff --git a/objects/AgendaDeck.85c4c6.json b/objects/DoomCounter.85c4c6.json similarity index 79% rename from objects/AgendaDeck.85c4c6.json rename to objects/DoomCounter.85c4c6.json index 773a295b..c472d5d2 100644 --- a/objects/AgendaDeck.85c4c6.json +++ b/objects/DoomCounter.85c4c6.json @@ -33,17 +33,17 @@ "IgnoreFoW": false, "LayoutGroupSortIndex": 0, "Locked": true, - "LuaScript": "require(\"core/AgendaDeck\")", - "LuaScriptState": "0", + "LuaScript": "require(\"core/DoomCounter\")", + "LuaScriptState": "[0,{\"Agenda\":true,\"Playarea\":true,\"Playermats\":true}]", "MeasureMovement": false, "Name": "Custom_Token", - "Nickname": "Agenda Deck", + "Nickname": "Doom Counter", "Snap": true, "Sticky": true, - "Tooltip": false, + "Tooltip": true, "Transform": { - "posX": -5.316, - "posY": 1.639, + "posX": -5.3, + "posY": 1.633, "posZ": 0.378, "rotX": 0, "rotY": 270, @@ -53,5 +53,5 @@ "scaleZ": 0.42 }, "Value": 0, - "XmlUI": "" -} + "XmlUI_path": "DoomCounter.85c4c6.xml" +} \ No newline at end of file diff --git a/objects/DoomCounter.85c4c6.xml b/objects/DoomCounter.85c4c6.xml new file mode 100644 index 00000000..d6bb38f8 --- /dev/null +++ b/objects/DoomCounter.85c4c6.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + Doom on Agenda + Doom in Playarea + Doom on Playermats + + diff --git a/objects/MasterClueCounter.4a3aa4.json b/objects/MasterClueCounter.4a3aa4.json index 4428ffbc..6099abb3 100644 --- a/objects/MasterClueCounter.4a3aa4.json +++ b/objects/MasterClueCounter.4a3aa4.json @@ -34,16 +34,16 @@ "LayoutGroupSortIndex": 0, "Locked": true, "LuaScript": "require(\"core/MasterClueCounter\")", - "LuaScriptState": "[true,0]", + "LuaScriptState": "", "MeasureMovement": false, "Name": "Custom_Token", "Nickname": "Master Clue Counter\n", "Snap": true, "Sticky": true, - "Tooltip": false, + "Tooltip": true, "Transform": { - "posX": -5.369, - "posY": 1.557, + "posX": -5.3, + "posY": 1.633, "posZ": -5.1, "rotX": 0, "rotY": 270, @@ -54,4 +54,4 @@ }, "Value": 0, "XmlUI": "" -} +} \ No newline at end of file diff --git a/objects/MiscDoominplay.652ff3.json b/objects/OtherDoominPlay.652ff3.json similarity index 86% rename from objects/MiscDoominplay.652ff3.json rename to objects/OtherDoominPlay.652ff3.json index cfffcffc..9a8c30a9 100644 --- a/objects/MiscDoominplay.652ff3.json +++ b/objects/OtherDoominPlay.652ff3.json @@ -34,10 +34,10 @@ "LayoutGroupSortIndex": 0, "Locked": true, "LuaScript": "require(\"core/DoomInPlayCounter\")", - "LuaScriptState": "[true,0]", + "LuaScriptState": "", "MeasureMovement": false, "Name": "Custom_Token", - "Nickname": "Misc. Doom in play", + "Nickname": "Other Doom in Play", "Snap": true, "Sticky": true, "Tags": [ @@ -45,16 +45,16 @@ ], "Tooltip": true, "Transform": { - "posX": -6.185, - "posY": 1.56, - "posZ": 1.396, + "posX": -5.3, + "posY": 1.633, + "posZ": 1.8, "rotX": 0, "rotY": 270, "rotZ": 0, - "scaleX": 0.23, + "scaleX": 0.25, "scaleY": 1, - "scaleZ": 0.23 + "scaleZ": 0.25 }, "Value": 0, "XmlUI": "" -} +} \ No newline at end of file diff --git a/src/core/AgendaDeck.ttslua b/src/core/AgendaDeck.ttslua deleted file mode 100644 index 910be946..00000000 --- a/src/core/AgendaDeck.ttslua +++ /dev/null @@ -1,60 +0,0 @@ --- Doom Counter with Print --- original by: - --- changed by: Chr1Z --- description: Clickable counter for doom on the agenda, changing the value prints the new value, reset button added -information = { - version = "1.4", - last_updated = "12.11.2022" -} - -function onSave() return JSON.encode(val) end - -function onLoad(saved_data) - if saved_data ~= "" then - val = JSON.decode(saved_data) - else - val = 0 - end - - self.createButton({ - label = tostring(val), - click_function = "addOrSubtract", - function_owner = self, - position = { 0, 0.06, 0 }, - height = 800, - width = 800, - font_size = 650, - scale = { 1.5, 1.5, 1.5 }, - font_color = { 1, 1, 1, 95 }, - color = { 0, 0, 0, 0 } - }) - - self.createButton({ - label = "Reset", - click_function = "setToZero", - function_owner = self, - position = { 0, -0.04, 2.7 }, - height = 600, - width = 1250, - font_size = 425 - }) - - self.addContextMenuItem("More Information", function() - printToAll("------------------------------", "White") - printToAll("Doom Counter v" .. information["version"] .. " by Chr1Z", "Orange") - printToAll("last updated: " .. information["last_updated"], "White") - end) -end - -function setToZero() updateVal(0) end - -function addOrSubtract(_, _, alt_click) - local new_value = math.min(math.max(val + (alt_click and -1 or 1), 0), 99) - if val ~= new_value then updateVal(new_value) end -end - -function updateVal(number) - val = number or 0 - self.editButton({ index = 0, label = tostring(val) }) - printToAll("Doom on agenda set to: " .. val) -end diff --git a/src/core/DoomCounter.ttslua b/src/core/DoomCounter.ttslua new file mode 100644 index 00000000..553bafbb --- /dev/null +++ b/src/core/DoomCounter.ttslua @@ -0,0 +1,75 @@ +local optionsVisible = false +local options = { + Agenda = true, + Playarea = true, + Playermats = true +} + +val = 0 + +-- save current value and options +function onSave() return JSON.encode({ val, options }) end + +function onLoad(savedData) + if savedData ~= "" then + local loadedData = JSON.decode(savedData) + val = loadedData[1] + options = loadedData[2] + + -- restore state for option panel + for key, bool in pairs(options) do + if bool then + self.UI.setAttribute("option" .. key, "isOn", 0) + end + end + end + + self.createButton({ + label = tostring(val), + click_function = "addOrSubtract", + function_owner = self, + position = { 0, 0.06, 0 }, + height = 800, + width = 800, + font_size = 650, + scale = { 1.5, 1.5, 1.5 }, + font_color = { 1, 1, 1, 95 }, + color = { 0, 0, 0, 0 } + }) +end + +-- called by the invisible button to change displayed value +function addOrSubtract(_, _, isRightClick) + local newVal = math.min(math.max(val + (isRightClick and -1 or 1), 0), 99) + if val ~= newVal then updateVal(newVal) end +end + +function updateVal(number) + val = number or 0 + self.editButton({ index = 0, label = tostring(val) }) + printToAll("Doom on agenda set to: " .. val) +end + +-- called by "Reset" button to remove doom +function startReset() + if options.Agenda then + updateVal(0) + end + getObjectFromGUID("652ff3").call("removeDoom", options) +end + +-- XML UI functions +function optionClick(_, optionName) + options[optionName] = not options[optionName] + printToAll("Doom removal of " .. optionName .. (options[optionName] and " enabled" or " disabled")) +end + +function toggleOptions() + optionsVisible = not optionsVisible + + if optionsVisible then + self.UI.show("Options") + else + self.UI.hide("Options") + end +end diff --git a/src/core/DoomInPlayCounter.ttslua b/src/core/DoomInPlayCounter.ttslua index 7260e959..d0509a9a 100644 --- a/src/core/DoomInPlayCounter.ttslua +++ b/src/core/DoomInPlayCounter.ttslua @@ -1,104 +1,106 @@ --- Doom-in-Play Counter --- made by: Chr1Z --- description: counts the doom tokens in play periodically (excluding the agenda), ignores objects with specified tag -information = { - version = "1.1", - last_updated = "12.11.2022" -} - -- common parameters local castParameters = {} castParameters.direction = { 0, 1, 0 } castParameters.type = 3 castParameters.max_distance = 0 -local zone = getObjectFromGUID("a2f932") -local doom_url = "https://i.imgur.com/EoL7yaZ.png" +local zone +local doomURL = "https://i.imgur.com/EoL7yaZ.png" local IGNORE_TAG = "DoomCounter_ignore" -- playermats 1 to 4 local originAndSize = { - { origin = { -55, 1.6, 16.5 }, size = { 12, 1, 25 } }, - { origin = { -55, 1.6, -16.5 }, size = { 12, 1, 25 } }, - { origin = { -25, 1.6, 27 }, size = { 25, 1, 12 } }, - { origin = { -25, 1.6, -27 }, size = { 25, 1, 12 } } + { origin = { -55, 1.6, 16.5 }, size = { 12, 1, 25 } }, + { origin = { -55, 1.6, -16.5 }, size = { 12, 1, 25 } }, + { origin = { -25, 1.6, 27 }, size = { 25, 1, 12 } }, + { origin = { -25, 1.6, -27 }, size = { 25, 1, 12 } } } -- create button, context menu and start loop function onLoad() - self.createButton({ - label = tostring(0), - click_function = "moreInformation", - function_owner = self, - position = { 0, 0.06, 0 }, - height = 600, - width = 1000, - scale = { 1.5, 1.5, 1.5 }, - font_size = 600, - font_color = { 1, 1, 1, 100 }, - color = { 0, 0, 0, 0 } - }) + self.createButton({ + label = tostring(0), + click_function = "none", + function_owner = self, + position = { 0, 0.06, 0 }, + height = 0, + width = 0, + scale = { 1.5, 1.5, 1.5 }, + font_size = 600, + font_color = { 1, 1, 1, 100 }, + color = { 0, 0, 0, 0 } + }) - -- context menu - self.addContextMenuItem("More Information", moreInformation) - self.addContextMenuItem("Remove Doom", function() - Wait.stop(loopID) - removeDoom = true - countDoom() - Wait.time(function() - removeDoom = false - loopID = Wait.time(countDoom, 2, -1) - end, 2) - end) - - loopID = Wait.time(countDoom, 2, -1) -end - -function moreInformation() - printToAll("------------------------------", "White") - printToAll("Doom-in-Play Counter v" .. information["version"] .. " by Chr1Z", "Orange") - printToAll("last updated: " .. information["last_updated"], "White") - printToAll("Automatically counts the doom in play (exluding the agenda and objects with the ignore tag).", "Green") - printToAll("ignore tag: " .. IGNORE_TAG, "White") + zone = getObjectFromGUID("a2f932") + loopID = Wait.time(countDoom, 2, -1) end -- main function function countDoom() - local doom = 0 - for i = 1, 5 do doom = doom + search(i) end - self.editButton({ index = 0, label = tostring(doom) }) + local doom = 0 + for i = 1, 5 do doom = doom + search(i) end + self.editButton({ index = 0, label = tostring(doom) }) end -- searches playermats (num = 1-4) or the scripting zone (num = 5) function search(num) - local val = 0 - if num == 5 then - for _, obj in ipairs(zone.getObjects()) do - val = val + isDoom(obj) - end - else - castParameters.origin = originAndSize[num].origin - castParameters.size = originAndSize[num].size - - for _, obj in ipairs(Physics.cast(castParameters)) do - val = val + isDoom(obj.hit_object) - end + local val = 0 + if num == 5 then + for _, obj in ipairs(zone.getObjects()) do + val = val + isDoom(obj) end - return val + else + castParameters.origin = originAndSize[num].origin + castParameters.size = originAndSize[num].size + + for _, obj in ipairs(Physics.cast(castParameters)) do + val = val + isDoom(obj.hit_object) + end + end + return val end -- checks an object for the doom image and gets quantity (for stacks) function isDoom(obj) - if (obj.is_face_down and obj.getCustomObject().image_bottom == doom_url) or - (obj.name == "Custom_Token" and obj.getCustomObject().image == doom_url) then - if not obj.hasTag(IGNORE_TAG) then - if removeDoom then - obj.destruct() - return 0 - else - return math.abs(obj.getQuantity()) - end - end + if (obj.is_face_down and obj.getCustomObject().image_bottom == doomURL) or + (obj.name == "Custom_Token" and obj.getCustomObject().image == doomURL) then + if not obj.hasTag(IGNORE_TAG) then + return math.abs(obj.getQuantity()) end - return 0 + end + return 0 +end + +-- removes doom from playermats / playarea +function removeDoom(options) + local trashCan = getObjectFromGUID("70b9f6") + local count = 0 + if options.Playermats then + for i = 1, 4 do + castParameters.origin = originAndSize[i].origin + castParameters.size = originAndSize[i].size + + for _, obj in ipairs(Physics.cast(castParameters)) do + local obj = obj.hit_object + local amount = isDoom(obj) + if amount > 0 then + trashCan.putObject(obj) + count = count + amount + end + end + end + broadcastToAll(count .. " doom removed from Playermats.", "White") + end + + local count = 0 + if options.Playarea then + for _, obj in ipairs(zone.getObjects()) do + local amount = isDoom(obj) + if amount > 0 then + trashCan.putObject(obj) + count = count + amount + end + end + broadcastToAll(count .. " doom removed from Playarea.", "White") + end end diff --git a/src/core/MasterClueCounter.ttslua b/src/core/MasterClueCounter.ttslua index efbb38cc..1cc0b4da 100644 --- a/src/core/MasterClueCounter.ttslua +++ b/src/core/MasterClueCounter.ttslua @@ -1,161 +1,45 @@ -MIN_VALUE = -99 -MAX_VALUE = 999 +local clueCounters = {} +local clueCounterGUIDS = { + "37be78", + "1769ed", + "032300", + "d86b7c" +} -function onload(saved_data) - light_mode = false - val = 0 +function onLoad() + self.createButton({ + label = "0", + click_function = "removeAllPlayerClues", + function_owner = self, + position = { 0, 0.06, 0 }, + height = 900, + width = 900, + scale = { 1.5, 1.5, 1.5 }, + font_size = 600, + font_color = { 1, 1, 1, 100 }, + color = { 0, 0, 0, 0 } + }) - if saved_data ~= "" then - local loaded_data = JSON.decode(saved_data) - light_mode = loaded_data[1] - val = loaded_data[2] - end - p1ClueCounter = getObjectFromGUID("37be78") - p2ClueCounter = getObjectFromGUID("1769ed") - p3ClueCounter = getObjectFromGUID("032300") - p4ClueCounter = getObjectFromGUID("d86b7c") + -- loading object references to the counting bowls via GUID + for i = 1, 4 do + clueCounters[i] = getObjectFromGUID(clueCounterGUIDS[i]) + end - timerID = self.getGUID()..math.random(9999999999999) - Timer.create({ - identifier=timerID, - function_name="totalCounters", function_owner=self, - repetitions=0, delay=1 - }) - createAll() -end - -function loadPlayerCounters() - p1ClueCounter = getObjectFromGUID("37be78") - p2ClueCounter = getObjectFromGUID("1769ed") - p3ClueCounter = getObjectFromGUID("032300") - p4ClueCounter = getObjectFromGUID("d86b7c") -end - - -function totalCounters() - if p1ClueCounter == nil or p2ClueCounter == nil or p3ClueCounter == nil or p4ClueCounter == nil then - loadPlayerCounters() - end - local p1ClueCount = p1ClueCounter.getVar("exposedValue") - local p2ClueCount = p2ClueCounter.getVar("exposedValue") - local p3ClueCount = p3ClueCounter.getVar("exposedValue") - local p4ClueCount = p4ClueCounter.getVar("exposedValue") - val = tonumber(p1ClueCount) + tonumber(p2ClueCount) + tonumber(p3ClueCount) + tonumber(p4ClueCount) - updateVal() - updateSave() -end - -function updateSave() - local data_to_save = {light_mode, val} - saved_data = JSON.encode(data_to_save) - self.script_state = saved_data -end - -function createAll() - s_color = {0.5, 0.5, 0.5, 95} - - if light_mode then - f_color = {1,1,1,95} - else - f_color = {0,0,0,100} - end - - self.createButton({ - label=tostring(val), - click_function="removeAllPlayerClues", - function_owner=self, - position={0,0.05,0}, - height=600, - width=1000, - alignment = 3, - tooltip = "Click button to remove all clues from all investigators", - scale={x=1.5, y=1.5, z=1.5}, - font_size=600, - font_color=f_color, - color={0,0,0,0} - }) - - if light_mode then - lightButtonText = "[ Set dark ]" - else - lightButtonText = "[ Set light ]" - end - -end - -function removeAll() - self.removeInput(0) - self.removeInput(1) - self.removeButton(0) - self.removeButton(1) - self.removeButton(2) + loopID = Wait.time(sumClues, 2, -1) end +-- removes all player clues by calling the respective function from the counting bowls function removeAllPlayerClues() - p1ClueCounter.call("removeAllClues") - p2ClueCounter.call("removeAllClues") - p3ClueCounter.call("removeAllClues") - p4ClueCounter.call("removeAllClues") -end - - -function reloadAll() - removeAll() - createAll() - updateSave() -end - -function swap_fcolor(_obj, _color, alt_click) - light_mode = not light_mode - reloadAll() -end - -function swap_align(_obj, _color, alt_click) - center_mode = not center_mode - reloadAll() -end - -function editName(_obj, _string, value) - self.setName(value) - setTooltips() -end - -function updateVal() - self.editButton({ - index = 0, - label = tostring(val), - - }) -end - -function reset_val() - val = 0 - updateVal() - updateSave() -end - -function setTooltips() - self.editInput({ - index = 0, - value = self.getName(), - tooltip = "Click button to remove all clues from all investigators" - }) - self.editButton({ - index = 0, - value = tostring(val), - - }) -end - -function null() -end - -function keepSample(_obj, _string, value) - reloadAll() -end - -function onDestroy() - if timerID and type(timerID) == 'object' then - Timer.destroy(timerID) + for i = 1, 4 do + clueCounters[i].call("removeAllClues") end end + +-- gets the counted values from the counting bowls and sums them up +function sumClues() + local count = 0 + for i = 1, 4 do + count = count + tonumber(clueCounters[i].getVar("exposedValue")) + end + self.editButton({ index = 0, label = tostring(count) }) +end diff --git a/src/playermat/ClueCounter.ttslua b/src/playermat/ClueCounter.ttslua index 08a1942f..d2bf81cd 100644 --- a/src/playermat/ClueCounter.ttslua +++ b/src/playermat/ClueCounter.ttslua @@ -1,91 +1,69 @@ ---Counting Bowl by MrStump - ---Table of items which can be counted in this Bowl ---Each entry has 2 things to enter - --a name (what is in the name field of that object) - --a value (how much it is worth) ---A number in the items description will override the number entry in this table -validCountItemList = { - ["Clue"] = 1, - [""] = 1, - --["Name3"] = 2, - --["Name4"] = 31, - --Add more entries as needed - --Remove the -- from before a line for the script to use it +-- Table of items which can be counted in this Bowl +-- Each entry has 2 things to enter +-- a name (what is in the name field of that object) +-- a value (how much it is worth) +-- a number in the items description will override the number entry in this table +local validCountItemList = { + ["Clue"] = 1, + [""] = 1 } - ---END OF CODE TO EDIT +local trashGUID = "70b9f6" +exposedValue = 0 function onLoad() - timerID = self.getGUID()..math.random(9999999999999) - --Sets position/color for the button, spawns it - self.createButton({ - label="", click_function="removeAllClues", function_owner=self, - position={0,0,0}, rotation={0,8,0}, height=0, width=0, - font_color={0,0,0}, font_size=2000 - }) - --Start timer which repeats forever, running countItems() every second - Timer.create({ - identifier=timerID, - function_name="countItems", function_owner=self, - repetitions=0, delay=1 - }) - exposedValue = 0 - trashCan = getObjectFromGUID("147e80") + self.createButton({ + label = "", + click_function = "removeAllClues", + function_owner = self, + height = 0, + width = 0, + font_color = { 0, 0, 0 }, + font_size = 2000 + }) + loopID = Wait.time(countItems, 1, -1) +end + +-- Activated once per second, counts items in bowls +function countItems() + local totalValue = -1 + local countableItems = findValidItemsInSphere() + for _, entry in ipairs(countableItems) do + local descValue = tonumber(entry.hit_object.getDescription()) + local stackMult = math.abs(entry.hit_object.getQuantity()) + -- Use value in description if available + if descValue ~= nil then + totalValue = totalValue + descValue * stackMult + else + -- Otherwise use the value in validCountItemList + totalValue = totalValue + validCountItemList[entry.hit_object.getName()] * stackMult + end + end + exposedValue = totalValue + self.editButton({ index = 0, label = totalValue }) end function findValidItemsInSphere() - return filterByValidity(findItemsInSphere()) -end + local items = Physics.cast({ + origin = self.getPosition(), + direction = { 0, 1, 0 }, + type = 2, + max_distance = 0, + size = { 2, 2, 2 }, + --debug=true + }) ---Activated once per second, counts items in bowls -function countItems() - local totalValue = -1 - local countableItems = findValidItemsInSphere() - for ind, entry in ipairs(countableItems) do - local descValue = tonumber(entry.hit_object.getDescription()) - local stackMult = math.abs(entry.hit_object.getQuantity()) - --Use value in description if available - if descValue ~= nil then - totalValue = totalValue + descValue * stackMult - else - --Otherwise use the value in validCountItemList - totalValue = totalValue + validCountItemList[entry.hit_object.getName()] * stackMult - end + retval = {} + for _, entry in ipairs(items) do + --Ignore the bowl + if entry.hit_object ~= self then + --Ignore if not in validCountItemList + local tableEntry = validCountItemList[entry.hit_object.getName()] + if tableEntry ~= nil then + table.insert(retval, entry) + end end - exposedValue = totalValue - --Updates the number display - self.editButton({index=0, label=totalValue}) -end - -function filterByValidity(items) - retval = {} - for _, entry in ipairs(items) do - --Ignore the bowl - if entry.hit_object ~= self then - --Ignore if not in validCountItemList - local tableEntry = validCountItemList[entry.hit_object.getName()] - if tableEntry ~= nil then - table.insert(retval, entry) - end - end - end - return retval -end - - ---Gets the items in the bowl for countItems to count -function findItemsInSphere() - --Find scaling factor - local scale = self.getScale() - --Set position for the sphere - local pos = self.getPosition() - pos.y=pos.y+(1.25*scale.y) - --Ray trace to get all objects - return Physics.cast({ - origin=pos, direction={0,1,0}, type=2, max_distance=0, - size={6*scale.x,6*scale.y,6*scale.z}, --debug=true - }) + end + return retval end function removeAllClues() @@ -96,19 +74,12 @@ function clueRemovalCoroutine() for _, entry in ipairs(findValidItemsInSphere()) do -- Do not put the table in the garbage if entry.hit_object.getGUID() ~= "4ee1f2" then - --delay for animation purposes - for k=1,10 do + -- delay for animation purposes + for k = 1, 10 do coroutine.yield(0) end - trashCan.putObject(entry.hit_object) + getObjectFromGUID(trashGUID).putObject(entry.hit_object) end end - --coroutines must return a value return 1 end - -function onDestroy() - if timerID and type(timerID) == 'object' then - Timer.destroy(timerID) - end -end