added sorting for custom cards

This commit is contained in:
Chr1Z93 2024-05-25 00:40:18 +02:00
parent afff593874
commit 5b38ea1c02
3 changed files with 111 additions and 30 deletions

View File

@ -12,9 +12,9 @@ function onLoad()
Wait.frames(startIndexBuild, 30)
end
-- Called by Hotfix bags when they load. If we are still loading indexes, then
-- Called by Hotfix bags when they load. If we are still loading indexes, then
-- the all cards and hotfix bags are being loaded together, and we can ignore
-- this call as the hotfix will be included in the initial indexing. If it is
-- this call as the hotfix will be included in the initial indexing. If it is
-- called once indexing is complete it means the hotfix bag has been added
-- later, and we should rebuild the index to integrate the hotfix bag.
function rebuildIndexForHotfix()
@ -170,12 +170,16 @@ function buildSupplementalIndexes()
-- override cycle name for night of the zealot
cycleName = cycleName:gsub("the night of the zealot", "core")
if cycleIndex[cycleName] == nil then
cycleIndex[cycleName] = { }
end
table.insert(cycleIndex[cycleName], cardMetadata.id)
else
-- track cards without defined cycle (should only be fan-made cards)
cycleName = "other"
end
-- maybe initialize table
if cycleIndex[cycleName] == nil then
cycleIndex[cycleName] = { }
end
table.insert(cycleIndex[cycleName], cardMetadata.id)
end
end
end
@ -220,7 +224,7 @@ end
-- Params table:
-- id: String ID of the card to retrieve
-- Return: If the indexes are still being constructed, an empty table is
-- returned. Otherwise, a single table with the following fields
-- returned. Otherwise, a single table with the following fields
-- cardData: TTS object data, suitable for spawning the card
-- cardMetadata: Table of parsed metadata
function getCardById(params)
@ -240,21 +244,80 @@ function getCardsByClassAndLevel(params)
if not isIndexReady() then return {} end
local upgradeKey
if (params.upgraded) then
if params.upgraded then
upgradeKey = "-upgrade"
else
upgradeKey = "-level0"
end
return classAndLevelIndex[params.class..upgradeKey];
return classAndLevelIndex[params.class..upgradeKey]
end
function getCardsByCycle(cycleName)
function getCardsByCycle(params)
if not isIndexReady() then return {} end
return cycleIndex[string.lower(cycleName)]
if not params.sortByMetadata then
return cycleIndex[string.lower(params.cycle)]
end
-- sort list by metadata (useful for custom cards without proper IDs)
local cardList = {}
for _, id in ipairs(cycleIndex[string.lower(params.cycle)]) do
table.insert(cardList, id)
end
table.sort(cardList, metadataSortFunction)
return cardList
end
-- Searches the bag for cards which match the given name and returns a list. Note that this is
-- an O(n) search without index support. It may be slow.
-- sorts cards by metadata: class, type, level, name and then description
function metadataSortFunction(id1, id2)
local card1 = cardIdIndex[id1]
local card2 = cardIdIndex[id2]
-- extract class per card
local classValue1 = getClassValueFromString(card1.metadata.class)
local classValue2 = getClassValueFromString(card2.metadata.class)
-- conversion tables to simplify type sorting
local typeConversion = {
Asset = 1,
Event = 2,
Skill = 3
}
if classValue1 ~= classValue2 then
return classValue1 < classValue2
elseif typeConversion[card1.metadata.type] ~= typeConversion[card2.metadata.type] then
return typeConversion[card1.metadata.type] < typeConversion[card2.metadata.type]
elseif card1.metadata.level ~= card2.metadata.level then
return card1.metadata.level < card2.metadata.level
elseif card1.data.Nickname ~= card2.data.Nickname then
return card1.data.Nickname < card2.data.Nickname
else
return card1.data.Description < card2.data.Description
end
end
-- helper function to calculate the class value for sorting from the "|" separated string
function getClassValueFromString(s)
local classValueList = {
Guardian = 1,
Seeker = 2,
Rogue = 3,
Mystic = 4,
Survivor = 5,
Neutral = 6
}
local classValue = 0
for str in s:gmatch("([^|]+)") do
-- this sorts multiclass cards
classValue = classValue * 10 + classValueList[str]
end
return classValue
end
-- Searches the bag for cards which match the given name and returns a list. Note that this is
-- an O(n) search without index support. It may be slow.
-- Parameter array must contain these fields to define the search:
-- name String or string fragment to search for names
-- exact Whether the name match should be exact
@ -276,14 +339,14 @@ function getCardsByName(params)
return results
end
-- Gets a random basic weakness from the bag. Once a given ID has been returned
-- Gets a random basic weakness from the bag. Once a given ID has been returned
-- it will be removed from the list and cannot be selected again until a reload
-- occurs or the indexes are rebuilt, which will refresh the list to include all
-- weaknesses.
-- Return: String ID of the selected weakness.
function getRandomWeaknessId()
local availableWeaknesses = buildAvailableWeaknesses()
if (#availableWeaknesses > 0) then
local availableWeaknesses = buildAvailableWeaknesses()
if #availableWeaknesses > 0 then
return availableWeaknesses[math.random(#availableWeaknesses)]
end
end
@ -295,14 +358,12 @@ function buildAvailableWeaknesses()
local weaknessesInPlay = { }
local allObjects = getAllObjects()
for _, object in ipairs(allObjects) do
if (object.name == "Deck") then
if object.type == "Deck" then
for _, cardData in ipairs(object.getData().ContainedObjects) do
local cardMetadata = JSON.decode(cardData.GMNotes)
incrementWeaknessCount(weaknessesInPlay, cardMetadata)
incrementWeaknessCount(weaknessesInPlay, JSON.decode(cardData.GMNotes))
end
elseif (object.name == "Card") then
local cardMetadata = JSON.decode(object.getGMNotes())
incrementWeaknessCount(weaknessesInPlay, cardMetadata)
elseif object.type == "Card" then
incrementWeaknessCount(weaknessesInPlay, JSON.decode(object.getGMNotes()))
end
end
@ -327,8 +388,8 @@ end
-- Helper function that adds one to the table entry for the number of weaknesses in play
function incrementWeaknessCount(table, cardMetadata)
if (isBasicWeakness(cardMetadata)) then
if (table[cardMetadata.id] == nil) then
if isBasicWeakness(cardMetadata) then
if table[cardMetadata.id] == nil then
table[cardMetadata.id] = 1
else
table[cardMetadata.id] = table[cardMetadata.id] + 1

View File

@ -70,8 +70,8 @@ do
return returnCopyOfList(getAllCardsBag().call("getCardsByClassAndLevel", { class = class, upgraded = upgraded }))
end
AllCardsBagApi.getCardsByCycle = function(cycle)
return returnCopyOfList(getAllCardsBag().call("getCardsByCycle", cycle))
AllCardsBagApi.getCardsByCycle = function(cycle, sortByMetadata)
return returnCopyOfList(getAllCardsBag().call("getCardsByCycle", { cycle = cycle, sortByMetadata = sortByMetadata }))
end
AllCardsBagApi.getUniqueWeaknesses = function()

View File

@ -425,7 +425,7 @@ end
---@param groupName string Name of the group to spawn, matching a key in InvestigatorPanelData
function spawnInvestigators(groupName)
if INVESTIGATOR_GROUPS[groupName] == nil then
printToAll("No " .. groupName .. " data yet")
printToAll("No investigator data for " .. groupName .. " yet")
return
end
@ -434,7 +434,7 @@ function spawnInvestigators(groupName)
local investigatorCount = #INVESTIGATOR_GROUPS[groupName]
local position = getInvestigatorRowStartPos(investigatorCount, row)
for i, investigatorName in ipairs(INVESTIGATOR_GROUPS[groupName]) do
for _, investigatorName in ipairs(INVESTIGATOR_GROUPS[groupName]) do
for _, spawnSpec in ipairs(buildInvestigatorSpawnSpec(investigatorName, INVESTIGATORS[investigatorName], position)) do
spawnBag.spawn(spawnSpec)
end
@ -625,9 +625,15 @@ function spawnCycle(cycle)
prepareToPlaceCards()
spawnInvestigators(cycle)
-- sort custom cards
local sortByMetadata = false
if cycle == "Other" then
sortByMetadata = true
end
spawnBag.spawn({
name = "cycle" .. cycle,
cards = allCardsBagApi.getCardsByCycle(cycle),
cards = allCardsBagApi.getCardsByCycle(cycle, sortByMetadata),
globalPos = self.positionToWorld(startPositions.cycle),
rotation = FACE_UP_ROTATION,
spread = true,
@ -635,6 +641,20 @@ function spawnCycle(cycle)
})
end
-- Comparison function used to sort the class card bag indexes. Sorts by card level, then name, then subname.
function cardComparator(id1, id2)
local card1 = cardIdIndex[id1]
local card2 = cardIdIndex[id2]
if card1.metadata.level ~= card2.metadata.level then
return card1.metadata.level < card2.metadata.level
elseif card1.data.Nickname ~= card2.data.Nickname then
return card1.data.Nickname < card2.data.Nickname
else
return card1.data.Description < card2.data.Description
end
end
function spawnBonded()
prepareToPlaceCards()
spawnBag.spawn({