525 lines
16 KiB
Plaintext
525 lines
16 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("__root", function(require, _LOADED, __bundle_register, __bundle_modules)
|
||
|
require("tokens/BlessCurseManager")
|
||
|
end)
|
||
|
__bundle_register("tokens/BlessCurseManager", function(require, _LOADED, __bundle_register, __bundle_modules)
|
||
|
-- Bless / Curse Manager
|
||
|
-- updated by: Chr1Z
|
||
|
-- made by: Tikatoy
|
||
|
-- description: helps with adding / removing and sealing of bless and curse tokens
|
||
|
information = {
|
||
|
version = "3.5",
|
||
|
last_updated = "12.11.2022"
|
||
|
}
|
||
|
|
||
|
local IMAGE_URL = {
|
||
|
Bless = "http://cloud-3.steamusercontent.com/ugc/1655601092778627699/339FB716CB25CA6025C338F13AFDFD9AC6FA8356/",
|
||
|
Curse = "http://cloud-3.steamusercontent.com/ugc/1655601092778636039/2A25BD38E8C44701D80DD96BF0121DA21843672E/"
|
||
|
}
|
||
|
|
||
|
-- 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 = " "
|
||
|
|
||
|
-- variable will be set by outside call
|
||
|
tokenArranger = nil
|
||
|
|
||
|
---------------------------------------------------------
|
||
|
-- 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)
|
||
|
self.addContextMenuItem("More Information", function()
|
||
|
printToAll("------------------------------", "White")
|
||
|
printToAll("Bless / Curse Manager v" .. information["version"] .. " by Chr1Z", "Orange")
|
||
|
printToAll("last updated: " .. information["last_updated"], "White")
|
||
|
printToAll("original by Tikatoy", "White")
|
||
|
end)
|
||
|
|
||
|
-- hotkeys
|
||
|
addHotkey("Bless Curse Status", printStatus, false)
|
||
|
addHotkey("Wendy's Menu", addMenuOptions, false)
|
||
|
|
||
|
-- 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 = getChaosBag()
|
||
|
if chaosbag == nil then return end
|
||
|
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 = getTokenCount(token)
|
||
|
if count == "(0/0)" then return end
|
||
|
broadcastToAll(token .. " Tokens " .. count, "White")
|
||
|
end
|
||
|
|
||
|
function printStatus(color)
|
||
|
broadcastToColor("Curse Tokens " .. getTokenCount("Curse"), color, "White")
|
||
|
broadcastToColor("Bless Tokens " .. getTokenCount("Bless"), color, "White")
|
||
|
end
|
||
|
|
||
|
-- context menu function 1
|
||
|
function doRemove(color)
|
||
|
local chaosbag = getChaosBag()
|
||
|
if chaosbag == nil then
|
||
|
broadcastToAll("Chaos bag not found!", "Red")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- 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")
|
||
|
|
||
|
-- removing tokens that were 'taken'
|
||
|
local function removeType(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
|
||
|
|
||
|
broadcastToColor("Removed " .. removeType("Bless") .. " Bless and " ..
|
||
|
removeType("Curse") .. " Curse tokens from play.", color, "White")
|
||
|
|
||
|
doReset(color)
|
||
|
end
|
||
|
|
||
|
-- context menu function 2
|
||
|
function doReset(color)
|
||
|
-- delete previously pulled out tokens by the token arranger
|
||
|
if tokenArranger then
|
||
|
for _, token in ipairs(getObjectsWithTag(tokenArranger.getVar("TO_DELETE_TAG"))) do
|
||
|
token.destruct()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
playerColor = color
|
||
|
numInPlay = { Bless = 0, Curse = 0 }
|
||
|
tokensTaken = { Bless = {}, Curse = {} }
|
||
|
initializeState()
|
||
|
updateTokenArranger()
|
||
|
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)
|
||
|
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 updateTokenArranger() end
|
||
|
end
|
||
|
|
||
|
UPDATING = false
|
||
|
function updateTokenArranger()
|
||
|
if tokenArranger and not UPDATING then
|
||
|
UPDATING = true
|
||
|
Wait.time(function()
|
||
|
UPDATING = false
|
||
|
tokenArranger.call("layout")
|
||
|
end, 1.5)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function getChaosBag()
|
||
|
local zone = getObjectFromGUID("83ef06")
|
||
|
if zone == nil then printToAll("Zone for chaosbag not found!", "Red") return end
|
||
|
|
||
|
local items = zone.getObjects()
|
||
|
local chaosbag = nil
|
||
|
for _, v in ipairs(items) do
|
||
|
if v.getDescription() == "Chaos Bag" then
|
||
|
chaosbag = getObjectFromGUID(v.getGUID())
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
if chaosbag == nil then printToColor("No chaos bag found", playerColor) end
|
||
|
return chaosbag
|
||
|
end
|
||
|
|
||
|
function getTokenCount(type)
|
||
|
if type == nil then type = mode end
|
||
|
return "(" .. (numInPlay[type] - #tokensTaken[type]) .. "/" .. #tokensTaken[type] .. ")"
|
||
|
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
|
||
|
return spawnToken(type)
|
||
|
end
|
||
|
|
||
|
function spawnToken(type)
|
||
|
local chaosbag = getChaosBag()
|
||
|
if chaosbag == nil then
|
||
|
return 0
|
||
|
end
|
||
|
local pos = chaosbag.getPosition()
|
||
|
local obj = spawnObject({
|
||
|
type = 'Custom_Tile',
|
||
|
position = { pos.x, pos.y + 1, pos.z },
|
||
|
callback_function = function(obj)
|
||
|
obj.setName(type)
|
||
|
chaosbag.putObject(obj)
|
||
|
numInPlay[type] = numInPlay[type] + 1
|
||
|
printToAll("Adding " .. type .. " token " .. getTokenCount(type))
|
||
|
end
|
||
|
})
|
||
|
obj.setCustomObject({
|
||
|
type = 2,
|
||
|
image = IMAGE_URL[type],
|
||
|
thickness = 0.1,
|
||
|
})
|
||
|
obj.scale { 0.81, 1, 0.81 }
|
||
|
end
|
||
|
|
||
|
function takeToken(type, remove)
|
||
|
local chaosbag = getChaosBag()
|
||
|
if chaosbag == nil then
|
||
|
broadcastToAll("Chaos bag not found!", "Red")
|
||
|
return 0
|
||
|
end
|
||
|
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 " .. getTokenCount(type))
|
||
|
obj.destruct()
|
||
|
else
|
||
|
table.insert(tokensTaken[type], obj.getGUID())
|
||
|
printToAll("Taking " .. type .. " token " .. getTokenCount(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 = getChaosBag()
|
||
|
if chaosbag == nil then
|
||
|
return 0
|
||
|
end
|
||
|
chaosbag.putObject(token)
|
||
|
printToAll("Returning " .. type .. " token " .. getTokenCount(type))
|
||
|
end
|
||
|
|
||
|
---------------------------------------------------------
|
||
|
-- Wendy Menu (context menu for cards on hotkey press)
|
||
|
---------------------------------------------------------
|
||
|
|
||
|
function addMenuOptions(playerColor, 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)
|
||
|
updateTokenArranger()
|
||
|
end, true)
|
||
|
|
||
|
hoveredObject.addContextMenuItem("Release Bless", function(color)
|
||
|
releaseToken("Bless", color, hoveredObject)
|
||
|
updateTokenArranger()
|
||
|
end, true)
|
||
|
|
||
|
hoveredObject.addContextMenuItem("Seal Curse", function(color)
|
||
|
sealToken("Curse", color, hoveredObject)
|
||
|
updateTokenArranger()
|
||
|
end, true)
|
||
|
|
||
|
hoveredObject.addContextMenuItem("Release Curse", function(color)
|
||
|
releaseToken("Curse", color, hoveredObject)
|
||
|
updateTokenArranger()
|
||
|
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 = getChaosBag()
|
||
|
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 " .. getTokenCount(type), playerColor)
|
||
|
end, 1)
|
||
|
end
|
||
|
})
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
printToColor(type .. " token not found in bag", playerColor)
|
||
|
end
|
||
|
|
||
|
function releaseToken(type, playerColor, enemy)
|
||
|
local chaosbag = getChaosBag()
|
||
|
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" .. getTokenCount(type), playerColor)
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
printToColor(type .. " token not sealed on " .. enemy.getName(), playerColor)
|
||
|
end
|
||
|
end)
|
||
|
return __bundle_require("__root")
|