improved custom card support

This commit is contained in:
Chr1Z93 2024-08-06 13:40:14 +02:00
parent 6600610076
commit c785baa4be
3 changed files with 87 additions and 59 deletions

View File

@ -64,51 +64,22 @@ end
-- and creating the keyed lookup tables for the cards. This is a coroutine which will -- and creating the keyed lookup tables for the cards. This is a coroutine which will
-- spread the workload by processing 20 cards before yielding. -- spread the workload by processing 20 cards before yielding.
function buildIndex() function buildIndex()
local cardCount = 0 cardCount = 0
indexingDone = false indexingDone = false
otherCardsDetected = false otherCardsDetected = false
-- process the allcardsbag itself -- process the allcardsbag itself
for _, cardData in ipairs(self.getData().ContainedObjects) do local selfData = self.getData()
addCardToIndex(cardData) if selfData.ContainedObjects then
cardCount = cardCount + 1 processContainedObjects(selfData.ContainedObjects)
if cardCount > 19 then
cardCount = 0
coroutine.yield(0)
end
end end
-- process hotfix bags (and the additional playercards bag) -- process hotfix bags (and the additional playercards bag)
for _, hotfixBag in ipairs(getObjectsWithTag("AllCardsHotfix")) do for _, hotfixBag in ipairs(getObjectsWithTag("AllCardsHotfix")) do
local hotfixData = hotfixBag.getData() local hotfixData = hotfixBag.getData()
if hotfixData.ContainedObjects then
-- if the bag is empty, continue with the next bag processContainedObjects(hotfixData.ContainedObjects, hotfixData.CustomDeck)
if not hotfixData.ContainedObjects then
goto nextBag
end end
for _, cardData in ipairs(hotfixData.ContainedObjects) do
if cardData.ContainedObjects then
-- process containers
for _, deepCardData in ipairs(cardData.ContainedObjects) do
addCardToIndex(deepCardData)
cardCount = cardCount + 1
if cardCount > 19 then
cardCount = 0
coroutine.yield(0)
end
end
else
-- process single cards
addCardToIndex(cardData)
cardCount = cardCount + 1
if cardCount > 19 then
cardCount = 0
coroutine.yield(0)
end
end
end
::nextBag::
end end
buildSupplementalIndexes() buildSupplementalIndexes()
@ -117,6 +88,43 @@ function buildIndex()
return 1 return 1
end end
-- Processes the contained objects for cards to add to the index
function processContainedObjects(containedObjects, customDeck)
for _, objData in ipairs(containedObjects) do
if objData.ContainedObjects then
-- recursively process nested containers
processContainedObjects(objData.ContainedObjects, objData.CustomDeck)
else
-- we might need to fix the "CustomDeck" entry for cards inside decks since TTS doesn't update it while they are in bags
if customDeck then
local wantedCustomDeckIdStr = tostring(objData.CardID):sub(1, -3)
local presentCustomDeckIdNum = next(objData.CustomDeck)
-- type conversion (TTS seems to store these as strings, but reads them as numbers)
local wantedCustomDeckIdNum = tonumber(wantedCustomDeckIdStr)
if wantedCustomDeckIdNum ~= presentCustomDeckIdNum then
if customDeck[wantedCustomDeckIdNum] then
objData.CustomDeck = {}
objData.CustomDeck[wantedCustomDeckIdStr] = customDeck[wantedCustomDeckIdNum]
log("Correct CustomDeckData for " .. objData.Nickname)
else
log("Could not correct CustomDeckData for " .. objData.Nickname)
return
end
end
end
addCardToIndex(objData)
cardCount = cardCount + 1
if cardCount > 19 then
cardCount = 0
coroutine.yield(0)
end
end
end
end
-- Adds a card to any indexes it should be a part of, based on its metadata -- Adds a card to any indexes it should be a part of, based on its metadata
---@param cardData table TTS object data for the card ---@param cardData table TTS object data for the card
function addCardToIndex(cardData) function addCardToIndex(cardData)
@ -178,6 +186,17 @@ function buildSupplementalIndexes()
-- add to cycle index -- add to cycle index
local cycleName = card.metadata.cycle local cycleName = card.metadata.cycle
-- if this is a minicard without cycle, check the parent card for cycle data
if not cycleName and card.metadata.type == "Minicard" then
-- TO-DO: use a more robust detection instead of 5 characters
local parentId = string.match(card.metadata.id, ".....")
local parent = cardIdIndex[parentId]
if parent and parent.metadata.cycle then
cycleName = parent.metadata.cycle
end
end
if cycleName then if cycleName then
cycleName = string.lower(cycleName) cycleName = string.lower(cycleName)
@ -189,18 +208,14 @@ function buildSupplementalIndexes()
else else
-- track cards without defined cycle (should only be fan-made cards) -- track cards without defined cycle (should only be fan-made cards)
cycleName = "other" cycleName = "other"
log(card.metadata.id)
otherCardsDetected = true otherCardsDetected = true
end end
-- only add official cards with level to cycle index, but all fan-made cards -- maybe initialize table
if card.metadata.level or cycleName == "other" then if cycleIndex[cycleName] == nil then
-- maybe initialize table cycleIndex[cycleName] = {}
if cycleIndex[cycleName] == nil then
cycleIndex[cycleName] = {}
end
table.insert(cycleIndex[cycleName], card.metadata.id)
end end
table.insert(cycleIndex[cycleName], card.metadata.id)
end end
end end
@ -278,8 +293,9 @@ end
-- Returns a list of cards from the bag matching a cycle -- Returns a list of cards from the bag matching a cycle
---@param params table ---@param params table
-- cycle: String cycle to retrieve ("The Scarlet Keys" etc.) -- cycle: string Name of the cycle to retrieve ("The Scarlet Keys" etc.)
-- sortByMetadata: true to sort the table by metadata instead of ID -- sortByMetadata: boolean If true, sorts the table by metadata instead of ID
-- includeNoLevelCards: boolean If true, includes cards without level
---@return table: If the indexes are still being constructed, returns an empty table. ---@return table: If the indexes are still being constructed, returns an empty table.
-- Otherwise, a list of tables, each with the following fields -- Otherwise, a list of tables, each with the following fields
-- data: TTS object data, suitable for spawning the card -- data: TTS object data, suitable for spawning the card
@ -288,17 +304,18 @@ function getCardsByCycle(params)
if not isIndexReady() then return {} end if not isIndexReady() then return {} end
local cycleData = cycleIndex[string.lower(params.cycle)] or {} local cycleData = cycleIndex[string.lower(params.cycle)] or {}
if not params.sortByMetadata then
return cycleData -- create a copy of the data to not change the source
local cardList = {}
for _, id in ipairs(cycleData) do
-- only include cards without level if requested
if cardIdIndex[id].metadata.level or params.includeNoLevelCards then
table.insert(cardList, id)
end
end end
-- sort list by metadata (useful for custom cards without proper IDs) -- sort list by metadata (useful for custom cards without proper IDs)
local cardList = {} if params.sortByMetadata and #cardList > 0 then
for _, id in ipairs(cycleData) do
table.insert(cardList, id)
end
if #cardList > 0 then
table.sort(cardList, metadataSortFunction) table.sort(cardList, metadataSortFunction)
end end
return cardList return cardList
@ -340,13 +357,15 @@ end
-- helper function to calculate the class value for sorting from the "|" separated string -- helper function to calculate the class value for sorting from the "|" separated string
function getClassValueFromString(s) function getClassValueFromString(s)
s = s or "NoClass"
local classValueList = { local classValueList = {
Guardian = 1, Guardian = 1,
Seeker = 2, Seeker = 2,
Rogue = 3, Rogue = 3,
Mystic = 4, Mystic = 4,
Survivor = 5, Survivor = 5,
Neutral = 6 Neutral = 6,
NoClass = 7
} }
local classValue = 0 local classValue = 0
for str in s:gmatch("([^|]+)") do for str in s:gmatch("([^|]+)") do

View File

@ -77,12 +77,17 @@ do
-- Returns a list of cards from the bag matching a cycle -- Returns a list of cards from the bag matching a cycle
---@param cycle string Cycle to retrieve ("The Scarlet Keys" etc.) ---@param cycle string Cycle to retrieve ("The Scarlet Keys" etc.)
---@param sortByMetadata boolean If true, sorts the table by metadata instead of ID ---@param sortByMetadata boolean If true, sorts the table by metadata instead of ID
---@param includeNoLevelCards boolean If true, includes cards without level
---@return table: If the indexes are still being constructed, returns an empty table. ---@return table: If the indexes are still being constructed, returns an empty table.
-- Otherwise, a list of tables, each with the following fields -- Otherwise, a list of tables, each with the following fields
-- data: TTS object data, suitable for spawning the card -- data: TTS object data, suitable for spawning the card
-- metadata: Table of parsed metadata -- metadata: Table of parsed metadata
AllCardsBagApi.getCardsByCycle = function(cycle, sortByMetadata) AllCardsBagApi.getCardsByCycle = function(cycle, sortByMetadata, includeNoLevelCards)
return returnCopyOfList(getAllCardsBag().call("getCardsByCycle", { cycle = cycle, sortByMetadata = sortByMetadata })) return returnCopyOfList(getAllCardsBag().call("getCardsByCycle", {
cycle = cycle,
sortByMetadata = sortByMetadata,
includeNoLevelCards = includeNoLevelCards
}))
end end
-- Constructs a list of available basic weaknesses by starting with the full pool of basic -- Constructs a list of available basic weaknesses by starting with the full pool of basic

View File

@ -493,7 +493,9 @@ end
---@param groupName string Name of the group to spawn, matching a key in InvestigatorPanelData ---@param groupName string Name of the group to spawn, matching a key in InvestigatorPanelData
function spawnInvestigators(groupName) function spawnInvestigators(groupName)
if INVESTIGATOR_GROUPS[groupName] == nil then if INVESTIGATOR_GROUPS[groupName] == nil then
printToAll("No investigator data for " .. groupName .. " yet") if groupName ~= "Other" then
printToAll("No investigator data for '" .. groupName .. "' yet")
end
return return
end end
@ -693,15 +695,17 @@ function spawnCycle(cycle)
prepareToPlaceCards() prepareToPlaceCards()
spawnInvestigators(cycle) spawnInvestigators(cycle)
-- sort custom cards -- sort custom cards and include cards without level
local sortByMetadata = false local sortByMetadata = false
local includeNoLevelCards = false
if cycle == "Other" then if cycle == "Other" then
sortByMetadata = true sortByMetadata = true
includeNoLevelCards = true
end end
spawnBag.spawn({ spawnBag.spawn({
name = "cycle" .. cycle, name = "cycle" .. cycle,
cards = allCardsBagApi.getCardsByCycle(cycle, sortByMetadata), cards = allCardsBagApi.getCardsByCycle(cycle, sortByMetadata, includeNoLevelCards),
globalPos = self.positionToWorld(startPositions.cycle), globalPos = self.positionToWorld(startPositions.cycle),
rotation = FACE_UP_ROTATION, rotation = FACE_UP_ROTATION,
spread = true, spread = true,