Updated campaign exporter and option panel
This commit is contained in:
parent
7ad53e2192
commit
e1428547b5
@ -56,13 +56,13 @@ function onLoad()
|
||||
})
|
||||
end
|
||||
|
||||
function onObjectLeaveContainer(container, _)
|
||||
function onObjectLeaveContainer(container)
|
||||
if container.hasTag("ImporterToken") then
|
||||
broadcastToAll("Removing objects from the Save Coin bag will break functionality. Please return the removed objects.", "Yellow")
|
||||
end
|
||||
end
|
||||
|
||||
function onObjectEnterContainer(container, _)
|
||||
function onObjectEnterContainer(container)
|
||||
if container.hasTag("ImporterToken") then
|
||||
broadcastToAll("Adding objects to the Save Coin bag will break functionality. Please remove the objects.", "Yellow")
|
||||
end
|
||||
@ -78,7 +78,7 @@ function onCollisionEnter(info)
|
||||
end
|
||||
end
|
||||
|
||||
-- Identifies import token, determines campaign box and downloads it (if needed)
|
||||
-- identifies import token, determines campaign box and downloads it (if needed)
|
||||
function importFromToken(coin)
|
||||
broadcastToAll("Campaign Import Initiated")
|
||||
local importData = JSON.decode(coin.getGMNotes())
|
||||
@ -115,7 +115,7 @@ function importFromToken(coin)
|
||||
)
|
||||
end
|
||||
|
||||
-- After box has been downloaded, places content on table
|
||||
-- after box has been downloaded, places content on table
|
||||
function placeCampaignFromToken(importData, coin)
|
||||
getObjectFromGUID(importData["box"]).call("buttonClick_place")
|
||||
Wait.condition(
|
||||
@ -126,31 +126,28 @@ function placeCampaignFromToken(importData, coin)
|
||||
)
|
||||
end
|
||||
|
||||
-- After content is placed on table, conducts all the other import operations
|
||||
-- after content is placed on table, conducts all the other import operations
|
||||
function restoreCampaignData(importData, coin)
|
||||
-- destroy existing campaign log
|
||||
findUniqueObjectWithTag("CampaignLog").destruct()
|
||||
-- go over internal items and respawn them (only storing campaign log and additional player cards)
|
||||
for _, objData in ipairs(coin.getData().ContainedObjects) do
|
||||
objData.Locked = true
|
||||
local spawnData = { data = objData }
|
||||
|
||||
-- destroy existing "additional player cards" bag
|
||||
if importData["additionalIndex"] then
|
||||
guidReferenceApi.getObjectByOwnerAndType("Mythos", "AdditionalPlayerCardsBag").destruct()
|
||||
end
|
||||
|
||||
if coin.type == "Bag" then
|
||||
-- go over internal items and spawn them at the original position
|
||||
for _, objData in ipairs(coin.getData().ContainedObjects) do
|
||||
objData["Locked"] = true
|
||||
spawnObjectData({data = objData})
|
||||
-- maybe restore position of item and destroy duplicate
|
||||
if objData.Nickname == "Additional Player Cards" then
|
||||
local additionalIndex = guidReferenceApi.getObjectByOwnerAndType("Mythos", "AdditionalPlayerCardsBag")
|
||||
spawnData.position = additionalIndex.getPosition()
|
||||
additionalIndex.destruct()
|
||||
else
|
||||
local campaignLog = findUniqueObjectWithTag("CampaignLog")
|
||||
if campaignLog then
|
||||
spawnData.position = campaignLog.getPosition()
|
||||
campaignLog.destruct()
|
||||
end
|
||||
end
|
||||
else
|
||||
-- support for older save coins that stored the data serialized
|
||||
if importData["additionalIndex"] then
|
||||
spawnObjectJSON({json = importData["additionalIndex"]})
|
||||
end
|
||||
spawnObjectData({data = importData["log"]})
|
||||
end
|
||||
|
||||
coin.destruct()
|
||||
spawnObjectData(spawnData)
|
||||
end
|
||||
|
||||
chaosBagApi.setChaosBagState(importData["bag"])
|
||||
|
||||
@ -164,21 +161,21 @@ function restoreCampaignData(importData, coin)
|
||||
deckImporterApi.setUiState(importData["decks"])
|
||||
end
|
||||
|
||||
playAreaApi.setInvestigatorCount(importData["clueCount"])
|
||||
|
||||
-- set campaign guide page
|
||||
local guide = findUniqueObjectWithTag("CampaignGuide")
|
||||
if guide then
|
||||
Wait.condition(
|
||||
-- Called after the condition function returns true
|
||||
function() printToAll("Campaign Guide import successful!") end,
|
||||
-- Condition function that is called continuously until it returns true or timeout is reached
|
||||
function() return guide.Book.setPage(importData["guide"]) end,
|
||||
-- Amount of time in seconds until the Wait times out
|
||||
2,
|
||||
-- Called if the Wait times out
|
||||
function() printToAll("Campaign Guide import failed!") end
|
||||
)
|
||||
-- maybe set campaign guide page
|
||||
if importData["guide"] then
|
||||
local campaignGuide = findUniqueObjectWithTag("CampaignGuide")
|
||||
if campaignGuide then
|
||||
Wait.condition(
|
||||
-- Called after the condition function returns true
|
||||
function() printToAll("Campaign Guide import successful!") end,
|
||||
-- Condition function that is called continuously until it returns true or timeout is reached
|
||||
function() return campaignGuide.Book.setPage(importData["guide"]) end,
|
||||
-- Amount of time in seconds until the Wait times out
|
||||
2,
|
||||
-- Called if the Wait times out
|
||||
function() printToAll("Campaign Guide import failed!") end
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
Wait.time(function() optionPanelApi.loadSettings(importData["options"]) end, 0.5)
|
||||
@ -189,14 +186,21 @@ function restoreCampaignData(importData, coin)
|
||||
tourStarter.destruct()
|
||||
end
|
||||
|
||||
-- restore PlayArea image
|
||||
-- restore PlayArea image and player count
|
||||
playAreaApi.updateSurface(importData["playarea"])
|
||||
playAreaApi.setInvestigatorCount(importData["clueCount"])
|
||||
|
||||
coin.destruct()
|
||||
broadcastToAll("Campaign successfully imported!", "Green")
|
||||
end
|
||||
|
||||
-- Creates a campaign token with save data encoded into GM Notes based on the current state of the table
|
||||
-- creates a campaign token with save data encoded into GM Notes based on the current state of the table
|
||||
function createCampaignToken(_, playerColor, _)
|
||||
local campaignData = {}
|
||||
|
||||
-- need to reset the contained objects to support multiple exports
|
||||
campaignTokenData.ContainedObjects = {}
|
||||
|
||||
-- find active campaign
|
||||
local campaignBox
|
||||
for _, obj in ipairs(getObjectsWithTag("CampaignBox")) do
|
||||
@ -204,7 +208,7 @@ function createCampaignToken(_, playerColor, _)
|
||||
if not campaignBox then
|
||||
campaignBox = obj
|
||||
else
|
||||
broadcastToAll("Multiple empty campaign box detected; delete all but one.", "Red")
|
||||
broadcastToAll("Multiple empty campaign boxes detected; delete all but one.", "Red")
|
||||
return
|
||||
end
|
||||
end
|
||||
@ -215,60 +219,55 @@ function createCampaignToken(_, playerColor, _)
|
||||
return
|
||||
end
|
||||
|
||||
local campaignLog = findUniqueObjectWithTag("CampaignLog")
|
||||
if campaignLog == nil then
|
||||
broadcastToAll("Campaign log not found!", "Red")
|
||||
return
|
||||
end
|
||||
|
||||
local additionalIndex = guidReferenceApi.getObjectByOwnerAndType("Mythos", "AdditionalPlayerCardsBag")
|
||||
local traumaValues = { }
|
||||
local trauma = campaignLog.getVar("returnTrauma")
|
||||
|
||||
if trauma ~= nil then
|
||||
printToAll("Trauma values found in campaign log!", "Green")
|
||||
trauma = campaignLog.call("returnTrauma")
|
||||
for _, val in ipairs(trauma) do
|
||||
table.insert(traumaValues, val)
|
||||
end
|
||||
else
|
||||
traumaValues = nil
|
||||
printToAll("Trauma values could not be found in campaign log!", "Yellow")
|
||||
end
|
||||
|
||||
local campaignGuide = findUniqueObjectWithTag("CampaignGuide")
|
||||
if campaignGuide == nil then
|
||||
broadcastToAll("Campaign guide not found!", "Red")
|
||||
return
|
||||
end
|
||||
|
||||
-- clean up chaos tokens
|
||||
-- clean up chaos tokens (needs to happen before saving chaos bag state)
|
||||
blessCurseApi.removeAll(playerColor)
|
||||
chaosBagApi.releaseAllSealedTokens(playerColor)
|
||||
|
||||
local campaignData = {
|
||||
box = campaignBox.getGUID(),
|
||||
log = campaignLog.getPosition(),
|
||||
bag = chaosBagApi.getChaosBagState(),
|
||||
trauma = traumaValues,
|
||||
decks = deckImporterApi.getUiState(),
|
||||
clueCount = playAreaApi.getInvestigatorCount(),
|
||||
playarea = playAreaApi.getSurface(),
|
||||
options = optionPanelApi.getOptions(),
|
||||
guide = campaignGuide.Book.getPage(),
|
||||
additionalIndex = additionalIndex.getPosition()
|
||||
}
|
||||
-- main data collection
|
||||
campaignData.box = campaignBox.getGUID()
|
||||
campaignData.bag = chaosBagApi.getChaosBagState()
|
||||
campaignData.decks = deckImporterApi.getUiState()
|
||||
campaignData.clueCount = playAreaApi.getInvestigatorCount()
|
||||
campaignData.playarea = playAreaApi.getSurface()
|
||||
campaignData.options = optionPanelApi.getOptions()
|
||||
|
||||
-- save campaign log if present
|
||||
local campaignLog = findUniqueObjectWithTag("CampaignLog")
|
||||
if campaignLog then
|
||||
local logData = campaignLog.getData()
|
||||
logData.Locked = false
|
||||
table.insert(campaignTokenData.ContainedObjects, logData)
|
||||
|
||||
-- maybe also extract the trauma values
|
||||
local trauma = campaignLog.getVar("returnTrauma")
|
||||
if trauma then
|
||||
printToAll("Trauma values found in campaign log!", "Green")
|
||||
campaignData.trauma = {}
|
||||
for _, val in ipairs(campaignLog.call("returnTrauma")) do
|
||||
table.insert(campaignData.trauma, val)
|
||||
end
|
||||
else
|
||||
printToAll("Trauma values could not be found in campaign log!", "Yellow")
|
||||
end
|
||||
end
|
||||
|
||||
-- store campaign guide page if present
|
||||
local campaignGuide = findUniqueObjectWithTag("CampaignGuide")
|
||||
if campaignGuide then
|
||||
campaignData.guide = campaignGuide.Book.getPage()
|
||||
end
|
||||
|
||||
-- store the additional index if there are any cards in it
|
||||
local additionalIndex = guidReferenceApi.getObjectByOwnerAndType("Mythos", "AdditionalPlayerCardsBag")
|
||||
if additionalIndex and #additionalIndex.getObjects() > 0 then
|
||||
local indexData = additionalIndex.getData()
|
||||
indexData.Locked = false
|
||||
table.insert(campaignTokenData.ContainedObjects, indexData)
|
||||
end
|
||||
|
||||
-- finish the data for the campaign token
|
||||
campaignTokenData.GMNotes = JSON.encode(campaignData)
|
||||
campaignTokenData.Nickname = campaignBox.getName() .. os.date(" %b %d") .. " Save"
|
||||
campaignTokenData.ContainedObjects = { }
|
||||
|
||||
local indexData = additionalIndex.getData()
|
||||
indexData.Locked = false
|
||||
table.insert(campaignTokenData.ContainedObjects, indexData)
|
||||
|
||||
local logData = campaignLog.getData()
|
||||
logData.Locked = false
|
||||
table.insert(campaignTokenData.ContainedObjects, logData)
|
||||
|
||||
spawnObjectData({ data = campaignTokenData })
|
||||
broadcastToAll("Campaign successfully exported! Save coin object to import on a different save.", "Green")
|
||||
|
@ -54,7 +54,7 @@ local tabIdTable = {
|
||||
tab5 = "fanmadePlayerCards"
|
||||
}
|
||||
|
||||
-- optionPanel data
|
||||
-- optionPanel data (intentionally not local!)
|
||||
optionPanel = {}
|
||||
local LANGUAGES = {
|
||||
{ code = "zh_CN", name = "简体中文" },
|
||||
@ -762,7 +762,6 @@ end
|
||||
|
||||
-- returns all sealed tokens on cards to the chaos bag
|
||||
function releaseAllSealedTokens(playerColor)
|
||||
local chaosBag = findChaosBag()
|
||||
for _, obj in ipairs(getObjectsWithTag("CardThatSeals")) do
|
||||
obj.call("releaseAllTokens", playerColor)
|
||||
end
|
||||
@ -1331,17 +1330,16 @@ end
|
||||
|
||||
-- called by toggling an option
|
||||
function onClick_toggleOption(_, id)
|
||||
local state = self.UI.getAttribute(id, "isOn")
|
||||
local toggleState = self.UI.getAttribute(id, "isOn")
|
||||
|
||||
-- flip state (and handle stupid "False" value)
|
||||
if state == "False" then
|
||||
state = true
|
||||
-- flip state (and handle stupid "False" values)
|
||||
if toggleState == "False" then
|
||||
self.UI.setAttribute(id, "isOn", true)
|
||||
applyOptionPanelChange(id, true)
|
||||
else
|
||||
state = false
|
||||
self.UI.setAttribute(id, "isOn", "False")
|
||||
applyOptionPanelChange(id, false)
|
||||
end
|
||||
|
||||
self.UI.setAttribute(id, "isOn", state)
|
||||
applyOptionPanelChange(id, state)
|
||||
end
|
||||
|
||||
-- color selection for playArea
|
||||
@ -1439,24 +1437,23 @@ function updateOptionPanelState()
|
||||
end
|
||||
end
|
||||
|
||||
-- handles the applying of option selections and calls the respective functions based
|
||||
-- handles the applying of option selections and calls the respective functions based on the id
|
||||
---@param id string ID of the option that was selected or deselected
|
||||
---@param state boolean|any State of the option (true = enabled)
|
||||
function applyOptionPanelChange(id, state)
|
||||
optionPanel[id] = state
|
||||
|
||||
-- option: Snap tags
|
||||
if id == "useSnapTags" then
|
||||
playmatApi.setLimitSnapsByType(state, "All")
|
||||
optionPanel[id] = state
|
||||
|
||||
-- option: Draw 1 button
|
||||
elseif id == "showDrawButton" then
|
||||
playmatApi.showDrawButton(state, "All")
|
||||
optionPanel[id] = state
|
||||
|
||||
-- option: Clickable clue counters
|
||||
elseif id == "useClueClickers" then
|
||||
playmatApi.clickableClues(state, "All")
|
||||
optionPanel[id] = state
|
||||
|
||||
-- update master clue counter
|
||||
local counter = guidReferenceApi.getObjectByOwnerAndType("Mythos", "MasterClueCounter")
|
||||
@ -1465,52 +1462,39 @@ function applyOptionPanelChange(id, state)
|
||||
-- option: Play area snap tags
|
||||
elseif id == "playAreaConnections" then
|
||||
playAreaApi.setConnectionDrawState(state)
|
||||
optionPanel[id] = state
|
||||
|
||||
-- option: Play area connection color
|
||||
elseif id == "playAreaConnectionColor" then
|
||||
playAreaApi.setConnectionColor(state)
|
||||
UI.setAttribute(id, "color", "#" .. Color.new(state):toHex())
|
||||
optionPanel[id] = state
|
||||
|
||||
-- option: Play area snap tags
|
||||
elseif id == "playAreaSnapTags" then
|
||||
playAreaApi.setLimitSnapsByType(state)
|
||||
optionPanel[id] = state
|
||||
|
||||
-- option: Show Title on placing scenarios
|
||||
elseif id == "showTitleSplash" then
|
||||
optionPanel[id] = state
|
||||
|
||||
-- option: Change custom playarea image on setup
|
||||
elseif id == "changePlayAreaImage" then
|
||||
optionPanel[id] = state
|
||||
|
||||
-- option: Show clean up helper
|
||||
elseif id == "showCleanUpHelper" then
|
||||
optionPanel[id] = spawnOrRemoveHelper(state, "Clean Up Helper", { -66, 1.6, 46 })
|
||||
spawnOrRemoveHelper(state, "Clean Up Helper", { -66, 1.6, 46 })
|
||||
|
||||
-- option: Show hand helper for each player
|
||||
elseif id == "showHandHelper" then
|
||||
spawnOrRemoveHelperForPlayermats("Hand Helper", state)
|
||||
optionPanel[id] = state
|
||||
|
||||
-- option: Show search assistant for each player
|
||||
elseif id == "showSearchAssistant" then
|
||||
spawnOrRemoveHelperForPlayermats("Search Assistant", state)
|
||||
optionPanel[id] = state
|
||||
|
||||
-- option: Show attachment helper
|
||||
elseif id == "showAttachmentHelper" then
|
||||
optionPanel[id] = spawnOrRemoveHelper(state, "Attachment Helper", { -62, 1.4, 0 })
|
||||
spawnOrRemoveHelper(state, "Attachment Helper", { -62, 1.4, 0 })
|
||||
|
||||
-- option: Show CYOA campaign guides
|
||||
elseif id == "showCYOA" then
|
||||
optionPanel[id] = spawnOrRemoveHelper(state, "CYOA Campaign Guides", { 39, 1.3, -20 })
|
||||
spawnOrRemoveHelper(state, "CYOA Campaign Guides", { 39, 1.3, -20 })
|
||||
|
||||
-- option: Show displacement tool
|
||||
elseif id == "showDisplacementTool" then
|
||||
optionPanel[id] = spawnOrRemoveHelper(state, "Displacement Tool", { -57, 1.6, 46 })
|
||||
spawnOrRemoveHelper(state, "Displacement Tool", { -57, 1.6, 46 })
|
||||
end
|
||||
end
|
||||
|
||||
@ -1537,7 +1521,7 @@ function spawnOrRemoveHelper(state, name, position, rotation, owner)
|
||||
local cleanName = name:gsub("%s+", "")
|
||||
guidReferenceApi.editIndex(owner or "Mythos", cleanName, spawnedGUID)
|
||||
else
|
||||
return removeHelperObject(name)
|
||||
removeHelperObject(name)
|
||||
end
|
||||
end
|
||||
|
||||
@ -1597,15 +1581,6 @@ end
|
||||
|
||||
-- loads the default options
|
||||
function onClick_defaultSettings()
|
||||
for id, _ in pairs(optionPanel) do
|
||||
local state = false
|
||||
-- override for settings that are enabled by default
|
||||
if id == "useSnapTags" or id == "showTitleSplash" then
|
||||
state = true
|
||||
end
|
||||
applyOptionPanelChange(id, state)
|
||||
end
|
||||
|
||||
-- clean reset of variables
|
||||
optionPanel = {
|
||||
cardLanguage = "en",
|
||||
@ -1626,6 +1601,11 @@ function onClick_defaultSettings()
|
||||
useSnapTags = true
|
||||
}
|
||||
|
||||
-- applying changes
|
||||
for id, state in pairs(optionPanel) do
|
||||
applyOptionPanelChange(id, state)
|
||||
end
|
||||
|
||||
-- update UI
|
||||
updateOptionPanelState()
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user