initial commit

This commit is contained in:
Chr1Z93 2024-02-19 11:13:18 +01:00
parent 5e7ef9947c
commit 6d1bf009b5
4 changed files with 81 additions and 119 deletions

View File

@ -15,9 +15,9 @@
],
"Autoraise": true,
"ColorDiffuse": {
"b": 1,
"g": 1,
"r": 1
"b": 0,
"g": 0,
"r": 0
},
"CustomImage": {
"CustomTile": {
@ -28,7 +28,7 @@
},
"ImageScalar": 1,
"ImageSecondaryURL": "",
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/254843371583173230/BECDC34EB4D2C8C5F9F9933C97085F82A2F21AE3/",
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/2503508192913854749/B7CFE8596F3ED5BCEBD3CD59DF1CE88991AA923F/",
"WidthScale": 0
},
"Description": "Saves the state of the table to enable loading the campaign into a new save and keep all current progress.\n\nThis tool will track which campaign you're playing, the entire contents of your campaign log, the contents of your chaos bag, update your health/sanity according to trauma, your ArkhamDB deck IDs, the number of investigators, the page of your campaign guide, cards in the Additional Player Cards bag and any options you have selected in the options panel.\n\nFor saving trauma values to correct seats, ensure investigators in the campaign log are in the following order: White, Orange, Green, Red\n\nFor custom campaigns, ensure: 1) Campaign Box, Campaign Log, and Campaign Guide each have the corresponding tag, 2)The Campaign Box is on the table when you import or export.",

View File

@ -6,8 +6,7 @@ local optionPanelApi = require("core/OptionPanelApi")
local playAreaApi = require("core/PlayAreaApi")
local playmatApi = require("playermat/PlaymatApi")
local checkWarning = true
-- base data for token creation
local campaignTokenData = {
Name = "Custom_Model_Bag",
Transform = {
@ -22,31 +21,26 @@ local campaignTokenData = {
scaleZ = 2
},
Description = "SCED Importer Token",
Tags = {
"ImporterToken"
},
Tags = { "ImporterToken" },
CustomMesh = {
MeshURL = "http://cloud-3.steamusercontent.com/ugc/943949966265929204/A38BB5D72419E6298385556D931877C0A1A55C17/",
DiffuseURL = "http://cloud-3.steamusercontent.com/ugc/254843371583188147/920981125E37B5CEB6C400E3FD353A2C428DA969/",
NormalURL = "",
ColliderURL = "http://cloud-3.steamusercontent.com/ugc/943949966265929204/A38BB5D72419E6298385556D931877C0A1A55C17/",
Convex = true,
MaterialIndex = 2,
TypeIndex = 6,
CustomShader = {
SpecularColor = {
r = 0.7222887,
g = 0.507659256,
b = 0.339915335
r = 0.72,
g = 0.51,
b = 0.34
},
SpecularIntensity = 0.4,
SpecularSharpness = 7.0,
FresnelStrength = 0.0
},
CastShadows = true
}
}
}
local COLORS = { "White", "Orange", "Green", "Red" }
function onLoad()
self.createButton({
@ -58,25 +52,19 @@ function onLoad()
font_size = 400,
width = 1400,
height = 600,
scale = { 0.5, 1, 0.5 },
scale = { 0.5, 1, 0.5 }
})
end
function onObjectLeaveContainer(container, object)
if container.hasTag("ImporterToken") and checkWarning then
broadcastToAll(
"Removing objects from the Save Coin bag will break functionality. Please replace the objects in the same order they were removed.",
Color.Yellow
)
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, object)
if container.hasTag("ImporterToken") and checkWarning then
broadcastToAll(
"Adding objects to the Save Coin bag will break functionality. Please remove the objects.",
Color.Yellow
)
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
end
@ -94,18 +82,20 @@ end
function importFromToken(coin)
broadcastToAll("Campaign Import Initiated")
local importData = JSON.decode(coin.getGMNotes())
local campaignBox = getObjectFromGUID(importData["box"])
local campaignBoxGUID = importData["box"]
local campaignBox = getObjectFromGUID(campaignBoxGUID)
if not campaignBox then
broadcastToAll("Campaign Box not present on table!", Color.Red)
broadcastToAll("Campaign Box not present on table!", "Red")
return
end
if campaignBox.type == "Generic" then
campaignBox.call("buttonClick_download")
end
Wait.condition(
function()
local campaignBox = getObjectFromGUID(importData["box"])
if #campaignBox.getObjects() > 0 then
placeCampaignFromToken(importData, coin)
else
@ -113,11 +103,11 @@ function importFromToken(coin)
end
end,
function()
local obj = getObjectFromGUID(campaignBoxGUID)
local obj = getObjectFromGUID(importData["box"])
if obj == nil then
return false
else
return obj.type == "Bag" and obj.getLuaScript() ~= ""
return obj.type == "Bag"
end
end,
2,
@ -138,27 +128,29 @@ end
-- After content is placed on table, conducts all the other import operations
function restoreCampaignData(importData, coin)
-- destroy existing campaign log
findUniqueObjectWithTag("CampaignLog").destruct()
checkWarning = false
-- destroy existing "additional player cards" bag
if importData["additionalIndex"] then
guidReferenceApi.getObjectByOwnerAndType("Mythos", "AdditionalPlayerCardsBag").destruct()
if coin.type == "Bag" then
coin.takeObject({index = 0, position = importData["additionalIndex"], callback_function = function(obj) obj.setLock(true) end})
else
spawnObjectJSON({json = importData["additionalIndex"]})
end
end
-- destroy existing campaign log and load saved campaign log
findUniqueObjectWithTag("CampaignLog").destruct()
if coin.type == "Bag" then
local newLog = coin.takeObject({index = 0, position = importData["log"], callback_function = function(obj) obj.setLock(true) end})
-- 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})
end
else
spawnObjectData({ data = importData["log"] })
-- 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()
checkWarning = true
chaosBagApi.setChaosBagState(importData["bag"])
@ -179,13 +171,13 @@ function restoreCampaignData(importData, coin)
if guide then
Wait.condition(
-- Called after the condition function returns true
function() log("Campaign Guide import successful!") end,
-- Condition function that is called continiously until returs true or timeout is reached
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() log("Campaign Guide import failed!") end
function() printToAll("Campaign Guide import failed!") end
)
end
@ -200,12 +192,11 @@ function restoreCampaignData(importData, coin)
-- restore PlayArea image
playAreaApi.updateSurface(importData["playarea"])
broadcastToAll("Campaign successfully imported!", Color.Green)
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
function createCampaignToken(_, playerColor, _)
-- find active campaign
local campaignBox
for _, obj in ipairs(getObjectsWithTag("CampaignBox")) do
@ -213,24 +204,24 @@ function createCampaignToken(_, playerColor, _)
if not campaignBox then
campaignBox = obj
else
broadcastToAll("Multiple empty campaign box detected; delete all but one.", Color.Red)
broadcastToAll("Multiple empty campaign box detected; delete all but one.", "Red")
return
end
end
end
if not campaignBox then
broadcastToAll("Campaign box with all placed objects not found!", Color.Red)
broadcastToAll("Campaign box with all placed objects not found!", "Red")
return
end
local campaignLog = findUniqueObjectWithTag("CampaignLog")
if campaignLog == nil then
broadcastToAll("Campaign log not found!", Color.Red)
broadcastToAll("Campaign log not found!", "Red")
return
end
local additionalIndex = guidReferenceApi.getObjectByOwnerAndType("Mythos", "AdditionalPlayerCardsBag")
local traumaValues = { }
local trauma = campaignLog.getVar("returnTrauma")
@ -241,12 +232,12 @@ function createCampaignToken(_, playerColor, _)
table.insert(traumaValues, val)
end
else
printToAll("Trauma values could not be found in campaign log!", "Yellow")
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!", Color.Red)
broadcastToAll("Campaign guide not found!", "Red")
return
end
@ -269,14 +260,17 @@ function createCampaignToken(_, playerColor, _)
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 fresh save", Color.Green)
broadcastToAll("Campaign successfully exported! Save coin object to import on a different save.", "Green")
end
---------------------------------------------------------
@ -290,27 +284,13 @@ function findUniqueObjectWithTag(tag)
if #objects == 1 then
return objects[1]
else
broadcastToAll("More than 1 " .. tag .. " detected; delete all but one.", Color.Red)
return nil
broadcastToAll("More than one " .. tag .. " detected; delete all but one.", "Red")
end
end
function setTrauma(trauma)
for i = 1, 4 do
playmatApi.updateCounter(COLORS[i], "DamageCounter", trauma[i])
playmatApi.updateCounter(COLORS[i], "HorrorCounter", trauma[i + 4])
end
end
-- gets data from campaign log if possible
function loadTrauma(log)
local trauma = log.getVar("returnTrauma")
if trauma ~= nil then
printToAll("Trauma values found in campaign log!", "Green")
trauma = log.call("returnTrauma")
return trauma
else
return nil
for i, matColor in ipairs({ "White", "Orange", "Green", "Red" }) do
playmatApi.updateCounter(matColor, "DamageCounter", trauma[i])
playmatApi.updateCounter(matColor, "HorrorCounter", trauma[i + 4])
end
end

View File

@ -625,7 +625,7 @@ function setChaosBagState(tokenList)
-- reset bless / curse manager
blessCurseManagerApi.removeTakenTokensAndReset()
printToAll("Chaos bag set to chosen difficulty.", "Green")
printToAll("Chaos Bag set to chosen difficulty.", "Green")
end
-- spawns the specified chaos token and puts it into the chaos bag
@ -1369,22 +1369,24 @@ function applyOptionPanelChange(id, state)
elseif id == "showHandHelper" then
local helperName = "Hand Helper"
local spawnData = playmatApi.getHelperSpawnData("All", helperName)
local i = 0
for color, data in pairs(spawnData) do
i = i + 1
optionPanel[id][i] = spawnOrRemoveHelper(state, helperName, data.position, data.rotation, color)
spawnOrRemoveHelper(state, helperName, data.position, data.rotation, color)
end
optionPanel[id] = state
-- option: Show search assistant for each player
elseif id == "showSearchAssistant" then
local helperName = "Search Assistant"
local spawnData = playmatApi.getHelperSpawnData("All", helperName)
local i = 0
for color, data in pairs(spawnData) do
i = i + 1
optionPanel[id][i] = spawnOrRemoveHelper(state, helperName, data.position, data.rotation, color)
spawnOrRemoveHelper(state, helperName, data.position, data.rotation, color)
end
optionPanel[id] = state
-- option: Show attachment helper
elseif id == "showAttachmentHelper" then
optionPanel[id] = spawnOrRemoveHelper(state, "Attachment Helper", {-62, 1.4, 0})
@ -1407,14 +1409,11 @@ end
---@param owner? string Owner of the object (defaults to "Mythos")
---@return string|nil GUID GUID of the spawnedObj (or nil if object was removed)
function spawnOrRemoveHelper(state, name, position, rotation, owner)
if (type(state) == "table" and #state == 0) then
return removeHelperObject(name)
elseif state then
if state then
Player.getPlayers()[1].pingTable(position)
local spawnedGUID = spawnHelperObject(name, position, rotation).getGUID()
local cleanName = name:gsub("%s+", "")
guidReferenceApi.editIndex(owner or "Mythos", cleanName, spawnedGUID)
return spawnedGUID
else
return removeHelperObject(name)
end
@ -1454,41 +1453,24 @@ end
-- removes the specified tool (by name)
---@param name string Object that should be removed
function removeHelperObject(name)
-- links objects name to the respective option name (to grab the GUID for removal)
local referenceTable = {
["Clean Up Helper"] = "showCleanUpHelper",
["Hand Helper"] = "showHandHelper",
["Search Assistant"] = "showSearchAssistant",
["Displacement Tool"] = "showDisplacementTool",
["Attachment Helper"] = "showAttachmentHelper",
["CYOA Campaign Guides"] = "showCYOA"
}
local data = optionPanel[referenceTable[name]]
-- if there is a GUID stored, remove that object
if type(data) == "string" then
local obj = getObjectFromGUID(data)
if obj then obj.destruct() end
-- if it is a table (e.g. for the "Hand Helper", remove all of them)
elseif type(data) == "table" then
for _, guid in pairs(data) do
local obj = getObjectFromGUID(guid)
if obj then obj.destruct() end
end
local cleanName = name:gsub("%s+", "")
for _, obj in pairs(guidReferenceApi.getObjectsByType(cleanName)) do
obj.destruct()
end
end
-- loads saved options
---@param newOptions table Contains the new state for the option panel
function loadSettings(newOptions)
-- TO-DO: instead of overriding, keep original table and only add new data
-- this will ensure that new options aren't set to nil when importing an old state
optionPanel = newOptions
updateOptionPanelState()
for id, state in pairs(optionPanel) do
applyOptionPanelChange(id, state)
for id, state in pairs(newOptions) do
if optionPanel[id] ~= state then
optionPanel[id] = state
applyOptionPanelChange(id, state)
end
end
-- update XML UI state
updateOptionPanelState()
end
-- loads the default options
@ -1513,8 +1495,8 @@ function onClick_defaultSettings()
showCYOA = false,
showDisplacementTool = false,
showDrawButton = false,
showHandHelper = {},
showSearchAssistant = {},
showHandHelper = false,
showSearchAssistant = false,
showTitleSplash = true,
useClueClickers = false,
useResourceCounters = "disabled",

View File

@ -86,10 +86,10 @@ function updateSurface(newURL)
if newURL ~= "" and newURL ~= nil and newURL ~= DEFAULT_URL then
customInfo.image = newURL
broadcastToAll("New Playarea Image Applied", { 0.2, 0.9, 0.2 })
broadcastToAll("New Playarea Image Applied", "Green")
else
customInfo.image = DEFAULT_URL
broadcastToAll("Default Playarea Image Applied", { 0.2, 0.9, 0.2 })
broadcastToAll("Default Playarea Image Applied", "Green")
end
self.setCustomObject(customInfo)