Merge pull request #218 from argonui/token-metadata

Token Arranger: token metadata support and misc. updates
This commit is contained in:
Chr1Z 2023-03-01 18:04:47 +01:00 committed by GitHub
commit ceef316adf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 349 additions and 283 deletions

View File

@ -49,8 +49,8 @@
"normalized": "location" "normalized": "location"
}, },
{ {
"displayed": "to_be_deleted", "displayed": "tempToken",
"normalized": "to_be_deleted" "normalized": "temptoken"
}, },
{ {
"displayed": "Minicard", "displayed": "Minicard",

View File

@ -34,18 +34,21 @@
"LayoutGroupSortIndex": 0, "LayoutGroupSortIndex": 0,
"Locked": false, "Locked": false,
"LuaScript": "require(\"accessories/TokenArranger\")", "LuaScript": "require(\"accessories/TokenArranger\")",
"LuaScriptState_path": "Fan-MadeAccessories.aa8b38/TokenArranger.022907.luascriptstate", "LuaScriptState": "",
"MeasureMovement": false, "MeasureMovement": false,
"Name": "Custom_Token", "Name": "Custom_Token",
"Nickname": "Token Arranger", "Nickname": "Token Arranger",
"Snap": true, "Snap": true,
"Sticky": true, "Sticky": true,
"Tags": [
"TokenArranger"
],
"Tooltip": true, "Tooltip": true,
"Transform": { "Transform": {
"posX": 22.951, "posX": -42.3,
"posY": 5.242, "posY": 1.53,
"posZ": -30.295, "posZ": -46.5,
"rotX": 1, "rotX": 0,
"rotY": 270, "rotY": 270,
"rotZ": 0, "rotZ": 0,
"scaleX": 2, "scaleX": 2,

View File

@ -1 +0,0 @@
{"":[0,11],"Auto-fail":[-100,7],"Bless":[101,8],"Cultist":[-2,4],"Curse":[-101,9],"Elder Sign":[100,2],"Elder Thing":[-4,6],"Frost":[-99,10],"Skull":[-1,3],"Tablet":[-3,5]}

View File

@ -1,20 +1,150 @@
-- names of tokens in order -- common parameters
local buttonParameters = {}
buttonParameters.function_owner = self
buttonParameters.label = ""
buttonParameters.tooltip = "Add / Remove"
buttonParameters.color = { 0, 0, 0, 0 }
buttonParameters.width = 325
buttonParameters.height = 325
local inputParameters = {}
inputParameters.function_owner = self
inputParameters.font_size = 100
inputParameters.width = 250
inputParameters.height = inputParameters.font_size + 23
inputParameters.alignment = 3
inputParameters.validation = 2
inputParameters.tab = 2
local latestLoad = "XXX"
local updating = false
local tokenPrecedence = {}
local TOKEN_NAMES = { local TOKEN_NAMES = {
"Elder Sign", "Elder Sign",
"Skull", "Skull",
"Cultist", "Cultist",
"Tablet", "Tablet",
"Elder Thing", "Elder Thing",
"Auto-fail", "Auto-fail",
"Bless", "Bless",
"Curse", "Curse",
"Frost", "Frost",
"" ""
} }
-- token modifiers for sorting (and order for same modifier) -- saving the precedence settings and information on the most recently loaded data
-- order starts at 2 because there is a "+1" token function onSave()
local TOKEN_PRECEDENCE = { return JSON.encode({
tokenPrecedence = tokenPrecedence,
latestLoad = latestLoad
})
end
function onLoad(saveState)
if saveState ~= nil and saveState ~= "" then
local loadedData = JSON.decode(saveState)
tokenPrecedence = loadedData.tokenPrecedence
latestLoad = loadedData.latestLoad or "XXX"
else
loadDefaultValues()
end
-- create UI
local offset = 0.725
local pos = { x = { -1.067, 0.377 }, z = -2.175 }
-- button and inputs index 0-9
for i = 1, 10 do
if i < 6 then
buttonParameters.position = { pos.x[1], 0, pos.z + i * offset }
inputParameters.position = { pos.x[1] + offset, 0.1, pos.z + i * offset }
else
buttonParameters.position = { pos.x[2], 0, pos.z + (i - 5) * offset }
inputParameters.position = { pos.x[2] + offset, 0.1, pos.z + (i - 5) * offset }
end
buttonParameters.click_function = attachIndex("tokenClick", i)
inputParameters.input_function = attachIndex2("tokenInput", i)
inputParameters.value = tokenPrecedence[TOKEN_NAMES[i]][1]
self.createButton(buttonParameters)
self.createInput(inputParameters)
end
-- index 10: "Update / Hide" button
buttonParameters.label = "Update / Hide"
buttonParameters.click_function = "layout"
buttonParameters.tooltip = "Left-Click: Update!\nRight-Click: Hide Tokens!"
buttonParameters.position = { 0.725, 0.1, 2.025 }
buttonParameters.color = { 1, 1, 1 }
buttonParameters.width = 675
buttonParameters.height = 175
self.createButton(buttonParameters)
-- reset context menu
self.addContextMenuItem("Load default values", function()
loadDefaultValues()
updateUI()
layout()
end)
-- grab token metadata from mythos area
local mythosArea = getObjectFromGUID("9f334f")
Wait.time(function() mythosArea.call("fireTokenDataChangedEvent") end, 0.5)
Wait.time(layout, 2)
end
-- delete temporary tokens when destroyed
function onDestroy() deleteCopiedTokens() end
-- layout tokens when dropped (after 2 seconds)
function onDrop() Wait.time(layout, 2) end
-- delete temporary tokens when picked up
function onPickUp() deleteCopiedTokens() end
-- helper functions to carry index
function attachIndex(click_function, index)
local fn_name = click_function .. index
_G[fn_name] = function(_, _, isRightClick)
_G[click_function](isRightClick, index)
end
return fn_name
end
function attachIndex2(input_function, index)
local fn_name = input_function .. index
_G[fn_name] = function(_, _, input, selected)
_G[input_function](input, selected, index)
end
return fn_name
end
-- click_function for buttons on chaos tokens
function tokenClick(isRightClick, index)
local change = tonumber(isRightClick and "-1" or "1")
tokenPrecedence[TOKEN_NAMES[index]][1] = tokenPrecedence[TOKEN_NAMES[index]][1] + change
self.editInput({ index = index - 1, value = tokenPrecedence[TOKEN_NAMES[index]][1] })
layout()
end
-- input_function for input_boxes
function tokenInput(input, selected, index)
if selected == false then
local num = tonumber(input)
if num ~= nil then
tokenPrecedence[TOKEN_NAMES[index]][1] = num
end
layout()
end
end
-- loads the default precedence table
function loadDefaultValues()
-- token modifiers for sorting (and order for same modifier)
-- order starts at 2 because there is a "+1" token
tokenPrecedence = {
["Elder Sign"] = { 100, 2 }, ["Elder Sign"] = { 100, 2 },
["Skull"] = { -1, 3 }, ["Skull"] = { -1, 3 },
["Cultist"] = { -2, 4 }, ["Cultist"] = { -2, 4 },
@ -25,223 +155,128 @@ local TOKEN_PRECEDENCE = {
["Curse"] = { -101, 9 }, ["Curse"] = { -101, 9 },
["Frost"] = { -99, 10 }, ["Frost"] = { -99, 10 },
[""] = { 0, 11 } [""] = { 0, 11 }
} }
-- common parameters
local buttonParameters = {}
buttonParameters.function_owner = self
buttonParameters.label = ""
buttonParameters.tooltip = "Add / Remove"
buttonParameters.color = { 0, 0, 0, 0 }
buttonParameters.width = 325
buttonParameters.height = 325
local inputParameters = {}
inputParameters.function_owner = self
inputParameters.font_size = 100
inputParameters.width = 250
inputParameters.height = inputParameters.font_size + 23
inputParameters.alignment = 3
inputParameters.validation = 2
inputParameters.tab = 2
updating = false
function onSave() return JSON.encode(TOKEN_PRECEDENCE) end
function onLoad(save_state)
if save_state ~= nil then
TOKEN_PRECEDENCE = JSON.decode(save_state)
end
-- create UI
local offset = 0.725
local pos = { x = { -1.067, 0.377 }, z = -2.175 }
-- button and inputs index 1-10
for i = 1, 10 do
if i < 6 then
buttonParameters.position = { pos.x[1], 0, pos.z + i * offset }
inputParameters.position = { pos.x[1] + offset, 0.1, pos.z + i * offset }
else
buttonParameters.position = { pos.x[2], 0, pos.z + (i - 5) * offset }
inputParameters.position = { pos.x[2] + offset, 0.1, pos.z + (i - 5) * offset }
end
buttonParameters.click_function = attachIndex("tokenClick", i)
inputParameters.input_function = attachIndex2("tokenInput", i)
inputParameters.value = TOKEN_PRECEDENCE[TOKEN_NAMES[i]][1]
self.createButton(buttonParameters)
self.createInput(inputParameters)
end
-- index 11: "Update / Hide" button
buttonParameters.label = "Update / Hide"
buttonParameters.click_function = "layout"
buttonParameters.tooltip = "Left-Click: Update!\nRight-Click: Hide Tokens!"
buttonParameters.position = { 0.725, 0.1, 2.025 }
buttonParameters.color = { 1, 1, 1 }
buttonParameters.width = 675
buttonParameters.height = 175
self.createButton(buttonParameters)
self.addContextMenuItem("More Information", function()
printToAll("------------------------------", "White")
printToAll("Token Arranger by Chr1Z", "Orange")
printToAll("original concept by Whimsical", "White")
end)
-- send object reference to bless/curse manager
Wait.time(function() getObjectFromGUID("5933fb").setVar("tokenArranger", self) end, 1)
end end
function onDestroy() -- update input fields
deleteCopiedTokens() function updateUI()
-- remove object reference from bless/curse manager for i = 1, 10 do
getObjectFromGUID("5933fb").setVar("tokenArranger", nil) self.editInput({ index = i - 1, value = tokenPrecedence[TOKEN_NAMES[i]][1] })
end end
function onPickUp()
deleteCopiedTokens()
end
-- helper functions to carry index
function attachIndex(click_function, index)
local fn_name = click_function .. index
_G[fn_name] = function(obj, player_color, isRightClick)
_G[click_function](obj, player_color, isRightClick, index)
end
return fn_name
end
function attachIndex2(input_function, index)
local fn_name = input_function .. index
_G[fn_name] = function(obj, player_color, input, selected)
_G[input_function](obj, player_color, input, selected, index)
end
return fn_name
end
-- click_function for buttons on chaos tokens
function tokenClick(_, _, isRightClick, index)
if not updating then
updating = true
local change = tonumber(isRightClick and "-1" or "1")
TOKEN_PRECEDENCE[TOKEN_NAMES[index]][1] = TOKEN_PRECEDENCE[TOKEN_NAMES[index]][1] + change
self.editInput({ index = index - 1, value = TOKEN_PRECEDENCE[TOKEN_NAMES[index]][1] })
layout()
end
end
-- input_function for input_boxes
function tokenInput(_, _, input, selected, index)
if selected == false and not updating then
updating = true
local num = tonumber(input)
if num ~= nil then
TOKEN_PRECEDENCE[TOKEN_NAMES[index]][1] = num
end
layout()
end
end end
-- order function for data sorting -- order function for data sorting
function token_value_comparator(left, right) function token_value_comparator(left, right)
if left.value > right.value then return true if left.value > right.value then
elseif right.value > left.value then return false return true
elseif left.order < right.order then return true elseif right.value > left.value then
elseif right.order < left.order then return false return false
else return left.token.getGUID() > right.token.getGUID() elseif left.order < right.order then
end return true
elseif right.order < left.order then
return false
else
return left.token.getGUID() > right.token.getGUID()
end
end end
-- get chaos bag from scripting zone and description -- checks scripting zone for chaos bag
function getChaosBag() function findChaosBag()
local chaosbag = nil for _, item in ipairs(getObjectFromGUID("83ef06").getObjects()) do
local chaosbag_zone = getObjectFromGUID("83ef06") if item.getDescription() == "Chaos Bag" then
return item
-- error handling: scripting zone not found
if chaosbag_zone == nil then
printToAll("Zone for chaos bag detection couldn't be found.", "Red")
return nil
end end
end
for _, v in ipairs(chaosbag_zone.getObjects()) do
if v.getDescription() == "Chaos Bag" then
chaosbag = getObjectFromGUID(v.getGUID())
break
end
end
-- error handling: chaos bag not found
if chaosbag == nil then
printToAll("Chaos bag couldn't be found.", "Red")
end
return chaosbag
end end
-- deletes previously placed tokens -- deletes previously placed tokens
function deleteCopiedTokens() function deleteCopiedTokens()
for _, token in ipairs(getObjectsWithTag("to_be_deleted")) do token.destruct() end for _, token in ipairs(getObjectsWithTag("tempToken")) do token.destruct() end
end end
-- main function (delete old tokens, clone chaos bag content, sort it and position it) -- main function (delete old tokens, clone chaos bag content, sort it and position it)
function layout(_, _, isRightClick) function layout(_, _, isRightClick)
deleteCopiedTokens() if updating then return end
updating = true
deleteCopiedTokens()
-- stop here if right-clicked -- stop here if right-clicked
if isRightClick then return end if isRightClick then
local chaosBag = getChaosBag()
local data = {}
-- clone tokens from chaos bag (default position above trash can)
for i, obj in ipairs(chaosBag.getData().ContainedObjects) do
obj["Tags"] = { "to_be_deleted" }
local spawnedObj = spawnObjectData({
data = obj,
position = { 0.49, 3, 0 }
})
local value = tonumber(obj["Nickname"])
local precedence = TOKEN_PRECEDENCE[obj["Nickname"]]
data[i] = {
token = spawnedObj,
value = value or precedence[1]
}
if precedence ~= nil then
data[i].order = precedence[2]
else
data[i].order = value
end
end
-- sort table by value (symbols last if same value)
table.sort(data, token_value_comparator)
-- error handling for removal of token arranger
if self == nil then
for _, token in ipairs(getObjectsWithTag("to_be_deleted")) do token.destruct() end
return
end
-- laying out the tokens
local pos = self.getPosition() + Vector(3.55, -0.05, -3.95)
local location = { x = pos.x, y = pos.y, z = pos.z }
local current_value = data[1].value
for _, item in ipairs(data) do
if item.value ~= current_value then
location.x = location.x - 1.75
location.z = pos.z
current_value = item.value
end
item.token.setPosition(location)
item.token.setRotation(self.getRotation())
location.z = location.z - 1.75
end
updating = false updating = false
return
end
local chaosBag = findChaosBag()
local data = {}
-- clone tokens from chaos bag (default position above trash can)
for i, obj in ipairs(chaosBag.getData().ContainedObjects) do
obj["Tags"] = { "tempToken" }
local spawnedObj = spawnObjectData({
data = obj,
position = { 0.49, 3, 0 }
})
local value = tonumber(obj["Nickname"])
local precedence = tokenPrecedence[obj["Nickname"]]
data[i] = {
token = spawnedObj,
value = value or precedence[1]
}
if precedence ~= nil then
data[i].order = precedence[2]
else
data[i].order = value
end
end
-- sort table by value (symbols last if same value)
table.sort(data, token_value_comparator)
-- error handling for removal of token arranger
if self == nil then
for _, token in ipairs(getObjectsWithTag("tempToken")) do token.destruct() end
return
end
-- laying out the tokens
local pos = self.getPosition() + Vector(3.55, -0.05, -3.95)
local location = { x = pos.x, y = pos.y, z = pos.z }
local current_value = data[1].value
for _, item in ipairs(data) do
if item.value ~= current_value then
location.x = location.x - 1.75
location.z = pos.z
current_value = item.value
end
item.token.setPosition(location)
item.token.setRotation(self.getRotation())
location.z = location.z - 1.75
end
Wait.time(function() updating = false end, 0.1)
end
-- called from outside to set default values for tokens
function onTokenDataChanged(parameters)
local tokenData = parameters.tokenData or {}
local currentScenario = parameters.currentScenario or ""
local useFrontData = parameters.useFrontData or "true"
-- only update if this data is new
local info = currentScenario .. useFrontData
if latestLoad == info then return end
latestLoad = info
-- update token precedence
for key, table in pairs(tokenData) do
local modifier = table.modifier
if modifier == -999 then modifier = 0 end
tokenPrecedence[key][1] = modifier
end
updateUI()
layout()
end end

View File

@ -0,0 +1,35 @@
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(tokenData, currentScenario, useFrontData)
callIfExistent("onTokenDataChanged", {
tokenData = tokenData,
currentScenario = currentScenario,
useFrontData = useFrontData
})
end
-- deletes already laid out tokens
TokenArrangerApi.deleteCopiedTokens = function()
callIfExistent("deleteCopiedTokens")
end
-- updates the laid out tokens
TokenArrangerApi.layout = function()
callIfExistent("layout")
end
return TokenArrangerApi
end

View File

@ -1,11 +1,4 @@
-- Bless / Curse Manager local tokenArrangerApi = require("accessories/TokenArrangerApi")
-- 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 = { local IMAGE_URL = {
Bless = "http://cloud-3.steamusercontent.com/ugc/1655601092778627699/339FB716CB25CA6025C338F13AFDFD9AC6FA8356/", Bless = "http://cloud-3.steamusercontent.com/ugc/1655601092778627699/339FB716CB25CA6025C338F13AFDFD9AC6FA8356/",
@ -25,9 +18,6 @@ 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 FONT_COLOR = { [false] = { 1, 1, 1 }, [true] = { 0, 0, 0 } }
local whitespace = " " local whitespace = " "
-- variable will be set by outside call
tokenArranger = nil
--------------------------------------------------------- ---------------------------------------------------------
-- creating buttons and menus + initializing tables -- creating buttons and menus + initializing tables
--------------------------------------------------------- ---------------------------------------------------------
@ -67,12 +57,6 @@ function onLoad(saved_state)
-- context menu -- context menu
self.addContextMenuItem("Remove all", doRemove) self.addContextMenuItem("Remove all", doRemove)
self.addContextMenuItem("Reset", doReset) 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 -- hotkeys
addHotkey("Bless Curse Status", printStatus, false) addHotkey("Bless Curse Status", printStatus, false)
@ -173,15 +157,13 @@ end
-- context menu function 2 -- context menu function 2
function doReset(color) function doReset(color)
-- delete previously pulled out tokens by the token arranger -- delete previously pulled out tokens by the token arranger
if tokenArranger then tokenArrangerApi.deleteCopiedTokens()
tokenArranger.call("deleteCopiedTokens")
end
playerColor = color playerColor = color
numInPlay = { Bless = 0, Curse = 0 } numInPlay = { Bless = 0, Curse = 0 }
tokensTaken = { Bless = {}, Curse = {} } tokensTaken = { Bless = {}, Curse = {} }
initializeState() initializeState()
updateTokenArranger() tokenArrangerApi.layout()
end end
--------------------------------------------------------- ---------------------------------------------------------
@ -263,18 +245,7 @@ function callFunctions(token, isRightClick)
success = takeToken(token, false) success = takeToken(token, false)
end end
end end
if success ~= 0 then updateTokenArranger() end if success ~= 0 then tokenArrangerApi.layout() 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 end
function getChaosBag() function getChaosBag()
@ -405,22 +376,22 @@ function addMenuOptions(playerColor, hoveredObject)
hoveredObject.addContextMenuItem("Seal Bless", function(color) hoveredObject.addContextMenuItem("Seal Bless", function(color)
sealToken("Bless", color, hoveredObject) sealToken("Bless", color, hoveredObject)
updateTokenArranger() tokenArrangerApi.layout()
end, true) end, true)
hoveredObject.addContextMenuItem("Release Bless", function(color) hoveredObject.addContextMenuItem("Release Bless", function(color)
releaseToken("Bless", color, hoveredObject) releaseToken("Bless", color, hoveredObject)
updateTokenArranger() tokenArrangerApi.layout()
end, true) end, true)
hoveredObject.addContextMenuItem("Seal Curse", function(color) hoveredObject.addContextMenuItem("Seal Curse", function(color)
sealToken("Curse", color, hoveredObject) sealToken("Curse", color, hoveredObject)
updateTokenArranger() tokenArrangerApi.layout()
end, true) end, true)
hoveredObject.addContextMenuItem("Release Curse", function(color) hoveredObject.addContextMenuItem("Release Curse", function(color)
releaseToken("Curse", color, hoveredObject) releaseToken("Curse", color, hoveredObject)
updateTokenArranger() tokenArrangerApi.layout()
end, true) end, true)
broadcastToColor("Right-click seal options added to " .. hoveredObject.getName(), playerColor) broadcastToColor("Right-click seal options added to " .. hoveredObject.getName(), playerColor)

View File

@ -845,9 +845,6 @@ function applyOptionPanelChange(id, state)
-- option: Show token arranger -- option: Show token arranger
elseif id == "showTokenArranger" then elseif id == "showTokenArranger" then
-- delete previously pulled out tokens
for _, token in ipairs(getObjectsWithTag("to_be_deleted")) do token.destruct() end
optionPanel[id] = spawnOrRemoveHelper(state, "Token Arranger", {-42.3, 1.6, -46.5}) optionPanel[id] = spawnOrRemoveHelper(state, "Token Arranger", {-42.3, 1.6, -46.5})
-- option: Show clean up helper -- option: Show clean up helper
@ -921,14 +918,7 @@ function spawnHelperObject(name, position, rotation)
return return
end end
local spawnTable = { local spawnTable = {position = position}
position = position,
callback_function = function(object)
if name == "Token Arranger" then
Wait.time(function() object.call("layout") end, 0.1)
end
end
}
-- only overrride rotation if there is one provided (object's rotation used instead) -- only overrride rotation if there is one provided (object's rotation used instead)
if rotation then if rotation then

View File

@ -1,5 +1,6 @@
local playArea = require("core/PlayAreaApi") local playAreaApi = require("core/PlayAreaApi")
local tokenSpawnTracker = require("core/token/TokenSpawnTrackerApi") local tokenArrangerApi = require("accessories/TokenArrangerApi")
local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi")
local ENCOUNTER_DECK_AREA = { local ENCOUNTER_DECK_AREA = {
upperLeft = { x = 0.9, z = 0.42 }, upperLeft = { x = 0.9, z = 0.42 },
@ -11,39 +12,65 @@ local ENCOUNTER_DISCARD_AREA = {
} }
local currentScenario local currentScenario
local useFrontData
local tokenData
-- we use this to turn off collision handling until onLoad() is complete -- we use this to turn off collision handling until onLoad() is complete
local COLLISION_ENABLED = false local collisionEnabled = false
function onLoad(saveState) function onLoad(saveState)
if saveState ~= nil then if saveState ~= nil then
local loadedState = JSON.decode(saveState) or { } local loadedState = JSON.decode(saveState) or {}
currentScenario = loadedState.currentScenario currentScenario = loadedState.currentScenario or ""
useFrontData = loadedState.useFrontData or true
tokenData = loadedState.tokenData or {}
end end
COLLISION_ENABLED = true collisionEnabled = true
end end
function onSave() function onSave()
return JSON.encode({ return JSON.encode({
currentScenario = currentScenario currentScenario = currentScenario,
useFrontData = useFrontData,
tokenData = tokenData
}) })
end end
-- TTS event handler. Handles scenario name event triggering and encounter card token resets. -- TTS event handler. Handles scenario name event triggering and encounter card token resets.
function onCollisionEnter(collisionInfo) function onCollisionEnter(collisionInfo)
if not COLLISION_ENABLED then if not collisionEnabled then
return return
end end
local object = collisionInfo.collision_object local object = collisionInfo.collision_object
if object.getName() == "Scenario" then if object.getName() == "Scenario" then
if currentScenario ~= object.getDescription() then local updateNeeded = false
currentScenario = object.getDescription() local description = object.getDescription()
-- detect if orientation of scenario card changed (flipped to other side)
if object.is_face_down == useFrontData then
useFrontData = not useFrontData
updateNeeded = true
end
-- detect if another scenario card is placed down
if currentScenario ~= description then
currentScenario = description
updateNeeded = true
fireScenarioChangedEvent() fireScenarioChangedEvent()
end end
-- trigger update if a change was detected and push new data
if updateNeeded then
local metadata = JSON.decode(object.getGMNotes()) or {}
if not metadata["tokens"] then return end
tokenData = metadata["tokens"][(useFrontData and "front" or "back")]
fireTokenDataChangedEvent()
end
end end
local localPos = self.positionToLocal(object.getPosition()) local localPos = self.positionToLocal(object.getPosition())
if inArea(localPos, ENCOUNTER_DECK_AREA) or inArea(localPos, ENCOUNTER_DISCARD_AREA) then if inArea(localPos, ENCOUNTER_DECK_AREA) or inArea(localPos, ENCOUNTER_DISCARD_AREA) then
tokenSpawnTracker.resetTokensSpawned(object.getGUID()) tokenSpawnTrackerApi.resetTokensSpawned(object.getGUID())
end end
end end
@ -52,13 +79,19 @@ end
function onObjectEnterContainer(container, object) function onObjectEnterContainer(container, object)
local localPos = self.positionToLocal(container.getPosition()) local localPos = self.positionToLocal(container.getPosition())
if inArea(localPos, ENCOUNTER_DECK_AREA) or inArea(localPos, ENCOUNTER_DISCARD_AREA) then if inArea(localPos, ENCOUNTER_DECK_AREA) or inArea(localPos, ENCOUNTER_DISCARD_AREA) then
tokenSpawnTracker.resetTokensSpawned(object.getGUID()) tokenSpawnTrackerApi.resetTokensSpawned(object.getGUID())
end end
end end
-- fires if the scenario title changes
function fireScenarioChangedEvent() function fireScenarioChangedEvent()
Wait.frames(function() Global.call('titleSplash', currentScenario) end, 20) Wait.frames(function() Global.call('titleSplash', currentScenario) end, 20)
playArea.onScenarioChanged(currentScenario) playAreaApi.onScenarioChanged(currentScenario)
end
-- fires if the scenario title or the difficulty changes
function fireTokenDataChangedEvent()
tokenArrangerApi.onTokenDataChanged(tokenData, currentScenario, tostring(useFrontData))
end end
-- Simple method to check if the given point is in a specified area. Local use only, -- Simple method to check if the given point is in a specified area. Local use only,