Merge pull request #777 from argonui/weakness-importing
Updated random basic weakness drawing for deck importer
This commit is contained in:
commit
439548f139
@ -138,7 +138,7 @@
|
|||||||
"Playermat3Green.383d8b",
|
"Playermat3Green.383d8b",
|
||||||
"Playermat4Red.0840d5",
|
"Playermat4Red.0840d5",
|
||||||
"LeadInvestigator.acaa93",
|
"LeadInvestigator.acaa93",
|
||||||
"ArkhamDBDeckImporter.a28140",
|
"DeckImporter.a28140",
|
||||||
"Configuration.03804b",
|
"Configuration.03804b",
|
||||||
"DrawingTool.280086",
|
"DrawingTool.280086",
|
||||||
"PlayAreaImageSwapper.b7b45b",
|
"PlayAreaImageSwapper.b7b45b",
|
||||||
|
@ -6,5 +6,6 @@
|
|||||||
"traits": "Pact.",
|
"traits": "Pact.",
|
||||||
"weakness": true,
|
"weakness": true,
|
||||||
"basicWeaknessCount": 1,
|
"basicWeaknessCount": 1,
|
||||||
|
"modeRestriction": "Campaign",
|
||||||
"cycle": "The Forgotten Age"
|
"cycle": "The Forgotten Age"
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,6 @@
|
|||||||
"traits": "Curse.",
|
"traits": "Curse.",
|
||||||
"weakness": true,
|
"weakness": true,
|
||||||
"basicWeaknessCount": 1,
|
"basicWeaknessCount": 1,
|
||||||
|
"modeRestriction": "Campaign",
|
||||||
"cycle": "The Forgotten Age"
|
"cycle": "The Forgotten Age"
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,6 @@
|
|||||||
"traits": "Monster. Geist.",
|
"traits": "Monster. Geist.",
|
||||||
"weakness": true,
|
"weakness": true,
|
||||||
"basicWeaknessCount": 1,
|
"basicWeaknessCount": 1,
|
||||||
|
"classRestriction": "Mystic",
|
||||||
"cycle": "The Scarlet Keys"
|
"cycle": "The Scarlet Keys"
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,6 @@
|
|||||||
"traits": "Monster. Shoggoth.",
|
"traits": "Monster. Shoggoth.",
|
||||||
"weakness": true,
|
"weakness": true,
|
||||||
"basicWeaknessCount": 1,
|
"basicWeaknessCount": 1,
|
||||||
|
"classRestriction": "Guardian",
|
||||||
"cycle": "The Scarlet Keys"
|
"cycle": "The Scarlet Keys"
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,6 @@
|
|||||||
"traits": "Pact.",
|
"traits": "Pact.",
|
||||||
"weakness": true,
|
"weakness": true,
|
||||||
"basicWeaknessCount": 1,
|
"basicWeaknessCount": 1,
|
||||||
|
"modeRestriction": "Campaign",
|
||||||
"cycle": "Return to the Forgotten Age"
|
"cycle": "Return to the Forgotten Age"
|
||||||
}
|
}
|
||||||
|
@ -6,5 +6,6 @@
|
|||||||
"traits": "Pact.",
|
"traits": "Pact.",
|
||||||
"weakness": true,
|
"weakness": true,
|
||||||
"basicWeaknessCount": 1,
|
"basicWeaknessCount": 1,
|
||||||
|
"classRestriction": "Rogue",
|
||||||
"cycle": "The Scarlet Keys"
|
"cycle": "The Scarlet Keys"
|
||||||
}
|
}
|
||||||
|
@ -6,5 +6,6 @@
|
|||||||
"traits": "Paradox.",
|
"traits": "Paradox.",
|
||||||
"weakness": true,
|
"weakness": true,
|
||||||
"basicWeaknessCount": 1,
|
"basicWeaknessCount": 1,
|
||||||
|
"classRestriction": "Seeker",
|
||||||
"cycle": "The Scarlet Keys"
|
"cycle": "The Scarlet Keys"
|
||||||
}
|
}
|
||||||
|
@ -6,5 +6,6 @@
|
|||||||
"traits": "Blunder.",
|
"traits": "Blunder.",
|
||||||
"weakness": true,
|
"weakness": true,
|
||||||
"basicWeaknessCount": 1,
|
"basicWeaknessCount": 1,
|
||||||
|
"classRestriction": "Survivor",
|
||||||
"cycle": "The Scarlet Keys"
|
"cycle": "The Scarlet Keys"
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
"traits": "Madness. Pact.",
|
"traits": "Madness. Pact.",
|
||||||
"weakness": true,
|
"weakness": true,
|
||||||
"basicWeaknessCount": 1,
|
"basicWeaknessCount": 1,
|
||||||
|
"modeRestriction": "Campaign",
|
||||||
"hidden": true,
|
"hidden": true,
|
||||||
"cycle": "Return to the Path to Carcosa"
|
"cycle": "Return to the Path to Carcosa"
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
"traits": "Madness. Pact.",
|
"traits": "Madness. Pact.",
|
||||||
"weakness": true,
|
"weakness": true,
|
||||||
"basicWeaknessCount": 1,
|
"basicWeaknessCount": 1,
|
||||||
|
"modeRestriction": "Campaign",
|
||||||
"hidden": true,
|
"hidden": true,
|
||||||
"cycle": "Return to the Path to Carcosa"
|
"cycle": "Return to the Path to Carcosa"
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
"traits": "Madness. Pact.",
|
"traits": "Madness. Pact.",
|
||||||
"weakness": true,
|
"weakness": true,
|
||||||
"basicWeaknessCount": 1,
|
"basicWeaknessCount": 1,
|
||||||
|
"modeRestriction": "Campaign",
|
||||||
"hidden": true,
|
"hidden": true,
|
||||||
"cycle": "Return to the Path to Carcosa"
|
"cycle": "Return to the Path to Carcosa"
|
||||||
}
|
}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
{"greenDeck":"","investigators":true,"loadNewest":true,"orangeDeck":"","privateDeck":true,"redDeck":"","whiteDeck":""}
|
|
@ -19,7 +19,7 @@
|
|||||||
},
|
},
|
||||||
"ImageScalar": 1,
|
"ImageScalar": 1,
|
||||||
"ImageSecondaryURL": "",
|
"ImageSecondaryURL": "",
|
||||||
"ImageURL": "https://i.imgur.com/wDp1Woo.jpg",
|
"ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2466368617691603054/ABA4AB3A811107629323CDA2765871EB36626242/",
|
||||||
"WidthScale": 0
|
"WidthScale": 0
|
||||||
},
|
},
|
||||||
"Description": "",
|
"Description": "",
|
||||||
@ -34,10 +34,10 @@
|
|||||||
"LayoutGroupSortIndex": 0,
|
"LayoutGroupSortIndex": 0,
|
||||||
"Locked": true,
|
"Locked": true,
|
||||||
"LuaScript": "require(\"arkhamdb/DeckImporter\")",
|
"LuaScript": "require(\"arkhamdb/DeckImporter\")",
|
||||||
"LuaScriptState_path": "ArkhamDBDeckImporter.a28140.luascriptstate",
|
"LuaScriptState_path": "DeckImporter.a28140.luascriptstate",
|
||||||
"MeasureMovement": false,
|
"MeasureMovement": false,
|
||||||
"Name": "Custom_Tile",
|
"Name": "Custom_Tile",
|
||||||
"Nickname": "ArkhamDB Deck Importer",
|
"Nickname": "Deck Importer",
|
||||||
"Snap": false,
|
"Snap": false,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
"Tooltip": false,
|
"Tooltip": false,
|
9
objects/DeckImporter.a28140.luascriptstate
Normal file
9
objects/DeckImporter.a28140.luascriptstate
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"greenDeck": "",
|
||||||
|
"loadNewest": true,
|
||||||
|
"orangeDeck": "",
|
||||||
|
"privateDeck": true,
|
||||||
|
"redDeck": "",
|
||||||
|
"standalone": false,
|
||||||
|
"whiteDeck": ""
|
||||||
|
}
|
@ -40,7 +40,7 @@ do
|
|||||||
---@param deckId string ArkhamDB deck id to be loaded
|
---@param deckId string ArkhamDB deck id to be loaded
|
||||||
---@param isPrivate boolean Whether this deck is published or private on ArkhamDB
|
---@param isPrivate boolean Whether this deck is published or private on ArkhamDB
|
||||||
---@param loadNewest boolean Whether the newest version of this deck should be loaded
|
---@param loadNewest boolean Whether the newest version of this deck should be loaded
|
||||||
---@param loadInvestigators boolean Whether investigator cards should be loaded as part of this deck
|
---@param standalone boolean Whether 'Campaign only' weaknesses should be exluded
|
||||||
---@param callback function Callback which will be sent the results of this load
|
---@param callback function Callback which will be sent the results of this load
|
||||||
--- Parameters to the callback will be:
|
--- Parameters to the callback will be:
|
||||||
--- slots table A map of card ID to count in the deck
|
--- slots table A map of card ID to count in the deck
|
||||||
@ -54,7 +54,7 @@ do
|
|||||||
deckId,
|
deckId,
|
||||||
isPrivate,
|
isPrivate,
|
||||||
loadNewest,
|
loadNewest,
|
||||||
loadInvestigators,
|
standalone,
|
||||||
callback)
|
callback)
|
||||||
-- Get a simple card to see if the bag indexes are complete. If not, abort
|
-- Get a simple card to see if the bag indexes are complete. If not, abort
|
||||||
-- the deck load. The called method will handle player notification.
|
-- the deck load. The called method will handle player notification.
|
||||||
@ -90,7 +90,7 @@ do
|
|||||||
return true, json
|
return true, json
|
||||||
end)
|
end)
|
||||||
|
|
||||||
deck:with(internal.onDeckResult, playerColor, loadNewest, loadInvestigators, callback)
|
deck:with(internal.onDeckResult, playerColor, loadNewest, standalone, callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Logs that a card could not be loaded in the mod by printing it to the console in the given
|
-- Logs that a card could not be loaded in the mod by printing it to the console in the given
|
||||||
@ -125,7 +125,7 @@ do
|
|||||||
---@param deck table ArkhamImportDeck
|
---@param deck table ArkhamImportDeck
|
||||||
---@param playerColor string Color name of the player mat to place this deck on (e.g. "Red")
|
---@param playerColor string Color name of the player mat to place this deck on (e.g. "Red")
|
||||||
---@param loadNewest boolean Whether the newest version of this deck should be loaded
|
---@param loadNewest boolean Whether the newest version of this deck should be loaded
|
||||||
---@param loadInvestigators boolean Whether investigator cards should be loaded as part of this deck
|
---@param standalone boolean Whether 'Campaign only' weaknesses should be exluded
|
||||||
---@param callback function Callback which will be sent the results of this load.
|
---@param callback function Callback which will be sent the results of this load.
|
||||||
--- Parameters to the callback will be:
|
--- Parameters to the callback will be:
|
||||||
--- slots table A map of card ID to count in the deck
|
--- slots table A map of card ID to count in the deck
|
||||||
@ -134,7 +134,7 @@ do
|
|||||||
--- added from a parent bonded card.
|
--- added from a parent bonded card.
|
||||||
--- customizations table The decoded table of customization upgrades in this deck
|
--- customizations table The decoded table of customization upgrades in this deck
|
||||||
--- playerColor String. Color this deck is being loaded for
|
--- playerColor String. Color this deck is being loaded for
|
||||||
internal.onDeckResult = function(deck, playerColor, loadNewest, loadInvestigators, callback)
|
internal.onDeckResult = function(deck, playerColor, loadNewest, standalone, callback)
|
||||||
-- Load the next deck in the upgrade path if the option is enabled
|
-- Load the next deck in the upgrade path if the option is enabled
|
||||||
if (loadNewest and deck.next_deck ~= nil and deck.next_deck ~= "") then
|
if (loadNewest and deck.next_deck ~= nil and deck.next_deck ~= "") then
|
||||||
buildDeck(playerColor, deck.next_deck)
|
buildDeck(playerColor, deck.next_deck)
|
||||||
@ -147,13 +147,16 @@ do
|
|||||||
-- be changed, as later steps may act on cards added in each. For example, a random weakness or
|
-- be changed, as later steps may act on cards added in each. For example, a random weakness or
|
||||||
-- investigator may have bonded cards or taboo entries, and should be present
|
-- investigator may have bonded cards or taboo entries, and should be present
|
||||||
local slots = deck.slots
|
local slots = deck.slots
|
||||||
internal.maybeDrawRandomWeakness(slots, playerColor)
|
|
||||||
|
-- get class for investigator to handle specific weaknesses
|
||||||
|
local class
|
||||||
|
local card = allCardsBagApi.getCardById(deck.investigator_code)
|
||||||
|
if card and card.metadata then class = card.metadata.class end
|
||||||
|
local restrictions = { class = class, standalone = standalone }
|
||||||
|
internal.maybeDrawRandomWeakness(slots, playerColor, restrictions)
|
||||||
|
|
||||||
-- handles alternative investigators (parallel, promo or revised art)
|
-- handles alternative investigators (parallel, promo or revised art)
|
||||||
local loadAltInvestigator = "normal"
|
local loadAltInvestigator = internal.addInvestigatorCards(deck, slots)
|
||||||
if loadInvestigators then
|
|
||||||
loadAltInvestigator = internal.addInvestigatorCards(deck, slots)
|
|
||||||
end
|
|
||||||
|
|
||||||
internal.maybeModifyDeckFromDescription(slots, deck.description_md, playerColor)
|
internal.maybeModifyDeckFromDescription(slots, deck.description_md, playerColor)
|
||||||
internal.maybeAddSummonedServitor(slots)
|
internal.maybeAddSummonedServitor(slots)
|
||||||
@ -179,16 +182,20 @@ do
|
|||||||
--- of those cards which will be spawned
|
--- of those cards which will be spawned
|
||||||
---@param playerColor string Color of the player this deck is being loaded for. Used for broadcast
|
---@param playerColor string Color of the player this deck is being loaded for. Used for broadcast
|
||||||
--- if a weakness is added.
|
--- if a weakness is added.
|
||||||
internal.maybeDrawRandomWeakness = function(slots, playerColor)
|
---@param restrictions table Additional restrictions:
|
||||||
|
--- class string Class to restrict weakness to
|
||||||
|
--- standalone boolean Whether 'Campaign only' weaknesses should be exluded
|
||||||
|
--- traits? string Trait(s) to use as filter
|
||||||
|
internal.maybeDrawRandomWeakness = function(slots, playerColor, restrictions)
|
||||||
local randomWeaknessAmount = slots[RANDOM_WEAKNESS_ID] or 0
|
local randomWeaknessAmount = slots[RANDOM_WEAKNESS_ID] or 0
|
||||||
slots[RANDOM_WEAKNESS_ID] = nil
|
slots[RANDOM_WEAKNESS_ID] = nil
|
||||||
|
|
||||||
if randomWeaknessAmount > 0 then
|
if randomWeaknessAmount > 0 then
|
||||||
for i = 1, randomWeaknessAmount do
|
local weaknessIds = allCardsBagApi.getRandomWeaknessIds(randomWeaknessAmount, restrictions)
|
||||||
local weaknessId = allCardsBagApi.getRandomWeaknessId()
|
for _, weaknessId in ipairs(weaknessIds) do
|
||||||
slots[weaknessId] = (slots[weaknessId] or 0) + 1
|
slots[weaknessId] = (slots[weaknessId] or 0) + 1
|
||||||
end
|
end
|
||||||
internal.maybePrint("Added " .. randomWeaknessAmount .. " random basic weakness(es) to deck", playerColor)
|
internal.maybePrint("Added " .. #weaknessIds .. " random basic weakness(es) to deck", playerColor)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -21,18 +21,18 @@ local UPGRADED_TOGGLE_LABELS = {}
|
|||||||
UPGRADED_TOGGLE_LABELS[true] = "Upgraded"
|
UPGRADED_TOGGLE_LABELS[true] = "Upgraded"
|
||||||
UPGRADED_TOGGLE_LABELS[false] = "Specific"
|
UPGRADED_TOGGLE_LABELS[false] = "Specific"
|
||||||
|
|
||||||
local LOAD_INVESTIGATOR_TOGGLE_LABELS = {}
|
local STANDALONE_TOGGLE_LABELS = {}
|
||||||
LOAD_INVESTIGATOR_TOGGLE_LABELS[true] = "Yes"
|
STANDALONE_TOGGLE_LABELS[true] = "Yes"
|
||||||
LOAD_INVESTIGATOR_TOGGLE_LABELS[false] = "No"
|
STANDALONE_TOGGLE_LABELS[false] = "No"
|
||||||
|
|
||||||
local redDeckId = ""
|
redDeckId = ""
|
||||||
local orangeDeckId = ""
|
orangeDeckId = ""
|
||||||
local whiteDeckId = ""
|
whiteDeckId = ""
|
||||||
local greenDeckId = ""
|
greenDeckId = ""
|
||||||
|
|
||||||
local privateDeck = true
|
local privateDeck = true
|
||||||
local loadNewestDeck = true
|
local loadNewestDeck = true
|
||||||
local loadInvestigators = false
|
local standalone = false
|
||||||
|
|
||||||
function onLoad(script_state)
|
function onLoad(script_state)
|
||||||
initializeUi(JSON.decode(script_state))
|
initializeUi(JSON.decode(script_state))
|
||||||
@ -53,7 +53,7 @@ function getUiState()
|
|||||||
greenDeck = greenDeckId,
|
greenDeck = greenDeckId,
|
||||||
privateDeck = privateDeck,
|
privateDeck = privateDeck,
|
||||||
loadNewest = loadNewestDeck,
|
loadNewest = loadNewestDeck,
|
||||||
investigators = loadInvestigators
|
standalone = standalone
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ function initializeUi(savedUiState)
|
|||||||
greenDeckId = savedUiState.greenDeck
|
greenDeckId = savedUiState.greenDeck
|
||||||
privateDeck = savedUiState.privateDeck
|
privateDeck = savedUiState.privateDeck
|
||||||
loadNewestDeck = savedUiState.loadNewest
|
loadNewestDeck = savedUiState.loadNewest
|
||||||
loadInvestigators = savedUiState.investigators
|
standalone = savedUiState.standalone
|
||||||
end
|
end
|
||||||
|
|
||||||
makeOptionToggles()
|
makeOptionToggles()
|
||||||
@ -84,72 +84,74 @@ end
|
|||||||
|
|
||||||
function makeOptionToggles()
|
function makeOptionToggles()
|
||||||
-- common parameters
|
-- common parameters
|
||||||
local checkboxParameters = {}
|
local cParams = {}
|
||||||
checkboxParameters.function_owner = self
|
cParams.function_owner = self
|
||||||
checkboxParameters.width = INPUT_FIELD_WIDTH
|
cParams.width = 1750
|
||||||
checkboxParameters.height = INPUT_FIELD_HEIGHT
|
cParams.height = INPUT_FIELD_HEIGHT
|
||||||
checkboxParameters.scale = { 0.1, 0.1, 0.1 }
|
cParams.position = Vector( 0.22, 0.1, -0.102)
|
||||||
checkboxParameters.font_size = 240
|
cParams.scale = { 0.1, 0.1, 0.1 }
|
||||||
checkboxParameters.hover_color = { 0.4, 0.6, 0.8 }
|
cParams.font_size = 240
|
||||||
checkboxParameters.color = FIELD_COLOR
|
cParams.hover_color = { 0.4, 0.6, 0.8 }
|
||||||
|
cParams.color = FIELD_COLOR
|
||||||
|
|
||||||
-- public / private deck
|
-- public / private deck
|
||||||
checkboxParameters.click_function = "publicPrivateChanged"
|
cParams.click_function = "publishedPrivateChanged"
|
||||||
checkboxParameters.position = { 0.25, 0.1, -0.102 }
|
cParams.tooltip = "Published or private deck?\n\nPLEASE USE A PRIVATE DECK IF JUST FOR TTS TO AVOID FLOODING ARKHAMDB PUBLISHED DECK LISTS!\n\nMake sure to enable deck sharing in your account settings.\n\nKeep this on 'Private' for arkham.build."
|
||||||
checkboxParameters.tooltip = "Published or private deck?\n\nPLEASE USE A PRIVATE DECK IF JUST FOR TTS TO AVOID FLOODING ARKHAMDB PUBLISHED DECK LISTS!"
|
cParams.label = PRIVATE_TOGGLE_LABELS[privateDeck]
|
||||||
checkboxParameters.label = PRIVATE_TOGGLE_LABELS[privateDeck]
|
self.createButton(cParams)
|
||||||
self.createButton(checkboxParameters)
|
|
||||||
|
|
||||||
-- load upgraded?
|
-- load upgraded?
|
||||||
checkboxParameters.click_function = "loadUpgradedChanged"
|
cParams.click_function = "loadUpgradedChanged"
|
||||||
checkboxParameters.position = { 0.25, 0.1, -0.01 }
|
cParams.position.z = -0.01
|
||||||
checkboxParameters.tooltip = "Load newest upgrade or exact deck?"
|
cParams.tooltip = "Load newest upgrade or exact deck?"
|
||||||
checkboxParameters.label = UPGRADED_TOGGLE_LABELS[loadNewestDeck]
|
cParams.label = UPGRADED_TOGGLE_LABELS[loadNewestDeck]
|
||||||
self.createButton(checkboxParameters)
|
self.createButton(cParams)
|
||||||
|
|
||||||
-- load investigators?
|
-- standalone mode?
|
||||||
checkboxParameters.click_function = "loadInvestigatorsChanged"
|
cParams.click_function = "standaloneChanged"
|
||||||
checkboxParameters.position = { 0.25, 0.1, 0.081 }
|
cParams.position.z = 0.081
|
||||||
checkboxParameters.tooltip = "Spawn investigator cards?"
|
cParams.tooltip = "Are you playing standalone mode? Enabling this will make all 'Campaign Only' weaknesses ineligible when determining the random basic weakness(es)."
|
||||||
checkboxParameters.label = LOAD_INVESTIGATOR_TOGGLE_LABELS[loadInvestigators]
|
cParams.label = STANDALONE_TOGGLE_LABELS[standalone]
|
||||||
self.createButton(checkboxParameters)
|
self.createButton(cParams)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create the four deck ID entry fields
|
-- Create the four deck ID entry fields
|
||||||
function makeDeckIdFields()
|
function makeDeckIdFields()
|
||||||
local inputParameters = {}
|
local iParams = {}
|
||||||
-- Parameters common to all entry fields
|
iParams.function_owner = self
|
||||||
inputParameters.function_owner = self
|
iParams.scale = { 0.1, 0.1, 0.1 }
|
||||||
inputParameters.scale = { 0.1, 0.1, 0.1 }
|
iParams.width = INPUT_FIELD_WIDTH
|
||||||
inputParameters.width = INPUT_FIELD_WIDTH
|
iParams.height = INPUT_FIELD_HEIGHT
|
||||||
inputParameters.height = INPUT_FIELD_HEIGHT
|
iParams.font_size = 320
|
||||||
inputParameters.font_size = 320
|
iParams.tooltip = "Deck ID from ArkhamDB URL of the deck\nPublished URL: 'https://arkhamdb.com/decklist/view/101/knowledge-overwhelming-solo-deck-1.0' = '101'\nPrivate URL: 'https://arkhamdb.com/deck/view/102' = '102'\n\nAlso supports the deck ID from shared decks from arkham.build!"
|
||||||
inputParameters.tooltip = "Deck ID from ArkhamDB URL of the deck\nPublic URL: 'https://arkhamdb.com/decklist/view/101/knowledge-overwhelming-solo-deck-1.0' = '101'\nPrivate URL: 'https://arkhamdb.com/deck/view/102' = '102'\n\nAlso supports the deck ID from shared decks from arkham.build!"
|
iParams.alignment = 3 -- Center
|
||||||
inputParameters.alignment = 3 -- Center
|
iParams.color = FIELD_COLOR
|
||||||
inputParameters.color = FIELD_COLOR
|
iParams.font_color = { 0, 0, 0 }
|
||||||
inputParameters.font_color = { 0, 0, 0 }
|
iParams.validation = 4 -- alphanumeric (to support arkham.build IDs)
|
||||||
inputParameters.validation = 4 -- alphanumeric (to support arkham.build IDs)
|
|
||||||
|
|
||||||
-- Green
|
-- Green
|
||||||
inputParameters.input_function = "greenDeckChanged"
|
iParams.input_function = "greenDeckChanged"
|
||||||
inputParameters.position = { -0.166, 0.1, 0.385 }
|
iParams.position = { -0.16, 0.1, 0.385 }
|
||||||
inputParameters.value = greenDeckId
|
iParams.value = greenDeckId
|
||||||
self.createInput(inputParameters)
|
self.createInput(iParams)
|
||||||
|
|
||||||
-- Red
|
-- Red
|
||||||
inputParameters.input_function = "redDeckChanged"
|
iParams.input_function = "redDeckChanged"
|
||||||
inputParameters.position = { 0.171, 0.1, 0.385 }
|
iParams.position = { 0.165, 0.1, 0.385 }
|
||||||
inputParameters.value = redDeckId
|
iParams.value = redDeckId
|
||||||
self.createInput(inputParameters)
|
self.createInput(iParams)
|
||||||
|
|
||||||
-- White
|
-- White
|
||||||
inputParameters.input_function = "whiteDeckChanged"
|
iParams.input_function = "whiteDeckChanged"
|
||||||
inputParameters.position = { -0.166, 0.1, 0.474 }
|
iParams.position = { -0.16, 0.1, 0.474 }
|
||||||
inputParameters.value = whiteDeckId
|
iParams.value = whiteDeckId
|
||||||
self.createInput(inputParameters)
|
self.createInput(iParams)
|
||||||
|
|
||||||
-- Orange
|
-- Orange
|
||||||
inputParameters.input_function = "orangeDeckChanged"
|
iParams.input_function = "orangeDeckChanged"
|
||||||
inputParameters.position = { 0.171, 0.1, 0.474 }
|
iParams.position = { 0.165, 0.1, 0.474 }
|
||||||
inputParameters.value = orangeDeckId
|
iParams.value = orangeDeckId
|
||||||
self.createInput(inputParameters)
|
self.createInput(iParams)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create the Build All button. This is a transparent button which covers the Build All portion of the background graphic
|
-- Create the Build All button. This is a transparent button which covers the Build All portion of the background graphic
|
||||||
@ -172,7 +174,7 @@ function whiteDeckChanged(_, _, inputValue) whiteDeckId = inputValue end
|
|||||||
function greenDeckChanged(_, _, inputValue) greenDeckId = inputValue end
|
function greenDeckChanged(_, _, inputValue) greenDeckId = inputValue end
|
||||||
|
|
||||||
-- Event handlers for toggle buttons
|
-- Event handlers for toggle buttons
|
||||||
function publicPrivateChanged()
|
function publishedPrivateChanged()
|
||||||
privateDeck = not privateDeck
|
privateDeck = not privateDeck
|
||||||
self.editButton({ index = 0, label = PRIVATE_TOGGLE_LABELS[privateDeck] })
|
self.editButton({ index = 0, label = PRIVATE_TOGGLE_LABELS[privateDeck] })
|
||||||
end
|
end
|
||||||
@ -182,25 +184,37 @@ function loadUpgradedChanged()
|
|||||||
self.editButton({ index = 1, label = UPGRADED_TOGGLE_LABELS[loadNewestDeck] })
|
self.editButton({ index = 1, label = UPGRADED_TOGGLE_LABELS[loadNewestDeck] })
|
||||||
end
|
end
|
||||||
|
|
||||||
function loadInvestigatorsChanged()
|
function standaloneChanged()
|
||||||
loadInvestigators = not loadInvestigators
|
standalone = not standalone
|
||||||
self.editButton({ index = 2, label = LOAD_INVESTIGATOR_TOGGLE_LABELS[loadInvestigators] })
|
self.editButton({ index = 2, label = STANDALONE_TOGGLE_LABELS[standalone] })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- start the deck importing process
|
||||||
function loadDecks()
|
function loadDecks()
|
||||||
|
co = coroutine.create(loadDecksCoroutine)
|
||||||
|
resumeLoadDecks()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- perform the deck importing (with a pause after each deck load)
|
||||||
|
-- this pause will for example allow weaknesses to be spawned so that the RBW drawing can detect them
|
||||||
|
function loadDecksCoroutine()
|
||||||
if not allCardsBagApi.isIndexReady() then return end
|
if not allCardsBagApi.isIndexReady() then return end
|
||||||
matsWithInvestigator = playermatApi.getUsedMatColors()
|
matsWithInvestigator = playermatApi.getUsedMatColors()
|
||||||
if redDeckId ~= nil and redDeckId ~= "" then
|
|
||||||
buildDeck("Red", redDeckId)
|
for _, matColor in ipairs({"White", "Orange", "Green", "Red"}) do
|
||||||
|
local deckId = _G[string.lower(matColor) .. "DeckId"]
|
||||||
|
if deckId ~= nil and deckId ~= "" then
|
||||||
|
buildDeck(matColor, deckId)
|
||||||
|
coroutine.yield()
|
||||||
end
|
end
|
||||||
if orangeDeckId ~= nil and orangeDeckId ~= "" then
|
|
||||||
buildDeck("Orange", orangeDeckId)
|
|
||||||
end
|
end
|
||||||
if whiteDeckId ~= nil and whiteDeckId ~= "" then
|
|
||||||
buildDeck("White", whiteDeckId)
|
|
||||||
end
|
end
|
||||||
if greenDeckId ~= nil and greenDeckId ~= "" then
|
|
||||||
buildDeck("Green", greenDeckId)
|
-- resume the deck importing process
|
||||||
|
function resumeLoadDecks()
|
||||||
|
if co and coroutine.status(co) ~= "dead" then
|
||||||
|
local status, err = coroutine.resume(co)
|
||||||
|
if not status then error(err) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -247,7 +261,7 @@ function buildDeck(playerColor, deckId)
|
|||||||
deckId,
|
deckId,
|
||||||
uiState.privateDeck,
|
uiState.privateDeck,
|
||||||
uiState.loadNewest,
|
uiState.loadNewest,
|
||||||
uiState.investigators,
|
uiState.standalone,
|
||||||
loadCards)
|
loadCards)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -343,6 +357,7 @@ function loadCards(slots, investigatorId, bondedList, customizations, playerColo
|
|||||||
if (not hadError) then
|
if (not hadError) then
|
||||||
printToAll("Deck loaded successfully!", playerColor)
|
printToAll("Deck loaded successfully!", playerColor)
|
||||||
end
|
end
|
||||||
|
resumeLoadDecks()
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -370,19 +370,45 @@ end
|
|||||||
-- Gets a random basic weakness from the bag. Once a given ID has been returned it will be
|
-- 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
|
-- 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.
|
-- are rebuilt, which will refresh the list to include all weaknesses.
|
||||||
---@return string: ID of the selected weakness
|
---@param params table Bundled parameters:
|
||||||
function getRandomWeaknessId()
|
--- count number Number of weaknesses
|
||||||
local availableWeaknesses = buildAvailableWeaknesses()
|
--- restrictions table Additional restrictions:
|
||||||
if #availableWeaknesses > 0 then
|
--- class string Class to restrict weakness to
|
||||||
return availableWeaknesses[math.random(#availableWeaknesses)]
|
--- standalone boolean Whether 'Campaign only' weaknesses should be exluded
|
||||||
|
--- traits? string Trait(s) to use as filter
|
||||||
|
---@return table: Table with IDs of the selected weaknesses
|
||||||
|
function getRandomWeaknessIds(params)
|
||||||
|
params.count = params.count or 1
|
||||||
|
local availableWeaknesses = buildAvailableWeaknesses(params.restrictions)
|
||||||
|
|
||||||
|
-- check if enough weaknesses are available
|
||||||
|
local missingWeaknesses = params.count - #availableWeaknesses
|
||||||
|
if missingWeaknesses > 0 then
|
||||||
|
broadcastToAll("Not enough basic weaknesses available! (" .. missingWeaknesses .. " missing)", { 0.9, 0.2, 0.2 })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local drawnWeaknesses = {}
|
||||||
|
|
||||||
|
-- Fisher-Yates shuffle algorithm
|
||||||
|
local n = #availableWeaknesses
|
||||||
|
for i = 1, math.min(params.count, n) do
|
||||||
|
local index = math.random(i, n)
|
||||||
|
table.insert(drawnWeaknesses, availableWeaknesses[index])
|
||||||
|
availableWeaknesses[index], availableWeaknesses[i] = availableWeaknesses[i], availableWeaknesses[index]
|
||||||
|
end
|
||||||
|
|
||||||
|
return drawnWeaknesses
|
||||||
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
|
||||||
-- weaknesses then removing any which are currently in the play or deck construction areas
|
-- weaknesses then removing any which are currently in the play or deck construction areas
|
||||||
---@param traits? string Trait(s) to use as filter
|
---@param restrictions? table Additional restrictions:
|
||||||
|
--- class string Class to restrict weakness to
|
||||||
|
--- standalone boolean Whether 'Campaign only' weaknesses should be exluded
|
||||||
|
--- traits? string Trait(s) to use as filter
|
||||||
---@return table: Array of weakness IDs which are valid to choose from
|
---@return table: Array of weakness IDs which are valid to choose from
|
||||||
function buildAvailableWeaknesses(traits)
|
function buildAvailableWeaknesses(restrictions)
|
||||||
|
restrictions = restrictions or {}
|
||||||
local weaknessesInPlay = {}
|
local weaknessesInPlay = {}
|
||||||
local allObjects = getAllObjects()
|
local allObjects = getAllObjects()
|
||||||
for _, object in ipairs(allObjects) do
|
for _, object in ipairs(allObjects) do
|
||||||
@ -400,10 +426,29 @@ function buildAvailableWeaknesses(traits)
|
|||||||
if (weaknessesInPlay[weaknessId] ~= nil and weaknessesInPlay[weaknessId] > 0) then
|
if (weaknessesInPlay[weaknessId] ~= nil and weaknessesInPlay[weaknessId] > 0) then
|
||||||
weaknessesInPlay[weaknessId] = weaknessesInPlay[weaknessId] - 1
|
weaknessesInPlay[weaknessId] = weaknessesInPlay[weaknessId] - 1
|
||||||
else
|
else
|
||||||
if traits then
|
local eligible = true
|
||||||
|
|
||||||
|
-- disable 'Campaign only' weaknesses in standalone mode
|
||||||
|
if restrictions.standalone then
|
||||||
|
local card = cardIdIndex[weaknessId]
|
||||||
|
if card.metadata.modeRestriction == "Campaign" then
|
||||||
|
eligible = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- disable class restricted weaknesses
|
||||||
|
if restrictions.class then
|
||||||
|
local card = cardIdIndex[weaknessId]
|
||||||
|
if card.metadata.classRestriction and card.metadata.classRestriction ~= restrictions.class then
|
||||||
|
eligible = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- disable non-matching traits
|
||||||
|
if restrictions.traits then
|
||||||
-- split the string into separate traits (separated by "|")
|
-- split the string into separate traits (separated by "|")
|
||||||
local allowedTraits = {}
|
local allowedTraits = {}
|
||||||
for str in traits:gmatch("([^|]+)") do
|
for str in restrictions.traits:gmatch("([^|]+)") do
|
||||||
-- remove dots
|
-- remove dots
|
||||||
str = str:gsub("[%.]", "")
|
str = str:gsub("[%.]", "")
|
||||||
|
|
||||||
@ -415,15 +460,24 @@ function buildAvailableWeaknesses(traits)
|
|||||||
table.insert(allowedTraits, str)
|
table.insert(allowedTraits, str)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local match = false
|
||||||
|
|
||||||
-- make sure the trait is present on the weakness
|
-- make sure the trait is present on the weakness
|
||||||
local card = cardIdIndex[weaknessId]
|
local card = cardIdIndex[weaknessId]
|
||||||
for _, allowedTrait in ipairs(allowedTraits) do
|
for _, allowedTrait in ipairs(allowedTraits) do
|
||||||
if string.contains(string.lower(card.metadata.traits), allowedTrait) then
|
if string.contains(string.lower(card.metadata.traits), allowedTrait) then
|
||||||
table.insert(availableWeaknesses, weaknessId)
|
match = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
|
||||||
|
if not match then
|
||||||
|
eligible = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- add weakness to list if eligible
|
||||||
|
if eligible then
|
||||||
table.insert(availableWeaknesses, weaknessId)
|
table.insert(availableWeaknesses, weaknessId)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -28,9 +28,14 @@ do
|
|||||||
-- Gets a random basic weakness from the bag. Once a given ID has been returned it
|
-- 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
|
-- 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.
|
-- or the indexes are rebuilt, which will refresh the list to include all weaknesses.
|
||||||
---@return string: ID of the selected weakness
|
---@param count number Number of weaknesses
|
||||||
AllCardsBagApi.getRandomWeaknessId = function()
|
---@param restrictions table Additional restrictions:
|
||||||
return getAllCardsBag().call("getRandomWeaknessId")
|
--- class string Class to restrict weakness to
|
||||||
|
--- standalone boolean Whether 'Campaign only' weaknesses should be exluded
|
||||||
|
--- traits? string Trait(s) to use as filter
|
||||||
|
---@return table: Table with IDs of the selected weaknesses
|
||||||
|
AllCardsBagApi.getRandomWeaknessIds = function(count, restrictions)
|
||||||
|
return returnCopyOfList(getAllCardsBag().call("getRandomWeaknessIds", {count = count, restrictions = restrictions}))
|
||||||
end
|
end
|
||||||
|
|
||||||
AllCardsBagApi.isIndexReady = function()
|
AllCardsBagApi.isIndexReady = function()
|
||||||
@ -82,10 +87,13 @@ do
|
|||||||
|
|
||||||
-- 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
|
||||||
-- weaknesses then removing any which are currently in the play or deck construction areas
|
-- weaknesses then removing any which are currently in the play or deck construction areas
|
||||||
---@param traits? string Trait(s) to use as filter
|
---@param restrictions table Additional restrictions:
|
||||||
|
--- class string Class to restrict weakness to
|
||||||
|
--- standalone boolean Whether 'Campaign only' weaknesses should be exluded
|
||||||
|
--- traits? string Trait(s) to use as filter
|
||||||
---@return table: Array of weakness IDs which are valid to choose from
|
---@return table: Array of weakness IDs which are valid to choose from
|
||||||
AllCardsBagApi.buildAvailableWeaknesses = function(traits)
|
AllCardsBagApi.buildAvailableWeaknesses = function(restrictions)
|
||||||
return returnCopyOfList(getAllCardsBag().call("buildAvailableWeaknesses", traits))
|
return returnCopyOfList(getAllCardsBag().call("buildAvailableWeaknesses", restrictions))
|
||||||
end
|
end
|
||||||
|
|
||||||
AllCardsBagApi.getUniqueWeaknesses = function()
|
AllCardsBagApi.getUniqueWeaknesses = function()
|
||||||
|
@ -782,21 +782,17 @@ function spawnRandomWeakness(_, playerColor, isRightClick)
|
|||||||
prepareToPlaceCards()
|
prepareToPlaceCards()
|
||||||
|
|
||||||
if not isRightClick then
|
if not isRightClick then
|
||||||
local weaknessId = allCardsBagApi.getRandomWeaknessId()
|
local weaknessIds = allCardsBagApi.getRandomWeaknessIds(1)
|
||||||
if weaknessId == nil then
|
if weaknessIds[1] then
|
||||||
broadcastToAll("All basic weaknesses are in play!", { 0.9, 0.2, 0.2 })
|
spawnSingleWeakness(weaknessIds[1])
|
||||||
else
|
|
||||||
spawnSingleWeakness(weaknessId)
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
Player[playerColor].showInputDialog("Specify a trait for the weakness (split multiple eligible traits with '|'):", lastWeaknessTrait,
|
Player[playerColor].showInputDialog("Specify a trait for the weakness (split multiple eligible traits with '|'):", lastWeaknessTrait,
|
||||||
function(text)
|
function(text)
|
||||||
lastWeaknessTrait = text
|
lastWeaknessTrait = text
|
||||||
local availableWeaknesses = allCardsBagApi.buildAvailableWeaknesses(text)
|
local weaknessIds = allCardsBagApi.getRandomWeaknessIds(1, { traits = text })
|
||||||
if #availableWeaknesses > 0 then
|
if weaknessIds[1] then
|
||||||
spawnSingleWeakness(availableWeaknesses[math.random(#availableWeaknesses)])
|
spawnSingleWeakness(weaknessIds[1])
|
||||||
else
|
|
||||||
broadcastToAll("No matching weakness available!", { 0.9, 0.2, 0.2 })
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@ -808,6 +804,6 @@ function spawnSingleWeakness(weaknessId)
|
|||||||
name = "randomWeakness",
|
name = "randomWeakness",
|
||||||
cards = { weaknessId },
|
cards = { weaknessId },
|
||||||
globalPos = self.positionToWorld(startPositions.randomWeakness),
|
globalPos = self.positionToWorld(startPositions.randomWeakness),
|
||||||
rotation = FACE_UP_ROTATION,
|
rotation = FACE_UP_ROTATION
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user