-- Bundled by luabundle {"version":"1.6.0"} local __bundle_require, __bundle_loaded, __bundle_register, __bundle_modules = (function(superRequire) local loadingPlaceholder = {[{}] = true} local register local modules = {} local require local loaded = {} register = function(name, body) if not modules[name] then modules[name] = body end end require = function(name) local loadedModule = loaded[name] if loadedModule then if loadedModule == loadingPlaceholder then return nil end else if not modules[name] then if not superRequire then local identifier = type(name) == 'string' and '\"' .. name .. '\"' or tostring(name) error('Tried to require ' .. identifier .. ', but no such module has been registered') else return superRequire(name) end end loaded[name] = loadingPlaceholder loadedModule = modules[name](require, loaded, register, modules) loaded[name] = loadedModule end return loadedModule end return require, loaded, register, modules end)(nil) __bundle_register("__root", function(require, _LOADED, __bundle_register, __bundle_modules) require("chaosbag/BlessCurseManager") end) __bundle_register("chaosbag/BlessCurseManager", function(require, _LOADED, __bundle_register, __bundle_modules) local tokenArrangerApi = require("accessories/TokenArrangerApi") -- common button parameters local buttonParamaters = {} buttonParamaters.function_owner = self buttonParamaters.color = { 0, 0, 0, 0 } buttonParamaters.width = 700 buttonParamaters.height = 700 local altState = false local MODE = { [false] = "Add / Remove", [true] = "Take / Return" } local BUTTON_COLOR = { [false] = { 0.4, 0.4, 0.4 }, [true] = { 0.9, 0.9, 0.9 } } local FONT_COLOR = { [false] = { 1, 1, 1 }, [true] = { 0, 0, 0 } } local whitespace = " " local updating --------------------------------------------------------- -- creating buttons and menus + initializing tables --------------------------------------------------------- function onSave() return JSON.encode(altState) end function onLoad(saved_state) if saved_state ~= nil then altState = JSON.decode(saved_state) end -- index: 0 - bless buttonParamaters.click_function = "clickBless" buttonParamaters.position = { -1.03, 0.05, 0.46 } self.createButton(buttonParamaters) -- index: 1 - curse buttonParamaters.click_function = "clickCurse" buttonParamaters.position[1] = -buttonParamaters.position[1] self.createButton(buttonParamaters) -- index: 2 - alternative mode (take / return) buttonParamaters.click_function = "enableAlt" buttonParamaters.width = 900 buttonParamaters.height = 210 buttonParamaters.position = { -1.03, 0.05, -0.85 } self.createButton(buttonParamaters) -- index: 3 - default mode (add / remove) buttonParamaters.click_function = "enableDefault" buttonParamaters.position[1] = -buttonParamaters.position[1] self.createButton(buttonParamaters) -- load labels, tooltips and colors updateButtons() -- context menu self.addContextMenuItem("Remove all", doRemove) self.addContextMenuItem("Reset", doReset) -- initializing tables numInPlay = { Bless = 0, Curse = 0 } tokensTaken = { Bless = {}, Curse = {} } sealedTokens = {} Wait.time(initializeState, 1) end function initializeState() -- count tokens in the bag local chaosbag = Global.call("findChaosBag") local tokens = {} for _, v in ipairs(chaosbag.getObjects()) do if v.name == "Bless" then numInPlay.Bless = numInPlay.Bless + 1 elseif v.name == "Curse" then numInPlay.Curse = numInPlay.Curse + 1 end end -- find tokens in the play area for _, obj in ipairs(getObjects()) do local pos = obj.getPosition() if pos.x > -50 and pos.x < 50 and pos.z > 8 and pos.z < 50 then if obj.getName() == "Bless" then table.insert(tokensTaken.Bless, obj.getGUID()) numInPlay.Bless = numInPlay.Bless + 1 elseif obj.getName() == "Curse" then table.insert(tokensTaken.Curse, obj.getGUID()) numInPlay.Curse = numInPlay.Curse + 1 end end end broadcastCount("Curse") broadcastCount("Bless") end function broadcastCount(token) local count = formatTokenCount(token) if count == "(0/0)" then return end broadcastToAll(token .. " Tokens " .. count, "White") end function printStatus(color) broadcastToColor("Curse Tokens " .. formatTokenCount("Curse"), color, "White") broadcastToColor("Bless Tokens " .. formatTokenCount("Bless"), color, "White") end -- context menu function 1 function doRemove(color) local chaosbag = Global.call("findChaosBag") -- remove tokens from chaos bag local count = { Bless = 0, Curse = 0 } for _, v in ipairs(chaosbag.getObjects()) do if v.name == "Bless" or v.name == "Curse" then chaosbag.takeObject({ guid = v.guid, position = { 0, 5, 0 }, callback_function = function(obj) obj.destruct() end }) count[v.name] = count[v.name] + 1 end end broadcastToColor("Removed " .. count.Bless .. " Bless and " .. count.Curse .. " Curse tokens from the chaos bag.", color, "White") broadcastToColor("Removed " .. removeTakenTokens("Bless") .. " Bless and " .. removeTakenTokens("Curse") .. " Curse tokens from play.", color, "White") doReset(color) end -- context menu function 2 function doReset(color) playerColor = color numInPlay = { Bless = 0, Curse = 0 } tokensTaken = { Bless = {}, Curse = {} } initializeState() tokenArrangerApi.layout() end -- removing tokens that were 'taken' function removeTakenTokens(type) local count = 0 for _, guid in ipairs(tokensTaken[type]) do local token = getObjectFromGUID(guid) if token ~= nil then token.destruct() count = count + 1 end end return count end --------------------------------------------------------- -- click functions --------------------------------------------------------- -- click function 1 function clickBless(_, color, isRightClick) playerColor = color callFunctions("Bless", isRightClick) end -- click function 2 function clickCurse(_, color, isRightClick) playerColor = color callFunctions("Curse", isRightClick) end -- click function 3 function enableAlt() if altState then return end altState = not altState updateButtons() end -- click function 4 function enableDefault() if not altState then return end altState = not altState updateButtons() end --------------------------------------------------------- -- called functions --------------------------------------------------------- function updateButtons() self.editButton({ index = 0, tooltip = MODE[altState] .. " Bless" }) self.editButton({ index = 1, tooltip = MODE[altState] .. " Curse" }) self.editButton({ index = 2, label = whitespace .. MODE[true] .. (altState and " ✓" or whitespace) .. " ", color = BUTTON_COLOR[not altState], font_color = FONT_COLOR[not altState] }) self.editButton({ index = 3, label = whitespace .. MODE[false] .. (altState and whitespace or " ✓") .. " ", color = BUTTON_COLOR[altState], font_color = FONT_COLOR[altState] }) end -- function that is called by click_functions 1+2 and calls the other functions function callFunctions(token, isRightClick) if not Global.call("canTouchChaosTokens") then return end local success if not altState then if isRightClick then success = takeToken(token, true) else success = addToken(token) end else if isRightClick then success = returnToken(token) else success = takeToken(token, false) end end if success ~= 0 then tokenArrangerApi.layout() end end -- returns a formatted string with information about the provided token type (bless / curse) function formatTokenCount(type) if type == nil then type = mode end return "(" .. (numInPlay[type] - #tokensTaken[type]) .. "/" .. #tokensTaken[type] .. ")" end -- called by cards that seal bless/curse tokens ---@param param Table This contains the type and guid of the sealed token function sealedToken(param) table.insert(tokensTaken[param.type], param.guid) broadcastCount(param.type) end -- called by cards that seal bless/curse tokens ---@param param Table This contains the type and guid of the released token function releasedToken(param) for i, v in ipairs(tokensTaken[param.type]) do if v == param.guid then table.remove(tokensTaken[param.type], i) break end end if not updating then updating = true Wait.frames(function() broadcastCount(param.type) updating = false end, 1) end end --------------------------------------------------------- -- main functions: add, take and return --------------------------------------------------------- function addToken(type) if numInPlay[type] == 10 then printToColor("10 tokens already in play, not adding any.", playerColor) return 0 end numInPlay[type] = numInPlay[type] + 1 printToAll("Adding " .. type .. " token " .. formatTokenCount(type)) return Global.call("spawnChaosToken", type) end function takeToken(type, remove) local chaosbag = Global.call("findChaosBag") if not remove and not SEAL_CARD_MESSAGE then broadcastToColor("For sealing tokens on cards try right-clicking on the card for seal options.", playerColor) SEAL_CARD_MESSAGE = true end local tokens = {} for _, v in ipairs(chaosbag.getObjects()) do if v.name == type then table.insert(tokens, v.guid) end end if #tokens == 0 then printToColor("No " .. type .. " tokens in the chaos bag.", playerColor) return 0 end local pos = self.getPosition() + Vector(2.25, 0, 0.85) if type == "Curse" then pos[3] = pos[3] - 1.7 end chaosbag.takeObject({ guid = table.remove(tokens), position = pos, smooth = false, callback_function = function(obj) if remove then numInPlay[type] = numInPlay[type] - 1 printToAll("Removing " .. type .. " token " .. formatTokenCount(type)) obj.destruct() else table.insert(tokensTaken[type], obj.getGUID()) printToAll("Taking " .. type .. " token " .. formatTokenCount(type)) end end }) end function returnToken(type) local guid = table.remove(tokensTaken[type]) if guid == nil then printToColor("No " .. type .. " tokens to return", playerColor) return 0 end local token = getObjectFromGUID(guid) if token == nil then printToColor("Couldn't find token " .. guid .. ", not returning to bag", playerColor) return 0 end local chaosbag = Global.call("findChaosBag") if chaosbag == nil then return 0 end chaosbag.putObject(token) printToAll("Returning " .. type .. " token " .. formatTokenCount(type)) end --------------------------------------------------------- -- Wendy Menu (context menu for cards on hotkey press) --------------------------------------------------------- function addMenuOptions(parameters) local playerColor = parameters.playerColor local hoveredObject = parameters.hoveredObject if hoveredObject == nil or hoveredObject.getVar("MENU_ADDED") == true then return end if hoveredObject.tag ~= "Card" then broadcastToColor("Right-click seal options can only be added to cards", playerColor) return end hoveredObject.addContextMenuItem("Seal Bless", function(color) sealToken("Bless", color, hoveredObject) tokenArrangerApi.layout() end, true) hoveredObject.addContextMenuItem("Release Bless", function(color) releaseToken("Bless", color, hoveredObject) tokenArrangerApi.layout() end, true) hoveredObject.addContextMenuItem("Seal Curse", function(color) sealToken("Curse", color, hoveredObject) tokenArrangerApi.layout() end, true) hoveredObject.addContextMenuItem("Release Curse", function(color) releaseToken("Curse", color, hoveredObject) tokenArrangerApi.layout() end, true) broadcastToColor("Right-click seal options added to " .. hoveredObject.getName(), playerColor) hoveredObject.setVar("MENU_ADDED", true) sealedTokens[hoveredObject.getGUID()] = {} end function sealToken(type, playerColor, enemy) local chaosbag = Global.call("findChaosBag") if chaosbag == nil then return end local pos = enemy.getPosition() for i, token in ipairs(chaosbag.getObjects()) do if token.name == type then chaosbag.takeObject({ position = { pos.x, pos.y + 1, pos.z }, index = i - 1, smooth = false, callback_function = function(obj) Wait.frames(function() table.insert(sealedTokens[enemy.getGUID()], obj) table.insert(tokensTaken[type], obj.getGUID()) printToColor("Sealing " .. type .. " token " .. formatTokenCount(type), playerColor) end, 1) end }) return end end printToColor(type .. " token not found in bag", playerColor) end function releaseToken(type, playerColor, enemy) local chaosbag = Global.call("findChaosBag") if chaosbag == nil then return end local tokens = sealedTokens[enemy.getGUID()] if tokens == nil or #tokens == 0 then return end for i, token in ipairs(tokens) do if token ~= nil and token.getName() == type then local guid = token.getGUID() chaosbag.putObject(token) for j, v in ipairs(tokensTaken[type]) do if v == guid then table.remove(tokensTaken[type], j) table.remove(tokens, i) printToColor("Releasing " .. type .. " token" .. formatTokenCount(type), playerColor) return end end end end printToColor(type .. " token not sealed on " .. enemy.getName(), playerColor) end end) __bundle_register("accessories/TokenArrangerApi", function(require, _LOADED, __bundle_register, __bundle_modules) do local TokenArrangerApi = {} -- local function to call the token arranger, if it is on the table ---@param functionName String Name of the function to cal ---@param argument Variant Parameter to pass local function callIfExistent(functionName, argument) local tokenArranger = getObjectsWithTag("TokenArranger")[1] if tokenArranger ~= nil then tokenArranger.call(functionName, argument) end end -- updates the token modifiers with the provided data ---@param tokenData Table Contains the chaos token metadata TokenArrangerApi.onTokenDataChanged = function(fullData) callIfExistent("onTokenDataChanged", fullData) end -- deletes already laid out tokens TokenArrangerApi.deleteCopiedTokens = function() callIfExistent("deleteCopiedTokens") end -- updates the laid out tokens TokenArrangerApi.layout = function() Wait.time(function() callIfExistent("layout") end, 0.1) end return TokenArrangerApi end end) return __bundle_require("__root")