initial feature implementation

This commit is contained in:
Chr1Z93 2024-07-29 20:08:10 +02:00
parent 62d9671864
commit 6c3306e4dd
38 changed files with 75 additions and 96 deletions

View File

@ -33,7 +33,7 @@
},
"Description": "Challenge Scenario",
"DragSelectable": true,
"GMNotes": "scenarios/challenge_all_or_nothing.json",
"GMNotes": "challenge_all_or_nothing",
"GUID": "72ab92",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "Challenge Scenario",
"DragSelectable": true,
"GMNotes": "scenarios/challenge_bad_blood.json",
"GMNotes": "challenge_bad_blood",
"GUID": "451eaa",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "Challenge Scenario",
"DragSelectable": true,
"GMNotes": "scenarios/challenge_by_the_book.json",
"GMNotes": "challenge_by_the_book",
"GUID": "cc7eb3",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "Challenge Scenario",
"DragSelectable": true,
"GMNotes": "scenarios/challenge_laid_to_rest.json",
"GMNotes": "challenge_laid_to_rest",
"GUID": "e2dd57",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "Challenge Scenario",
"DragSelectable": true,
"GMNotes": "scenarios/challenge_read_or_die.json",
"GMNotes": "challenge_read_or_die",
"GUID": "9e73fa",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "Challenge Scenario",
"DragSelectable": true,
"GMNotes": "scenarios/challenge_red_tide_rising.json",
"GMNotes": "challenge_red_tide_rising",
"GUID": "5302f2",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "Challenge Scenario",
"DragSelectable": true,
"GMNotes": "scenarios/challenge_relics_of_the_past.json",
"GMNotes": "challenge_relics_of_the_past",
"GUID": "0d6da1",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/night_of_the_zealot.json",
"GMNotes": "night_of_the_zealot",
"GUID": "64a613",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/edge_of_the_earth.json",
"GMNotes": "edge_of_the_earth",
"GUID": "895eaa",
"Grid": true,
"GridProjection": false,

View File

@ -32,7 +32,7 @@
},
"Description": "Use the context menu to download the encounter sets by cycle.",
"DragSelectable": true,
"GMNotes": "extras/encounter_sets.json",
"GMNotes": "encounter_sets",
"GUID": "304ffc",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "by Lemmingrad",
"DragSelectable": true,
"GMNotes": "extras/arkham_fantasy_minicards.json",
"GMNotes": "arkham_fantasy_minicards",
"GUID": "e17c9e",
"Grid": true,
"GridProjection": false,

View File

@ -23,7 +23,7 @@
},
"Description": "by RudeRugg",
"DragSelectable": true,
"GMNotes": "fancreations/campaign_lovecrafter_3077.json",
"GMNotes": "lovecrafter_3077",
"GUID": "b08d20",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "by Antimarkovnikov",
"DragSelectable": true,
"GMNotes": "extras/cyoa_campaign_guides.json",
"GMNotes": "cyoa_campaign_guides",
"GUID": "e87ea2",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/return_to_tcu.json",
"GMNotes": "return_to_tcu",
"GUID": "757324",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/return_to_tdl.json",
"GMNotes": "return_to_tdl",
"GUID": "ce9130",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/return_to_tfa.json",
"GMNotes": "return_to_tfa",
"GUID": "479ff3",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/return_to_tptc.json",
"GMNotes": "return_to_tptc",
"GUID": "e9889a",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/return_to_notz.json",
"GMNotes": "return_to_notz",
"GUID": "56270d",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "Investigators must spend 3XP each to play this side-mission",
"DragSelectable": true,
"GMNotes": "scenarios/carnevale_of_horrors.json",
"GMNotes": "carnevale_of_horrors",
"GUID": "23dd51",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "Investigators must spend 1XP each to play this side-mission",
"DragSelectable": true,
"GMNotes": "scenarios/curse_of_the_rougarou.json",
"GMNotes": "curse_of_the_rougarou",
"GUID": "db7039",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "scenarios/fortune_and_folly.json",
"GMNotes": "fortune_and_folly",
"GUID": "0dce91",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "Official side-mission",
"DragSelectable": true,
"GMNotes": "scenarios/guardians_of_the_abyss.json",
"GMNotes": "guardians_of_the_abyss",
"GUID": "ee987d",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "Scenario Pack",
"DragSelectable": true,
"GMNotes": "scenarios/machinations_through_time.json",
"GMNotes": "machinations_through_time",
"GUID": "3c4f3c",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "scenarios/murder_at_the_excelsior_hotel.json",
"GMNotes": "murder_at_the_excelsior_hotel",
"GUID": "01d780",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "Scenario Pack",
"DragSelectable": true,
"GMNotes": "scenarios/blob_that_ate_everything.json",
"GMNotes": "blob_that_ate_everything",
"GUID": "4dee5a",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "Beyond the Veil",
"DragSelectable": true,
"GMNotes": "scenarios/labyrinths_of_lunacy.json",
"GMNotes": "labyrinths_of_lunacy",
"GUID": "4c173f",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "Barkham Horror",
"DragSelectable": true,
"GMNotes": "scenarios/meddling_of_meowlathotep.json",
"GMNotes": "meddling_of_meowlathotep",
"GUID": "d02940",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "Scenario Pack",
"DragSelectable": true,
"GMNotes": "scenarios/war_of_the_outer_gods.json",
"GMNotes": "war_of_the_outer_gods",
"GUID": "fc7674",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/circle_undone.json",
"GMNotes": "the_circle_undone",
"GUID": "63e097",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/dream_eaters.json",
"GMNotes": "the_dream_eaters",
"GUID": "a16a1a",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/dunwich_legacy.json",
"GMNotes": "the_dunwich_legacy",
"GUID": "2898f6",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/the_feast_of_hemlock_vale.json",
"GMNotes": "the_feast_of_hemlock_vale",
"GUID": "c740af",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/forgotten_age.json",
"GMNotes": "the_forgotten_age",
"GUID": "0bcf19",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/innsmouth_conspiracy.json",
"GMNotes": "the_innsmouth_conspiracy",
"GUID": "465aab",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/path_to_carcosa.json",
"GMNotes": "the_path_to_carcosa",
"GUID": "aca04c",
"Grid": true,
"GridProjection": false,

View File

@ -33,7 +33,7 @@
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/the_scarlet_keys.json",
"GMNotes": "the_scarlet_keys",
"GUID": "300fcc",
"Grid": true,
"GridProjection": false,

View File

@ -28,7 +28,7 @@ end
function buttonClick_download(_, playerColor)
Global.call('placeholder_download', {
url = self.getGMNotes(),
filename = self.getGMNotes(),
player = playerColor and Player[playerColor] or nil,
replace = self.guid
})

View File

@ -41,17 +41,17 @@ local hideTitleSplashWaitFunctionId = nil
-- online functionality related variables
local MOD_VERSION = "3.9.0"
local SOURCE_REPO = 'https://raw.githubusercontent.com/chr1z93/loadable-objects/main'
local SOURCE_REPO = "https://github.com/Chr1Z93/SCED-downloads/releases/latest/download/"
local library, requestObj, modMeta
local acknowledgedUpgradeVersions = {}
local contentToShow = "campaigns"
local contentToShow = "campaign"
local currentListItem = 1
local tabIdTable = {
tab1 = "campaigns",
tab2 = "scenarios",
tab3 = "fanmadeCampaigns",
tab4 = "fanmadeScenarios",
tab5 = "fanmadePlayerCards"
tab1 = "campaign",
tab2 = "scenario",
tab3 = "fanmade-campaign",
tab4 = "fanmade-scenario",
tab5 = "fanmade-playercards"
}
-- optionPanel data (intentionally not local!)
@ -151,7 +151,7 @@ function onLoad(savedData)
-- initialization of loadable objects library (delay to let Navigation Overlay build)
Wait.time(function()
WebRequest.get(SOURCE_REPO .. '/library.json', libraryDownloadCallback)
WebRequest.get(SOURCE_REPO .. 'library.json', libraryDownloadCallback)
end, 1)
end
@ -1020,7 +1020,7 @@ function placeholder_download(params)
return 1
end
local url = SOURCE_REPO .. '/' .. params.url
local url = SOURCE_REPO .. params.filename .. ".json"
requestObj = WebRequest.get(url, function(request) contentDownloadCallback(request, params) end)
startLuaCoroutine(Global, 'downloadCoroutine')
end
@ -1066,7 +1066,7 @@ function coroutineDownloadAll()
broadcastToAll("Downloading " .. contentType .. "...")
local contained = ""
for _, params in ipairs(objectList) do
local request = WebRequest.get(SOURCE_REPO .. '/' .. params.url, function() end)
local request = WebRequest.get(SOURCE_REPO .. params.filename .. ".json", function() end)
local start = os.time()
while true do
if request.is_done then
@ -1141,7 +1141,7 @@ function onClick_spawnPlaceholder(player)
placeholder.setColorTint({ 1, 1, 1, 71 / 255 })
placeholder.setName(item.name)
placeholder.setDescription("by " .. (item.author or "Unknown"))
placeholder.setGMNotes(item.url)
placeholder.setGMNotes(item.filename)
placeholder.setLuaScript(dummy.getLuaScript())
Player.getPlayers()[1].pingTable(spawnPos)
@ -1229,8 +1229,7 @@ end
-- updates the preview window
function updatePreviewWindow()
local item = library[contentToShow][currentListItem]
local tempImage =
"https://steamusercontent-a.akamaihd.net/ugc/2115061845788345842/2CD6ABC551555CCF58F9D0DDB7620197BA398B06/"
local tempImage = "https://steamusercontent-a.akamaihd.net/ugc/2115061845788345842/2CD6ABC551555CCF58F9D0DDB7620197BA398B06/"
-- set default image if not defined
if item.boxsize == nil or item.boxsize == "" or item.boxart == nil or item.boxart == "" then
@ -1276,36 +1275,22 @@ function updatePreviewWindow()
end
-- formats the json response from the webrequest into a key-value lua table
-- strips the prefix from the community content items
function formatLibrary(json_response)
function formatLibrary(jsonResponse)
library = {}
library["campaigns"] = json_response.campaigns
library["scenarios"] = json_response.scenarios
library["extras"] = json_response.extras
library["fanmadeCampaigns"] = {}
library["fanmadeScenarios"] = {}
library["fanmadePlayerCards"] = {}
for _, item in ipairs(json_response.community) do
local identifier = nil
for str in string.gmatch(item.name, "([^:]+)") do
if not identifier then
-- grab the first part to know the content type
identifier = str
else
-- update the name without the content type
item.name = str
break
end
for _, item in ipairs(jsonResponse["content"]) do
local contentType = item["type"]
-- add "fanmade" for unofficial content
if item["author"] ~= "Fantasy Flight Games" then
contentType = "fanmade-" .. contentType
end
if identifier == "Fan Investigators" then
table.insert(library["fanmadePlayerCards"], item)
elseif identifier == "Fan Campaign" then
table.insert(library["fanmadeCampaigns"], item)
elseif identifier == "Fan Scenario" then
table.insert(library["fanmadeScenarios"], item)
-- initialize subtable
if library[contentType] == nil then
library[contentType] = {}
end
table.insert(library[contentType], item)
end
end
@ -1386,16 +1371,15 @@ function contentDownloadCallback(request, params)
-- if position is undefined, get empty position
if not spawnTable.position then
spawnTable.rotation = { 0, 270, 0 }
local pos = getValidSpawnPosition()
if pos then
spawnTable.position = pos
else
broadcastToAll(
"Please make space in the area below the tentacle stand in the upper middle of the table and try again.", "Red")
if not pos then
broadcastToAll("Please make space in the area below the tentacle stand in the upper middle of the table and try again.", "Red")
return
end
spawnTable.position = pos
spawnTable.rotation = { 0, 270, 0 }
else
end
-- if spawned from menu, move the camera and/or ping the table
@ -1432,13 +1416,9 @@ function getValidSpawnPosition()
local potentialSpawnPositionY = 1.5
local potentialSpawnPositionZ = { 35, 21, 7, -7, -21, -35 }
for i, posX in ipairs(potentialSpawnPositionX) do
for j, posZ in ipairs(potentialSpawnPositionZ) do
local pos = {
x = posX,
y = potentialSpawnPositionY,
z = posZ,
}
for _, posX in ipairs(potentialSpawnPositionX) do
for _, posZ in ipairs(potentialSpawnPositionZ) do
local pos = Vector(posX, potentialSpawnPositionY, posZ)
if checkPositionForContentSpawn(pos) then
return pos
end
@ -1448,11 +1428,10 @@ function getValidSpawnPosition()
end
-- checks whether something is in the specified position
-- returns true if empty
-- first hit is the table surface, additional hits means something is there
---@return boolean: True if empty
function checkPositionForContentSpawn(checkPos)
local searchResult = searchLib.atPosition(checkPos)
-- first hit is the table surface, additional hits means something is there
return #searchResult == 1
end
@ -1463,9 +1442,9 @@ function libraryDownloadCallback(request)
return
end
local json_response = nil
if pcall(function() json_response = JSON.decode(request.text) end) then
formatLibrary(json_response)
local jsonResponse = nil
if pcall(function() jsonResponse = JSON.decode(request.text) end) then
formatLibrary(jsonResponse)
updateDownloadItemList()
else
print('error parsing downloaded library')
@ -1814,7 +1793,7 @@ end
-- grabs the latest mod version and release notes from GitHub (called onLoad())
function getModVersion()
WebRequest.get(SOURCE_REPO .. '/modversion.json', compareVersion)
WebRequest.get(SOURCE_REPO .. 'modversion.json', compareVersion)
end
-- compares the modversion with GitHub and possibly shows the update notification