ah_sce_unpacked/unpacked/Custom_Token BlessCurse Manager 5933fb.ttslua
2024-02-17 19:48:30 -05:00

617 lines
20 KiB
Plaintext

-- 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("accessories/TokenArrangerApi", function(require, _LOADED, __bundle_register, __bundle_modules)
do
local TokenArrangerApi = {}
local guidReferenceApi = require("core/GUIDReferenceApi")
-- local function to call the token arranger, if it is on the table
---@param functionName string Name of the function to cal
---@param argument? table Parameter to pass
local function callIfExistent(functionName, argument)
local tokenArranger = guidReferenceApi.getObjectByOwnerAndType("Mythos", "TokenArranger")
if tokenArranger ~= nil then
tokenArranger.call(functionName, argument)
end
end
-- updates the token modifiers with the provided data
---@param fullData 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)
__bundle_register("chaosbag/ChaosBagApi", function(require, _LOADED, __bundle_register, __bundle_modules)
do
local ChaosBagApi = {}
-- respawns the chaos bag with a new state of tokens
---@param tokenList table List of chaos token ids
ChaosBagApi.setChaosBagState = function(tokenList)
return Global.call("setChaosBagState", tokenList)
end
-- returns a Table List of chaos token ids in the current chaos bag
-- requires copying the data into a new table because TTS is weird about handling table return values in Global
ChaosBagApi.getChaosBagState = function()
local chaosBagContentsCatcher = Global.call("getChaosBagState")
local chaosBagContents = {}
for _, v in ipairs(chaosBagContentsCatcher) do
table.insert(chaosBagContents, v)
end
return chaosBagContents
end
-- checks scripting zone for chaos bag (also called by a lot of objects!)
ChaosBagApi.findChaosBag = function()
return Global.call("findChaosBag")
end
-- returns a table of object references to the tokens in play (does not include sealed tokens!)
ChaosBagApi.getTokensInPlay = function()
return Global.call("getChaosTokensinPlay")
end
-- returns all sealed tokens on cards to the chaos bag
---@param playerColor string Color of the player to show the broadcast to
ChaosBagApi.releaseAllSealedTokens = function(playerColor)
return Global.call("releaseAllSealedTokens", playerColor)
end
-- returns all drawn tokens to the chaos bag
ChaosBagApi.returnChaosTokens = function()
return Global.call("returnChaosTokens")
end
-- removes the specified chaos token from the chaos bag
---@param id string ID of the chaos token
ChaosBagApi.removeChaosToken = function(id)
return Global.call("removeChaosToken", id)
end
-- returns a chaos token to the bag and calls all relevant functions
---@param token tts__Object Chaos token to return
ChaosBagApi.returnChaosTokenToBag = function(token)
return Global.call("returnChaosTokenToBag", token)
end
-- spawns the specified chaos token and puts it into the chaos bag
---@param id string ID of the chaos token
ChaosBagApi.spawnChaosToken = function(id)
return Global.call("spawnChaosToken", id)
end
-- Checks to see if the chaos bag can be manipulated. If a player is searching the bag when tokens
-- are drawn or replaced a TTS bug can cause those tokens to vanish. Any functions which change the
-- contents of the bag should check this method before doing so.
-- This method will broadcast a message to all players if the bag is being searched.
---@return any canTouch True if the bag is manipulated, false if it should be blocked.
ChaosBagApi.canTouchChaosTokens = function()
return Global.call("canTouchChaosTokens")
end
-- called by playermats (by the "Draw chaos token" button)
---@param mat tts__Object Playermat that triggered this
---@param drawAdditional boolean Controls whether additional tokens should be drawn
---@param tokenType? string Name of token (e.g. "Bless") to be drawn from the bag
---@param guidToBeResolved? string GUID of the sealed token to be resolved instead of drawing a token from the bag
ChaosBagApi.drawChaosToken = function(mat, drawAdditional, tokenType, guidToBeResolved)
return Global.call("drawChaosToken", {mat = mat, drawAdditional = drawAdditional, tokenType = tokenType, guidToBeResolved = guidToBeResolved})
end
-- returns a Table List of chaos token ids in the current chaos bag
-- requires copying the data into a new table because TTS is weird about handling table return values in Global
ChaosBagApi.getIdUrlMap = function()
return Global.getTable("ID_URL_MAP")
end
return ChaosBagApi
end
end)
__bundle_register("core/GUIDReferenceApi", function(require, _LOADED, __bundle_register, __bundle_modules)
do
local GUIDReferenceApi = {}
local function getGuidHandler()
return getObjectFromGUID("123456")
end
---@param owner string Parent object for this search
---@param type string Type of object to search for
---@return any: Object reference to the matching object
GUIDReferenceApi.getObjectByOwnerAndType = function(owner, type)
return getGuidHandler().call("getObjectByOwnerAndType", { owner = owner, type = type })
end
-- returns all matching objects as a table with references
---@param type string Type of object to search for
---@return table: List of object references to matching objects
GUIDReferenceApi.getObjectsByType = function(type)
return getGuidHandler().call("getObjectsByType", type)
end
-- returns all matching objects as a table with references
---@param owner string Parent object for this search
---@return table: List of object references to matching objects
GUIDReferenceApi.getObjectsByOwner = function(owner)
return getGuidHandler().call("getObjectsByOwner", owner)
end
-- sends new information to the reference handler to edit the main index
---@param owner string Parent of the object
---@param type string Type of the object
---@param guid string GUID of the object
GUIDReferenceApi.editIndex = function(owner, type, guid)
return getGuidHandler().call("editIndex", {
owner = owner,
type = type,
guid = guid
})
end
return GUIDReferenceApi
end
end)
__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 chaosBagApi = require("chaosbag/ChaosBagApi")
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 updating
---------------------------------------------------------
-- creating buttons and menus + initializing tables
---------------------------------------------------------
function onLoad()
-- index: 0 - bless
buttonParamaters.click_function = "clickBless"
buttonParamaters.position = { -1.03, 0, 0.46 }
buttonParamaters.tooltip = "Add / Remove Bless"
self.createButton(buttonParamaters)
-- index: 1 - curse
buttonParamaters.click_function = "clickCurse"
buttonParamaters.position[1] = -buttonParamaters.position[1]
buttonParamaters.tooltip = "Add / Remove Curse"
self.createButton(buttonParamaters)
-- index: 2 - bless count
buttonParamaters.tooltip = ""
buttonParamaters.click_function = "none"
buttonParamaters.width = 0
buttonParamaters.height = 0
buttonParamaters.color = { 0.4, 0.4, 0.4 }
buttonParamaters.font_color = { 1, 1, 1 }
buttonParamaters.font_size = 235
buttonParamaters.position = { -1.03, 0.06, -0.8 }
self.createButton(buttonParamaters)
-- index: 3 - curse count
buttonParamaters.position[1] = -buttonParamaters.position[1]
self.createButton(buttonParamaters)
-- context menu
self.addContextMenuItem("Remove all", doRemove)
self.addContextMenuItem("Reset", doReset)
-- initializing tables
initializeState()
broadcastCount("Curse")
broadcastCount("Bless")
end
function resetTables()
numInPlay = { Bless = 0, Curse = 0 }
tokensTaken = { Bless = {}, Curse = {} }
sealedTokens = {}
end
function initializeState()
resetTables()
-- count tokens in the bag
local chaosBag = chaosBagApi.findChaosBag()
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 > -65 and pos.x < 10 and pos.z > -35 and pos.z < 35 and obj.type == "Tile" 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
updateButtonLabels()
end
function updateButtonLabels()
self.editButton({ index = 2, label = formatTokenCount("Bless", true)})
self.editButton({ index = 3, label = formatTokenCount("Curse", true)})
end
function broadcastCount(token)
local count = formatTokenCount(token)
if count == "(0 + 0)" then return end
broadcastToAll(token .. " Tokens " .. count, "White")
end
function broadcastStatus(color)
broadcastToColor("Curse Tokens " .. formatTokenCount("Curse"), color, "White")
broadcastToColor("Bless Tokens " .. formatTokenCount("Bless"), color, "White")
end
---------------------------------------------------------
-- TTS event handling
---------------------------------------------------------
-- enable tracking of bag changes for 1 second
function onObjectDrop(_, object)
if not isBlurseToken(object) then return end
-- check if object was dropped in chaos bag area
for _, zone in ipairs(object.getZones()) do
if zone.getName() == "ChaosBagZone" then
trackBagChange = true
Wait.time(function() trackBagChange = false end, 1)
return
end
end
end
-- handle manual returning of bless / curse tokens
function onObjectEnterContainer(container, object)
if not (trackBagChange and isChaosbag(container) and isBlurseToken(object)) then return end
-- small delay to ensure token has entered bag
Wait.time(doReset, 0.5)
end
function isChaosbag(obj)
if obj.getDescription() ~= "Chaos Bag" then return end -- early exit for performance
return obj == chaosBagApi.findChaosBag()
end
function isBlurseToken(obj)
local name = obj.getName()
return name == "Bless" or name == "Curse"
end
---------------------------------------------------------
-- context menu functions
---------------------------------------------------------
function doRemove(color)
local chaosBag = chaosBagApi.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")
resetTables()
updateButtonLabels()
tokenArrangerApi.layout()
end
function doReset()
initializeState()
broadcastCount("Curse")
broadcastCount("Bless")
tokenArrangerApi.layout()
end
---------------------------------------------------------
-- click functions
---------------------------------------------------------
function clickBless(_, color, isRightClick)
playerColor = color
callFunctions("Bless", isRightClick)
end
function clickCurse(_, color, isRightClick)
playerColor = color
callFunctions("Curse", isRightClick)
end
function callFunctions(type, isRightClick)
if not chaosBagApi.canTouchChaosTokens() then return end
if isRightClick then
removeToken(type)
else
addToken(type)
end
tokenArrangerApi.layout()
end
---------------------------------------------------------
-- called functions
---------------------------------------------------------
-- returns a formatted string with information about the provided token type (bless / curse)
---@param type string Type of chaos token ("Bless" or "Curse")
---@param omitBrackets? boolean Controls whether the brackets should be omitted from the return
---@return string tokenCount
function formatTokenCount(type, omitBrackets)
if omitBrackets then
return (numInPlay[type] - #tokensTaken[type]) .. " + " .. #tokensTaken[type]
else
return "(" .. (numInPlay[type] - #tokensTaken[type]) .. " + " .. #tokensTaken[type] .. ")"
end
end
-- seals a token on a card (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)
updateButtonLabels()
end
-- returns a token to the bag (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
updateDisplayAndBroadcast(param.type)
end
-- removes a token (called by cards that seal bless/curse tokens)
---@param param table This contains the type and guid of the released token
function returnedToken(param)
for i, v in ipairs(tokensTaken[param.type]) do
if v == param.guid then
table.remove(tokensTaken[param.type], i)
numInPlay[param.type] = numInPlay[param.type] - 1
break
end
end
updateDisplayAndBroadcast(param.type)
end
function updateDisplayAndBroadcast(type)
if not updating then
updating = true
Wait.frames(function()
broadcastCount(type)
updateButtonLabels()
updating = false
end, 5)
end
end
---------------------------------------------------------
-- main functions: add and remove
---------------------------------------------------------
function addToken(type)
if numInPlay[type] == 10 then
printToColor("10 tokens already in play, not adding any.", playerColor)
return
end
numInPlay[type] = numInPlay[type] + 1
printToAll("Adding " .. type .. " token " .. formatTokenCount(type))
updateButtonLabels()
return chaosBagApi.spawnChaosToken(type)
end
function removeToken(type)
local chaosBag = chaosBagApi.findChaosBag()
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
end
chaosBag.takeObject({
guid = table.remove(tokens),
smooth = false,
callback_function = function(obj)
numInPlay[type] = numInPlay[type] - 1
printToAll("Removing " .. type .. " token " .. formatTokenCount(type))
updateButtonLabels()
obj.destruct()
end
})
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
---------------------------------------------------------
-- Wendy's Menu (context menu for cards on hotkey press)
---------------------------------------------------------
function addMenuOptions(parameters)
local playerColor = parameters.playerColor
local hoveredObject = parameters.hoveredObject
if hoveredObject == nil or hoveredObject.type ~= "Card" then
broadcastToColor("Right-click seal options can only be added to cards.", playerColor)
return
elseif hoveredObject.hasTag("CardThatSeals") or hoveredObject.getVar("MENU_ADDED") == true then
broadcastToColor("This card already has a sealing context menu.", 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, hoveredObject)
local chaosBag = chaosBagApi.findChaosBag()
for i, token in ipairs(chaosBag.getObjects()) do
if token.name == type then
return chaosBag.takeObject({
position = hoveredObject.getPosition() + Vector(0, 1, 0),
index = i - 1,
smooth = false,
callback_function = function(obj)
table.insert(sealedTokens[hoveredObject.getGUID()], obj)
table.insert(tokensTaken[type], obj.getGUID())
tokenArrangerApi.layout()
updateDisplayAndBroadcast(type)
end
})
end
end
printToColor(type .. " token not found in bag", playerColor)
end
function releaseToken(type, playerColor, hoveredObject)
local chaosBag = chaosBagApi.findChaosBag()
local tokens = sealedTokens[hoveredObject.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)
tokenArrangerApi.layout()
updateDisplayAndBroadcast(type)
return
end
end
end
end
printToColor(type .. " token not sealed on " .. hoveredObject.getName(), playerColor)
end
function none() end
end)
return __bundle_require("__root")