Merge branch 'megamerge'
This commit is contained in:
commit
c45164d8dd
@ -63,7 +63,7 @@
|
||||
"IgnoreFoW": false,
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": false,
|
||||
"LuaScript": "require(\"chaosbag/ChaosBag\")",
|
||||
"LuaScript": "",
|
||||
"LuaScriptState": "",
|
||||
"MaterialIndex": -1,
|
||||
"MeasureMovement": false,
|
||||
|
@ -18,7 +18,7 @@
|
||||
"Curse.16a9a7",
|
||||
"Bless.8e3aab",
|
||||
"ElderSign.0b1aca",
|
||||
"Auto-Fail.e31821",
|
||||
"Auto-fail.e31821",
|
||||
"ElderThing.38609c",
|
||||
"Tablet.1a1506",
|
||||
"Cultist.7d6103",
|
||||
|
@ -37,7 +37,7 @@
|
||||
"LuaScriptState": "",
|
||||
"MeasureMovement": false,
|
||||
"Name": "Custom_Tile",
|
||||
"Nickname": "Auto-Fail",
|
||||
"Nickname": "Auto-fail",
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
|
@ -15,8 +15,7 @@
|
||||
},
|
||||
"ContainedObjects_order": [
|
||||
"ArkhamFantasy-PixelArtMini-Cards.e17c9e",
|
||||
"DrawTokenButtonTooltipRenamer.cc77a8",
|
||||
"WhimsicalsGenericDifficultySelector.05efb4",
|
||||
"GenericDifficultySelector.8112ff",
|
||||
"LuckyPenny.2ab443",
|
||||
"Double-SidedResource.bc81cb",
|
||||
"DescriptivePhaseTracker.b171c8",
|
||||
|
@ -1,45 +0,0 @@
|
||||
{
|
||||
"AltLookAngle": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"Autoraise": true,
|
||||
"ColorDiffuse": {
|
||||
"b": 0,
|
||||
"g": 0,
|
||||
"r": 1
|
||||
},
|
||||
"Description": "By Pyxel",
|
||||
"DragSelectable": true,
|
||||
"GMNotes": "",
|
||||
"GUID": "cc77a8",
|
||||
"Grid": true,
|
||||
"GridProjection": false,
|
||||
"Hands": false,
|
||||
"HideWhenFaceDown": false,
|
||||
"IgnoreFoW": false,
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": false,
|
||||
"LuaScriptState": "",
|
||||
"LuaScript_path": "Fan-MadeAccessories.aa8b38/DrawTokenButtonTooltipRenamer.cc77a8.ttslua",
|
||||
"MeasureMovement": false,
|
||||
"Name": "Checker_red",
|
||||
"Nickname": "Draw Token Button Tooltip Renamer",
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": 30.498,
|
||||
"posY": 4.084,
|
||||
"posZ": -20.929,
|
||||
"rotX": 0,
|
||||
"rotY": 270,
|
||||
"rotZ": 0,
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"scaleZ": 1
|
||||
},
|
||||
"Value": 0,
|
||||
"XmlUI": ""
|
||||
}
|
@ -1,455 +0,0 @@
|
||||
function onLoad()
|
||||
spawnButton("symbols", "Change Tooltips",
|
||||
"Changes tooltip for 'draw chaos token' buttons.", 0, 0.5, 0, 600, 400, 70)
|
||||
end
|
||||
|
||||
function spawnButton( func, text, tool_tip, xPosition, yPosition, zPosition, button_width, button_height, fontsize )
|
||||
scale = self.getScale()
|
||||
scale = scale[1]
|
||||
params = {
|
||||
click_function = func,
|
||||
function_owner = self,
|
||||
label = text,
|
||||
position = {scale * xPosition, yPosition, scale * zPosition},
|
||||
rotation = {0, 0, 0},
|
||||
width = button_width * scale,
|
||||
height = button_height * scale,
|
||||
font_size = fontsize * scale,
|
||||
color = {1, 1, 1},
|
||||
font_color = {0, 0, 0},
|
||||
tooltip = tool_tip
|
||||
}
|
||||
self.createButton(params)
|
||||
end
|
||||
|
||||
function symbols()
|
||||
local tool = "no scenario selected"
|
||||
for _, scenario in ipairs(getObjectFromGUID("fe2ae4").getObjects()) do
|
||||
if scenario.getDescription() == "The Gathering" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull] -2. If you fail, after this skill test, search the encounter deck and discard pile for a [[Ghoul]] enemy, and draw it. Shuffle the encounter deck.\n\n[cultist] Reveal another token. If you fail, take 2 horror.\n\n[tablet] -4. If there is a [[Ghoul]] enemy at your location, take 1 damage and 1 horror."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull] -X. X is the number of [[Ghoul]] enemies at your location.\n\n[cultist] -1. If you fail, take 1 horror.\n\n[tablet] -2. If there is a [[Ghoul]] enemy at your location, take 1 damage.\n\n"
|
||||
end
|
||||
end
|
||||
-- midnight masks
|
||||
if scenario.getDescription() == "The Midnight Masks" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is the total number of doom in play.\n\n[cultist]: -2. Place 1 doom on each [[Cultist]] enemy in play. If there are no [[Cultist]] enemies in play, reveal another token.\n\n[tablet]: -4. If you fail, place all your clues on your location."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the highest number of doom on a [[Cultist]] enemy in play.\n\n[cultist]: -2. Place 1 doom on the nearest [[Cultist]] enemy.\n\n[tablet]: -3. If you fail, place 1 of your clues on your location."
|
||||
end
|
||||
end
|
||||
-- devourer below
|
||||
if scenario.getDescription() == "The Devourer Below" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -3. If you fail, after this skill test, search the encounter deck and discard pile for a [[Monster]] enemy, and draw it. Shuffle the encounter deck.\n\n[cultist]: -4. Place 2 doom on the nearest enemy.\n\n[tablet]: -5. If there is a [[Monster]] enemy at your location, take 1 damage and 1 horror.\n\n[elder_thing]: -7. If there is an [[Ancient One]] enemy in play, reveal another token."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the number of [[Monster]] enemies in play.\n\n[cultist]: -2. Place 1 doom on the nearest enemy.\n\n[tablet]: -3. If there is a [[Monster]] enemy at your location, take 1 damage.\n\n[elder_thing]: -5. If there is an [[Ancient One]] enemy in play, reveal another token."
|
||||
end
|
||||
end
|
||||
-- extracurricular activity symbols
|
||||
if scenario.getDescription() == "Extracurricular Activity" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2. If you fail, discard the top 5 cards of your deck.\n\n[cultist]: -1 (-5 instead if there are 10 or more cards in your discard pile).\n\n[elder_thing]: -X. Discard the top 3 cards of your deck. X is the total printed cost of those discarded cards."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1. If you fail, discard the top 3 cards of your deck.\n\n[cultist]: -1 (-3 instead if there are 10 or more cards in your discard pile).\n\n[elder_thing]: -X. Discard the top 2 cards of your deck. X is the total printed cost of those discarded cards."
|
||||
end
|
||||
end
|
||||
-- The house always wins symbols
|
||||
if scenario.getDescription() == "The House Always Wins" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -3. You may spend 3 resources to treat this token as a 0, instead.\n\n[cultist]: -3. If you fail, discard 3 resources.\n\n[tablet]: -2. Discard 3 resources."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -2. You may spend 2 resources to treat this token as a 0, instead.\n\n[cultist]: -3. If you succeed, gain 3 resources.\n\n[tablet]: -2. If you fail, discard 3 resources."
|
||||
end
|
||||
end
|
||||
-- Miskatonic museum symbols
|
||||
if scenario.getDescription() == "The Miskatonic Museum" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 (-4 instead if Hunting Horror is at your location.)\n\n[cultist]: -3. If you fail, search the encounter deck, discard pile, and the void for Hunting Horror and spawn it at your location, if able.\n\n[tablet]: -4. If Hunting Horror is at your location, it immediately attacks you.\n\n[elder_thing]: -5. If you fail, discard an asset you control."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 (-3 instead if Hunting Horror is at your location.)\n\n[cultist]: -1. If you fail, search the encounter deck, discard pile, and the void for Hunting Horror and spawn it at your location, if able.\n\n[tablet]: -2. Return 1 of your clues to your current location.\n\n[elder_thing]: -3. If you fail, discard an asset you control."
|
||||
end
|
||||
end
|
||||
-- essex county express symbols
|
||||
if scenario.getDescription() == "The Essex County Express" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is 1 more than the current Agenda #. \n\n[cultist]: Reveal another token. If you fail and it is your turn, lose all remaining actions and end your turn immediately.\n\n[tablet]: -4. Add 1 doom token to each Cultist enemy in play.\n\n[elder_thing]: -3. If you fail, choose and discard a card from your hand for each point you failed by."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the current Agenda #.\n\n[cultist]: -1. If you fail and it is your turn, lose all remaining actions and end your turn immediately.\n\n[tablet]: -2. Add 1 doom token to the nearest Cultist enemy.\n\n[elder_thing]: -3. If you fail, choose and discard a card from your hand."
|
||||
end
|
||||
end
|
||||
--blood on the Altar
|
||||
if scenario.getDescription() == "Blood on the Altar" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -1 for each location in play with no encounter card underneath it.\n\n[cultist]: -4. If you fail, add 1 clue from the token pool to your location.\n\n[tablet]: -3. Reveal another token.\n\n[elder_thing]: -3. Place 1 doom on the current agenda."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 for each location in play with no encounter card underneath it (max -4).\n\n[cultist]: -2. If you fail, add 1 clue from the token pool to your location.\n\n[tablet]: -2. If you are in the Hidden Chamber, reveal another token.\n\n[elder_thing]: -3. If you fail, place 1 doom on the current agenda."
|
||||
end
|
||||
end
|
||||
--undimensioned and unseen
|
||||
if scenario.getDescription() == "Undimensioned and Unseen" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 for each Brood of Yog-Sothoth in play.\n\n[cultist]: Reveal another token. If you fail this test, take 1 horror and 1 damage.\n\n[tablet]: 0. You must either remove all clue tokens from a Brood of Yog-Sothoth in play, or this test automatically fails.\n\n[elder_thing]: -5. If this token is revealed during an attack or evasion attempt against a Brood of Yog-Sothoth, it immediately attacks you."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 for each Brood of Yog-Sothoth in play.\n\n[cultist]: Reveal another token. If you fail this test, take 1 horror.\n\n[tablet]: 0. You must either remove all clue tokens from a Brood of Yog-Sothoth in play, or this token's modifier is -4 instead.\n\n[elder_thing]: -3. If this token is revealed during an attack or evasion attempt against a Brood of Yog-Sothoth, it immediately attacks you."
|
||||
end
|
||||
end
|
||||
-- where doom Awaits
|
||||
if scenario.getDescription() == "Where Doom Awaits" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 (-5 instead if you are at an [[Altered]] location).\n\n[cultist]: Reveal another token. Cancel the effects and icons of each skill card committed to this test.\n\n[tablet]: -3. If it is Agenda 2, you automatically fail instead.\n\n[elder_thing]: -X. Discard the top 3 cards of your deck. X is the total printed cost of those discarded cards."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 (-3 instead if you are at an [[Altered]] location).\n\n[cultist]: Reveal another token. Cancel the effects and icons of each skill card committed to this test.\n\n[tablet]: -2 (-4 instead if it is Agenda 2).\n\n[elder_thing]: -X. Discard the top 2 cards of your deck. X is the total printed cost of those discarded cards."
|
||||
end
|
||||
end
|
||||
--lost in time and space
|
||||
if scenario.getDescription() == "Lost in Time and Space" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -1 for each [[Extradimensional]] location in play.\n\n[cultist]: Reveal another token. After this skill test, discard cards from the top of the encounter deck until a location is discarded. Put that location into play and move there.\n\n[tablet]: -5. If Yog-Sothoth is in play, it attacks you after this skill test.\n\n[elder_thing]: -X. X is twice the shroud value of your location. If you fail and your location is [[Extradimensional]], discard it."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 for each [[Extradimensional]] location in play (max -5).\n\n[cultist]: Reveal another token. If you fail, after this skill test, discard cards from the top of the encounter deck until a location is discarded. Put that location into play and move there.\n\n[tablet]: -3. If Yog-Sothoth is in play, it attacks you after this skill test.\n\n[elder_thing]: -X. X is the shroud value of your location. If you fail and your location is [[Extradimensional]], discard it."
|
||||
end
|
||||
end
|
||||
-- curtain call
|
||||
if scenario.getDescription() == "Curtain Call" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X, where X is the amount of horror on you. (If you have no horror on you, X is 1.)\n\n[cultist] [tablet] [elder_thing]: -5. If your location has at least 1 horror on it, take 1 horror <i>(from the token pool)</i>. If your location has no horror on it, place 1 horror on it instead."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 (-3 instead if you have 3 or more horror on you).\n\n[cultist] [tablet] [elder_thing]: -4. If your location has at least 1 horror on it, take 1 horror <i>(from the token pool)</i>. If your location has no horror on it, place 1 horror on it instead."
|
||||
end
|
||||
end
|
||||
-- Last King
|
||||
if scenario.getDescription() == "The Last King" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: Reveal another token. If you fail, place 1 doom on the [[Lunatic]] enemy in play with the most remaining health.\n\n[cultist]: -3. Place 1 of your clues on your location.\n\n[tablet]: -4. Take 1 horror.\n\n[elder_thing]: -X. X is the shroud value of your location. If you fail, take 1 damage."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: Reveal another token. If you fail, place 1 doom on a [[Lunatic]] enemy in play.\n\n[cultist]: -2. If you fail, place 1 of your clues on your location.\n\n[tablet]: -4. If you fail, take 1 horror.\n\n[elder_thing]: -X. X is the shroud value of your location."
|
||||
end
|
||||
end
|
||||
-- Echoes Past
|
||||
if scenario.getDescription() == "Echoes of the Past" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is the total number of doom on enemies in play.\n\n[cultist]: -4. Place 1 doom on the nearest enemy.\n\n[tablet]: -4. Discard a random card from your hand.\n\n[elder_thing]: -4. If there is an enemy at your location, take 1 horror."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the highest number of doom on an enemy in play.\n\n[cultist]: -2. If you fail, place 1 doom on the nearest enemy.\n\n[tablet]: -2. If you fail, discard a random card from your hand.\n\n[elder_thing]: -2. If you fail and there is an enemy at your location, take 1 horror."
|
||||
end
|
||||
end
|
||||
-- Unspeakable Oath
|
||||
if scenario.getDescription() == "The Unspeakable Oath" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: Reveal another token. If you fail, randomly choose an enemy from among the set-aside [[Monster]] enemies and place it beneath the act deck without looking at it. (Limit once per test.)\n\n[cultist]: -X. X is the amount of horror on you. If you fail, take 1 horror.\n\n[tablet]: -X. X is the base shroud value of your location. If you fail, take 1 horror.\n\n[elder_thing]: 0. Either randomly choose an enemy from among the set-aside [[Monster]] enemies and place it beneath the act deck without looking at it, or this test automatically fails instead."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1. If you fail, randomly choose an enemy from among the set-aside [[Monster]] enemies and place it beneath the act deck without looking at it.\n\n[cultist]: -X. X is the amount of horror on you.\n\n[tablet]: -X. X is the base shroud value of your location.\n\n[elder_thing]: 0. Either randomly choose an enemy from among the set-aside [[Monster]] enemies and place it beneath the act deck without looking at it, or this test automatically fails instead."
|
||||
end
|
||||
end
|
||||
-- A Phantom of Truth
|
||||
if scenario.getDescription() == "A Phantom of Truth" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is the amount of doom in play.\n\n[cultist]: -2. Move each unengaged [[Byakhee]] in play once toward the nearest investigator.\n\n[tablet]: -4. Cancel the effects and icons of each skill card committed to this test.\n\n[elder_thing]: -3. If you fail, lose 1 resource for each point you failed by."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the amount of doom in play (max 5).\n\n[cultist]: -2. If you fail, move each unengaged [[Byakhee]] in play once toward the nearest investigator.\n\n[tablet]: -3. Cancel the effects and icons of each skill card committed to this test.\n\n[elder_thing]: -2. If you fail, lose 1 resource for each point you failed by."
|
||||
end
|
||||
end
|
||||
-- The Pallid Mask
|
||||
if scenario.getDescription() == "The Pallid Mask" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is the number of locations away from the starting location you are.\n\n[cultist]: -3. If this token is revealed during an attack and this skill test is successful, this attack deals no damage.\n\n[tablet]: -3. If there is a [[Ghoul]] or [[Geist]] enemy at your location, it readies and attacks you (if there is more than one, choose one).\n\n[elder_thing]: -4. If you fail, search the encounter deck and discard pile for a [[Ghoul]] or [[Geist]] enemy and draw it."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the number of locations away from the starting location you are (max 5).\n\n[cultist]: -2. If this token is revealed during an attack, and this skill test is successful, this attack deals 1 less damage.\n\n[tablet]: -2. If there is a ready [[Ghoul]] or [[Geist]] enemy at your location, it attacks you (if there is more than one, choose one).\n\n[elder_thing]: -3. If you fail, search the encounter deck and discard pile for a [[Ghoul]] or [[Geist]] enemy and draw it."
|
||||
end
|
||||
end
|
||||
-- Dim Carcosa
|
||||
if scenario.getDescription() == "Dim Carcosa" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is the amount of horror on you.\n\n[cultist]: Reveal another token. If you fail, take 2 horror.\n\n[tablet]: -5. If you fail and Hastur is in play, place 1 clue on your location <i>(from the token bank)</i>.\n\n[elder_thing]: -5. If this token is revealed during an attack or evasion attempt against a [[Monster]] or [[Ancient One]] enemy, lose 1 action."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -2 (-4 instead if you have no sanity remaining).\n\n[cultist]: Reveal another token. If you fail, take 1 horror.\n\n[tablet]: -3. If you fail and Hastur is in play, place 1 clue on your location <i>(from the token bank)</i>.\n\n[elder_thing]: -3. If this token is revealed during an attack or evasion attempt against a [[Monster]] or [[Ancient One]] enemy, lose 1 action."
|
||||
end
|
||||
end
|
||||
if scenario.getDescription() == "Black Stars Rise" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is the total amount of doom on agendas in play.\n\n[cultist]: Reveal another token. If there is an enemy with 1 or more doom on it at your location, this test automatically fails instead.\n\n[tablet]: Reveal another token. If you do not succeed by at least 1, place 1 doom on each agenda.\n\n[elder_thing]: -3. If you fail, search the encounter deck and discard pile for a [[Byakhee]] enemy and draw it."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the highest amount of doom on an agenda in play.\n\n[cultist]: Reveal another token. If this token is revealed during an attack or evasion attempt against an enemy with doom on it, this skill test automatically fails instead.\n\n[tablet]: Reveal another token. If you fail, place 1 doom on each agenda.\n\n[elder_thing]: -2. If you fail, search the encounter deck and discard pile for a [[Byakhee]] enemy and draw it."
|
||||
end
|
||||
end
|
||||
-- untamed Wilds
|
||||
if scenario.getDescription() == "The Untamed Wilds" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is 1 higher than the number of vengeance points in the victory display.\n\n[cultist]: -X. X is the number of locations in play.\n\n[tablet]: -X. X is the number of cards in the exploration deck (min 3).\n\n[elder_thing]: -3. If you are poisoned, this test automatically fails instead. If you are not poisoned and you fail, put a set-aside Poisoned weakness into play in your threat area."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the number of vengeance points in the victory display.\n\n[cultist]: -X. X is the number of locations in play (max 5).\n\n[tablet]: -X. X is the number of cards in the exploration deck (max 5).\n\n[elder_thing]: -2. If you are poisoned, this test automatically fails instead."
|
||||
end
|
||||
end
|
||||
--The doom of Eztli
|
||||
if scenario.getDescription() == "The Doom of Eztli" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 (-4 instead if there is doom on your location).\n\n[cultist] [tablet]: -X. X is the total amount of doom on locations in play.\n\n[elder_thing]: Reveal another chaos token. Place 1 doom on your location."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 (-3 instead if there is doom on your location).\n\n[cultist] [tablet]: -X. X is the number of locations with doom on them.\n\n[elder_thing]: Reveal another chaos token. If you fail, place 1 doom on your location."
|
||||
end
|
||||
end
|
||||
--Threads of Fate
|
||||
if scenario.getDescription() == "Threads of Fate" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull] : -X. X is the total number of doom in play.\n\n[cultist]: -2. If you do not succeed by at least 2, take 1 direct damage.\n\n[tablet]: -2. If you do not succeed by at least 2, place 1 doom on each [[cultist]] enemy.\n\n[elder_thing]: -3. If you fail, lose 1 of your clues."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull] : -X. X is the highest number of doom on a [[cultist]] enemy.\n\n[cultist]: -2. If you do not succeed by at least 1, take 1 damage.\n\n[tablet]: -2. If you do not succeed by at least 1, place 1 doom on the nearest [[cultist]] enemy.\n\n[elder_thing]: -2. If you fail, lose 1 of your clues."
|
||||
end
|
||||
end
|
||||
--The boundary beyond
|
||||
if scenario.getDescription() == "The Boundary Beyond" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 (-4 instead if you are at an [[Ancient]] location).\n\n[cultist]: Reveal another token. If you fail, place 1 doom on each [[Cultist]] enemy.\n\n[tablet]: Reveal another token. If you fail, each [[Serpent]] enemy at your location attacks you.\n\n[elder_thing]: -4. Place 1 clue <i>(from the token pool)</i> on the nearest [[Ancient]] location."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 (-3 instead if you are at an [[Ancient]] location).\n\n[cultist]: Reveal another token. If you fail, place 1 doom on a [[Cultist]] enemy.\n\n[tablet]: Reveal another token. If you fail and there is a [[Serpent]] enemy at your location, it attacks you.\n\n[elder_thing]: -4. If you fail, place 1 clue <i>(from the token pool)</i> on the nearest [[Ancient]] location."
|
||||
end
|
||||
end
|
||||
--Heart of the elders p1
|
||||
if scenario.getDescription() == "Heart of the Elders" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 (-4 instead if you are in a [[Cave]] location).\n\n[cultist]: -3. If you fail, place 1 doom on your location.\n\n[tablet]: -3. If you are poisoned, this test automatically fails instead. If you are not poisoned and you fail, put a set-aside Poisoned weakness into play in your threat area.\n\n[elder_thing]: -4. If you fail, take 1 horror."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 (-3 instead if you are in a [[Cave]] location).\n\n[cultist]: -2. If you fail, place 1 doom on your location.\n\n[tablet]: -2. If you are poisoned, this test automatically fails instead.\n\n[elder_thing]: -3. If you fail, take 1 horror."
|
||||
end
|
||||
end
|
||||
-- City of Archives
|
||||
if scenario.getDescription() == "The City of Archives" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 (if you have 5 or more cards in your hand, you automatically fail instead).\n\n[cultist] or [elder_thing]: -2. Place 1 of your clues on your location.\n\n[tablet]: -3. For each point you fail by, discard 1 random card from your hand."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 (-3 instead if you have 5 or more cards in your hand).\n\n[cultist] or [elder_thing]: -2. If you fail, place 1 of your clues on your location.\n\n[tablet]: -3. If you fail, discard 1 random card from your hand."
|
||||
end
|
||||
end
|
||||
--Depths of Yoth
|
||||
if scenario.getName() == "Scenario - Easy/Standard" then
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the current depth level.\n\n[cultist]: Reveal another token. If you fail, each [[Serpent]] enemy at your location or a connecting location heals 2 damage.\n\n[tablet]: Reveal another token. If you fail, place 1 clue on your location <i>(from the token pool)</i>.\n\n[elder_thing]: -2. If there are 3 or more vengeance points in the victory display, you automatically fail this test, instead."
|
||||
end
|
||||
--hard
|
||||
if scenario.getName() == "Scenario - Hard/Expert" then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is the current depth level. If you fail, take 1 horror.\n\n[cultist]: Reveal another token. If you fail, each [[Serpent]] enemy at your location or a connecting location heals 2 damage.\n\n[tablet]: Reveal another token. If you fail, place 1 clue on your location <i>(from the token pool)</i>.\n\n[elder_thing]: -4. If there are 3 or more vengeance points in the victory display, you automatically fail this test, instead."
|
||||
end
|
||||
--Shattered Aeons
|
||||
if scenario.getDescription() == "Shattered Aeons" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -3 (-5 instead if the Relic of Ages is at your location).\n\n[cultist]: -3. If you do not succeed by at least 1, place 1 doom on each [[Cultist]] enemy.\n\n[tablet]: -3. If you are poisoned, this test automatically fails instead. If you are not poisoned and you fail, put a set-aside Poisoned weakness into play in your threat area.\n\n[elder_thing]: -3. Shuffle the topmost [[Hex]] treachery in the encounter discard pile into the exploration deck."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -2 (-4 instead if the Relic of Ages is at your location).\n\n[cultist]: -2. If you do not succeed by at least 1, place 1 doom on the nearest [[Cultist]] enemy.\n\n[tablet]: -2. If you are poisoned, this test automatically fails instead.\n\n[elder_thing]: -2. If you fail, shuffle the topmost [[Hex]] treachery in the encounter discard pile into the exploration deck."
|
||||
end
|
||||
end
|
||||
--secret scenario
|
||||
if scenario.getDescription() == "Turn Back Time" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X . X is the total amount of doom on locations.\n\n[elder_thing]: -6. Place 1 doom on your location."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X . X is the number of locations with doom on them.\n\n[elder_thing]: -4. If you fail, place 1 doom on your location."
|
||||
end
|
||||
end
|
||||
--Dissappearance Twilight
|
||||
if scenario.getDescription() == "Disappearance at the Twilight Estate" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -5. If you fail and this is an attack or evasion attempt, resolve each haunted ability on your location."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -3. If you fail and this is an attack or evasion attempt, resolve each haunted ability on your location."
|
||||
end
|
||||
end
|
||||
--Witching Hour
|
||||
if scenario.getDescription() == "The Witching Hour" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2. Discard cards from the top of the encounter deck equal to this test's difficulty.\n\n[tablet]: -2. If you fail, after this test resolves, draw the bottommost treachery in the encounter discard pile.\n\n[elder_thing]: -4. If you fail, ready each [[Witch]] enemy at your location and at each connecting location. Heal all damage from each of those enemies."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1. For each point you fail by, discard the top card of the encounter deck.\n\n[tablet]: -1. If you fail, after this test resolves, draw the bottommost treachery in the encounter discard pile.\n\n[elder_thing]: -3. If you fail, choose an exhausted or damaged [[Witch]] enemy at your location or at a connecting location. Ready that enemy and heal all damage from it."
|
||||
end
|
||||
end
|
||||
--Death's Doorstep
|
||||
if scenario.getDescription() == "At Death's Doorstep" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 (-4 instead if your location is haunted).\n\n[tablet]: -3. If this is an attack or evasion attempt, resolve each haunted ability on your location.\n\n[elder_thing]: -4. If there is a [[Spectral]] enemy at your location, take 1 damage and 1 horror."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 (-3 instead if your location is haunted).\n\n[tablet]: -2. If you fail and this is an attack or evasion attempt, resolve each haunted ability on your location.\n\n[elder_thing]: -2. If there is a [[Spectral]] enemy at your location, take 1 damage."
|
||||
end
|
||||
end
|
||||
--Secret Name
|
||||
if scenario.getDescription() == "The Secret Name" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 (-4 instead if you are at an [[Extradimensional]] location).\n\n[cultist]: Reveal another chaos token. If you fail, discard the top 5 cards of the encounter deck.\n\n[tablet]: -3. If you fail and Nahab is in play, she attacks you <i>(regardless of her current location)</i>.\n\n[elder_thing]: -4. Resolve the hunter keyword on each enemy in play."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 (-3 instead if you are at an [[Extradimensional]] location).\n\n[cultist]: Reveal another chaos token. If you fail, discard the top 3 cards of the encounter deck.\n\n[tablet]: -2. If you fail and Nahab is at your location, she attacks you.\n\n[elder_thing]: -3. If you fail, resolve the hunter keyword on each enemy in play."
|
||||
end
|
||||
end
|
||||
--Wages of Sin
|
||||
if scenario.getDescription() == "The Wages of Sin" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is the number of copies of Unfinished Business in the victory display. Reveal another token.\n\n[cultist]: -4. Until the end of the rount, each Heretic enemy in play gets +1 fight and +1 evade.\n\n[tablet]: -4. If you fail, trigger the forced ability on a copy of Unfinished Business in your threat area as if it were the end of the round.\n\n[elder_thing]: -2. If this is an attack or evasion attempt, resolve each haunted ability on your location."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is 1 higher than the number of copies of Unfinished Business in the victory display.\n\n[cultist]: -3. Until the end of the round, each Heretic enemy in play gets +1 fight and +1 evade.\n\n[tablet]: -3. If you fail, trigger the forced ability on a copy of Unfinished Business in yout threat area as if it were the end of the round.\n\n[elder_thing]: -2. If you fail and this is an attack or evasion attempt, resolve each haunted ability on your location."
|
||||
end
|
||||
end
|
||||
-- For The Greater Good
|
||||
if scenario.getDescription() == "For the Greater Good" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is the total number of doom among [[Cultist]] enemies in play.\n\n[cultist]: -2. Reveal another token.\n\n[tablet]: -3. If you fail, place 1 doom on each [[Cultist]] enemy in play. If there are no [[Cultist]] enemies in play, reveal another token.\n\n[elder_thing]: -3. If you fail, move all doom from the [[Cultist]] enemy with the most doom on it to the current agenda. If no [[Cultist]] enemies in play have doom on them, reveal another token."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the highest number of doom on a [[Cultist]] enemy in play.\n\n[cultist]: -2. Reveal another token.\n\n[tablet]: -3. If you fail, place 1 doom on the nearest [[Cultist]] enemy.\n\n[elder_thing]: -3. If you fail, move 1 doom from the nearest [[Cultist]] enemy to the current agenda."
|
||||
end
|
||||
end
|
||||
--Union and Disillusion
|
||||
if scenario.getDescription() == "Union and Disillusion" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -3. If this is a skill test during a <b>circle</b> action, reveal another token.\n\n[cultist]: -4. If you have no damage on you, take 1 damage. If you have no horror on you, take 1 horror.\n\n[tablet]: -4. If you fail, a [[Spectral]] enemy at your location attacks you <i>(even if it is exhausted).</i>\n\n[elder_thing]: -4. If this is a skill test during a <b>circle</b> action and you fail, resolve each haunted ability on your location."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -2. If this is a skill test during a <b>circle</b> action, reveal another token.\n\n[cultist]: -3. If you have no damage on you, take 1 damage. If you have no horror on you, take 1 horror.\n\n[tablet]: -3. If you fail, a [[Spectral]] enemy at your location attacks you <i>(even if it is exhausted).</i>\n\n[elder_thing]: -3. If this is a skill test during a <b>circle</b> action and you fail, resolve each haunted ability on your location."
|
||||
end
|
||||
end
|
||||
--Clutches of Chaos
|
||||
if scenario.getDescription() == "In the Clutches of Chaos" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is 1 higher than the total amount of doom and breaches on your location.\n\n[cultist]: Reveal another token. If there are fewer than 3 breaches on your location, place 1 breach on your location.\n\n[tablet]: -3. For each point you fail by, remove 1 breach from the current act.\n\n[elder_thing]: -4. If you fail, place 1 breach on a random location."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the total amount of doom and breaches on your location.\n\n[cultist]: Reveal another token. If there are fewer than 3 breaches on your location, place 1 breach on your location.\n\n[tablet]: -2. For each point you fail by, remove 1 breach from the current act.\n\n[elder_thing]: -3. If you fail, place 1 breach on a random location."
|
||||
end
|
||||
end
|
||||
--Before the Black Throne
|
||||
if scenario.getDescription() == "Before the Black Throne" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is the amount of doom on Azathoth, to a minimum of 2.\n\n[cultist]: Reveal another token. If you fail, search the encounter deck and discard pile for a [[Cultist]] enemy and draw it. Shuffle the encounter deck.\n\n[tablet]: -3. If you fail, Azathoth attacks you.\n\n[elder_thing]: -6. If your modified skill value for this test is 0, place 1 doom on Azathoth."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is half of the doom on Azathoth (rounded up), to a minimum of 2.\n\n[cultist]: Reveal another token. If you fail, search the encounter deck and discard pile for a [[Cultist]] enemy and draw it. Shuffle the encounter deck.\n\n[tablet]: -2. If you fail, Azathoth attacks you.\n\n[elder_thing]: -4. If your modified skill value for this test is 0, place 1 doom on Azathoth."
|
||||
end
|
||||
end
|
||||
--Beyond the gates of sleep
|
||||
if scenario.getDescription() == "Beyond the Gates of Sleep" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull] : -X. X is the number of cards in your hand.\n\n[cultist]: -X. X is the number of revealed [[Woods]] locations.\n\n[tablet]: -2. If this is an attack or evasion attempt against a swarming enemy, add 1 swarm card to it."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull] : -X. X is half the number of cards in your hand (rounded up).\n\n[cultist]: -X. X is the number of revealed Enchanted Woods locations.\n\n[tablet]: -2. If you fail and this is an attack or evasion attempt against a swarming enemy, add 1 swarm card to it."
|
||||
end
|
||||
end
|
||||
--Waking Nightmare
|
||||
if scenario.getDescription() == "Waking Nightmare" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 (-4 instead if you are engaged with a [[Staff]] enemy).\n\n[cultist]: Reveal another chaos token. If it is agenda 2 or 3, make an infestation test.\n\n[elder_thing]: -X. X is 1 higher than the number of infested locations."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 (-3 instead if you are engaged with a [[Staff]] enemy).\n\n[cultist]: Reveal another chaos token. If you fail and it is agenda 2 or 3, make an infestation test.\n\n[elder_thing]: -X. X is the number of infested locations."
|
||||
end
|
||||
end
|
||||
--The search for kadath
|
||||
if scenario.getDescription() == "The Search for Kadath" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is 1 more than the number of Signs of the Gods the investigators have uncovered.\n\n[cultist]: Reveal another token. If this token is revealed during an investigation and this skill test fails, increase that location's shroud by 2 for the remainder of the round.\n\n[tablet]: -3. If you fail, either take 1 damage and 1 horror, or place 1 doom on the current agenda.\n\n[elder_thing]: +1. The black cat points you in the right direction. If this token is revealed during an investigation and you succeed, discover 1 additional clue."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the number of Signs of the Gods the investigators have uncovered.\n\n[cultist]: Reveal another token. If this token is revealed during an investigation and this skill test fails, increase that location's shroud by 1 for the remainder of the round.\n\n[tablet]: -2. If you fail, either take 1 damage and 1 horror, or place 1 doom on the current agenda.\n\n[elder_thing]: +2. The black cat points you in the right direction. If this token is revealed during an investigation and you succeed, discover 1 additional clue."
|
||||
end
|
||||
end
|
||||
--A thousand shapes of horror
|
||||
if scenario.getDescription() == "A Thousand Shapes of Horror" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 (-4 instead if you are at a [[Graveyard]] location).\n\n[cultist]: Reveal another token. If you fail and The Unnamable is in play, it attacks you (regardless of its current location).\n\n[tablet]: +1. The black cat causes a distraction. If this test is successful, choose and evade an enemy at any location with a fight value of X or lower, where X is the amount you succeeded by.\n\n[elder_thing]: -3. If you fail, you must either place 1 of your clues on your location or take 1 damage."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 (-3 instead if you are at a [[Graveyard]] location).\n\n[cultist]: Reveal another token. If you fail and The Unnamable is in play, it attacks you (regardless of its current location).\n\n[tablet]: +2. The black cat causes a distraction. If this test is successful, choose and evade an enemy at any location with a fight value of X or lower, where X is the amount you succeeded by.\n\n[elder_thing]: -2. If you fail, you must either place 1 of your clues on your location or take 1 damage."
|
||||
end
|
||||
end
|
||||
--Dark Side of the moon
|
||||
if scenario.getDescription() == "Dark Side of the Moon" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is your alarm level.\n\n[cultist]: Reveal another token. If you fail and your alarm level is higher than your modified skill value, after this skill test ends, draw the top card of the encounter deck.\n\n[tablet]: -2. If you fail, raise your alarm level by 1.\n\n[elder_thing]: 0. The black cat summons several other cats to help. If this token is revealed during an evasion attempt and you succeed, deal 2 damage to the evaded enemy."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is half your alarm level (rounded up).\n\n[cultist]: Reveal another token. If you fail and your alarm level is higher than your modified skill value, after this skill test ends, draw the top card of the encounter deck.\n\n[tablet]: -1. If you fail, raise your alarm level by 1.\n\n[elder_thing]: +1. The black cat summons several other cats to help. If this token is revealed during an evasion attempt and you succeed, deal 2 damage to the evaded enemy."
|
||||
end
|
||||
end
|
||||
--point of no return
|
||||
if scenario.getDescription() == "Point of No Return" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is 1 more than the amount of damage on this card.\n\n[cultist]: Reveal another token. If you fail, after this skill test ends, draw the top card of the encounter deck.\n\n[tablet]: 0. The black cat helps you navigate through the death-fire. If this token is revealed during an investigation and you succeed, draw 1 card.\n\n[elder_thing]: -4. If you fail by 2 or more, choose a ready enemy at your location or a connecting location. That enemy moves to your location, engages you, and makes an immediate attack."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the amount of damage on this card.\n\n[cultist]: Reveal another token. If you fail, after this skill test ends, draw the top card of the encounter deck.\n\n[tablet]: +1. The black cat helps you navigate through the death-fire. If this token is revealed during an investigation and you succeed, draw 1 card.\n\n[elder_thing]: -3. If you fail by 2 or more, choose a ready enemy at your location or a connecting location. That enemy moves to your location, engages you, and makes an immediate attack."
|
||||
end
|
||||
end
|
||||
--where the gods dwell
|
||||
if scenario.getDescription() == "Where the Gods Dwell" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is the number of the current act plus the number of the current agenda.\n\n[cultist]: Reveal another token. If you fail, place 1 doom on the current agenda. This effect may cause the current agenda to advance.\n\n[tablet]: -6. If you fail, choose and reveal a copy of Nyarlathotep in your hand. It attacks you and is shuffled into the encounter deck.\n\n[elder_thing]: -1. The black cat reminds you that it's all a dream."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the number of the current act.\n\n[cultist]: Reveal another token. If you fail, place 1 doom on the current agenda.\n\n[tablet]: -4. If you fail, choose and reveal a copy of Nyarlathotep in your hand. It attacks you and is shuffled into the encounter deck.\n\n[elder_thing]: 0. The black cat reminds you that it's all a dream."
|
||||
end
|
||||
end
|
||||
--weaver of the cosmos
|
||||
if scenario.getDescription() == "Weaver of the Cosmos" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is the amount of doom on locations in play.\n\n[cultist]: Reveal another token. If you fail, and there is an [[Ancient One]] enemy at your location, it attacks you.\n\n[tablet]: -1. The black cat tears at the web with its claws. If you succeed by 2 or more, remove 1 doom from your location.\n\n[elder_thing]: -4. If this skill test fails during an attack against a [[Spider]] enemy, place 1 doom on that enemy's location."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the highest amount of doom on a location in play.\n\n[cultist]: Reveal another token. If you fail, and there is an [[Ancient One]] enemy at your location, it attacks you.\n\n[tablet]: 0. The black cat tears at the web with its claws. If you succeed by 2 or more, remove 1 doom from your location.\n\n[elder_thing]: -3. If this skill test fails during an attack against a [[Spider]] enemy, place 1 doom on that enemy's location."
|
||||
end
|
||||
end
|
||||
--pit of despair
|
||||
if scenario.getDescription() == "The Pit of Despair" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 (-3 instead if your location is partially flooded; -4 instead if your location is fully flooded).\n\n[cultist]: -2. If your location is flooded, take 1 damage.\n\n[tablet]: -2. If you control a key, take 1 horror.\n\n[elder_thing]: -3. If The Amalgam is in the depths, put it into play engaged with you."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 (-2 instead if your location is partially flooded; -3 instead if your location is fully flooded).\n\n[cultist]: -2. If you fail and your location is flooded, take 1 damage.\n\n[tablet]: -2. If you fail and you control a key, take 1 horror.\n\n[elder_thing]: -3. If you fail and The Amalgam is in the depths, put it into play engaged with you."
|
||||
end
|
||||
end
|
||||
--vanishing of elena harper
|
||||
if scenario.getDescription() == "The Vanishing of Elina Harper" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is 1 more than the current agenda number.\n\n[cultist]: -2. Place 1 doom on the nearest enemy (2 doom instead if you failed).\n\n[tablet]: -3. Take 1 horror (1 horror and 1 damage instead if you failed).\n\n[elder_thing]: -4. Place 1 of your clues on your location (2 clues instead if you failed)."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the current agenda number.\n\n[cultist]: -2. If you fail, place 1 doom on the nearest enemy.\n\n[tablet]: -3. If you fail, take 1 horror.\n\n[elder_thing]: -4. If you fail, place 1 of your clues on your location."
|
||||
end
|
||||
end
|
||||
--in too deep
|
||||
if scenario.getDescription() == "In Too Deep" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 for each location to the east of your location (on the same row).\n\n[cultist]: -4. If you fail, move to the connecting location to the east, ignoring all barriers.\n\n[tablet]: -5. If you fail, choose a connecting location with no barriers between it and your location. Place 1 barrier between the two locations.\n\n[elder_thing]: -X. X is twice the number of barriers between your location and all connecting locations."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 for each location to the east of your location (on the same row).\n\n[cultist]: -2. If you fail, move to the connecting location to the east, ignoring all barriers.\n\n[tablet]: -3. If you fail, choose a connecting location with no barriers between it and your location. Place 1 barrier between the two locations.\n\n[elder_thing]: -X. X is the number of barriers between your location and all connecting locations."
|
||||
end
|
||||
end
|
||||
--devil reef
|
||||
if scenario.getDescription() == "Devil Reef" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -X. X is 1 more than the number of keys the investigators control.\n\n[cultist]: -3. If this is an attack or evasion attempt against a [[Deep One]] enemy, it engages you. (If it is already engaged with you, it disengages first, then re-engages you.)\n\n[tablet]: -4. If you are not in a vehicle, take 1 damage.\n\n[elder_thing]: -5. If your location has a key on it, take 1 horror."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -X. X is the number of keys the investigators control.\n\n[cultist]: -2. If you fail and this is an attack or evasion attempt against a [[Deep One]] enemy, it engages you. (If it is already engaged with you, it disengages first, then re-engages you.)\n\n[tablet]: -3. If you fail and you are not in a vehicle, take 1 damage.\n\n[elder_thing]: -4. If you fail and your location has a key on it, take 1 horror."
|
||||
end
|
||||
end
|
||||
--horror in high gear
|
||||
if scenario.getDescription() == "Horror in High Gear" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 (-4 instead if there are 6 or fewer locations remaining in the Road deck).\n\n[cultist]: -2. For each point you fail by, an investigator in your vehicle places 1 of their clues on your location.\n\n[tablet]: -3. For each point you fail by, an investigator in your vehicle loses 1 resource.\n\n[elder_thing]: -4. Resolve the hunter keyword on each enemy in play."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 (-3 instead if there are 6 or fewer locations remaining in the Road deck).\n\n[cultist]: -1. For each point you fail by, an investigator in your vehicle places 1 of their clues on your location.\n\n[tablet]: -2. For each point you fail by, an investigator in your vehicle loses 1 resource.\n\n[elder_thing]: -4. If you fail, resolve the hunter keyword on each enemy in play."
|
||||
end
|
||||
end
|
||||
--light in the fog
|
||||
if scenario.getDescription() == "A Light in the Fog" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2. If your location is flooded, reveal an additional chaos token.\n\n[cultist]: -2. If you fail, after this test ends, increase the flood level of your location (if you cannot, take 1 horror instead).\n\n[tablet]: -3. If you fail this test and your location is flooded, take 2 damage.\n\n[elder_thing]: -4. Move the nearest unengaged enemy once toward your location. It loses aloof during this movement."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1. If your location is flooded, reveal an additional chaos token.\n\n[cultist]: -2. If you fail, after this test ends, increase the flood level of your location.\n\n[tablet]: -3. If you fail this test and your location is flooded, take 1 damage.\n\n[elder_thing]: -4. If you fail, move the nearest ready unengaged enemy once toward your location. It loses aloof during this movement."
|
||||
end
|
||||
end
|
||||
--lair of dagon
|
||||
if scenario.getDescription() == "The Lair of Dagon" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 for each key on this card.\n\n[cultist]: -2. Reveal an additional chaos token. If you reveal 1 or more [curse] tokens during this test, you automatically fail.\n\n[tablet]: -3. Place each key you control on your location and take 1 damage.\n\n[elder_thing]: -4. Add 2 [curse] tokens to the chaos bag."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 for each key on this card.\n\n[cultist]: 0. Reveal an additional chaos token. If you reveal 1 or more [curse] tokens during this test, you automatically fail.\n\n[tablet]: -3. If you fail, place each key you control on your location.\n\n[elder_thing]: -4. If you fail, add 1 [curse] token to the chaos bag."
|
||||
end
|
||||
end
|
||||
--into the maelstrom
|
||||
if scenario.getDescription() == "Into the Maelstrom" then
|
||||
if scenario.is_face_down == true then
|
||||
tool = "Hard / Expert\n\n[skull]: -2 (-4 instead if there are 4 or more unflooded [[Y'ha-nthlei]] locations in play).\n\n[cultist]: -4. If you fail, place 1 doom on the current agenda (this may cause the current agenda to advance).\n\n[tablet]: -5. If you fail, you must either increase the flood level of your location or take 1 damage.\n\n[elder_thing]: -6. If you fail and there is a key on your location, take 1 horror."
|
||||
else
|
||||
tool = "Easy / Standard\n\n[skull]: -1 (-3 instead if there are 4 or more unflooded [[Y'ha-nthlei]] locations in play).\n\n[cultist]: -3. If you fail, place 1 doom on the current agenda (this may cause the current agenda to advance).\n\n[tablet]: -4. If you fail, you must either increase the flood level of your location or take 1 damage.\n\n[elder_thing]: -5. If you fail and there is a key on your location, take 1 horror."
|
||||
end
|
||||
end
|
||||
end
|
||||
getObjectFromGUID("8b081b").editButton({index = 6, tooltip = tool})
|
||||
getObjectFromGUID("bd0ff4").editButton({index = 6, tooltip = tool})
|
||||
getObjectFromGUID("383d8b").editButton({index = 6, tooltip = tool})
|
||||
getObjectFromGUID("0840d5").editButton({index = 6, tooltip = tool})
|
||||
end
|
@ -22,7 +22,7 @@
|
||||
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/965354846165100486/3DC8FCEF364B30758B09EF96AF9458F2B8E64D56/",
|
||||
"WidthScale": 0
|
||||
},
|
||||
"Description": "click to set chaos token difficulty",
|
||||
"Description": "Define difficulties in this objects script.",
|
||||
"DragSelectable": true,
|
||||
"GMNotes": "",
|
||||
"GUID": "8112ff",
|
||||
@ -34,7 +34,7 @@
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": false,
|
||||
"LuaScriptState": "",
|
||||
"LuaScript_path": "Fan-MadeAccessories.aa8b38/WhimsicalsGenericDifficultySelector.05efb4/GenericDifficultySelector.8112ff.ttslua",
|
||||
"LuaScript_path": "Fan-MadeAccessories.aa8b38/GenericDifficultySelector.8112ff.ttslua",
|
||||
"MeasureMovement": false,
|
||||
"Name": "Custom_Tile",
|
||||
"Nickname": "Generic Difficulty Selector",
|
||||
@ -54,4 +54,4 @@
|
||||
},
|
||||
"Value": 0,
|
||||
"XmlUI": ""
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
-- edit the "tokenData" table to change the preset difficulties
|
||||
-- list of valid ids: 'p1', '0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm7', 'm8',
|
||||
-- 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue', 'bless', 'curse', 'frost'
|
||||
|
||||
local tokenData = {
|
||||
Easy = { 'p1', 'p1', '0', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'skull', 'skull', 'cultist', 'red', 'blue' },
|
||||
Standard = { 'p1', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'm3', 'm4', 'skull', 'skull', 'cultist', 'red', 'blue' },
|
||||
Hard = { '0', '0', '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm5', 'skull', 'skull', 'cultist', 'red', 'blue' },
|
||||
Expert = { '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm4', 'm5', 'm6', 'm8', 'skull', 'skull', 'cultist', 'red', 'blue' }
|
||||
}
|
||||
|
||||
-- create buttons on startup
|
||||
function onLoad()
|
||||
local z_offset = -0.15
|
||||
for difficulty, _ in pairs(tokenData) do
|
||||
local clickFunction = difficulty:lower() .. "Click"
|
||||
self.setVar(clickFunction, function() clickFun(difficulty) end)
|
||||
|
||||
self.createButton({
|
||||
label = difficulty,
|
||||
function_owner = self,
|
||||
click_function = clickFunction,
|
||||
position = { 0, 0.1, z_offset },
|
||||
rotation = { 0, 0, 0 },
|
||||
scale = { 0.47, 1, 0.47 },
|
||||
height = 200,
|
||||
width = 1150,
|
||||
font_size = 100,
|
||||
color = { 0.87, 0.8, 0.70 },
|
||||
font_color = { 0, 0, 0 }
|
||||
})
|
||||
z_offset = z_offset + 0.20
|
||||
end
|
||||
end
|
||||
|
||||
function clickFun(difficulty)
|
||||
Global.call("setChaosBagState", tokenData[difficulty])
|
||||
end
|
@ -1,57 +0,0 @@
|
||||
{
|
||||
"AltLookAngle": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"Autoraise": true,
|
||||
"Bag": {
|
||||
"Order": 0
|
||||
},
|
||||
"ColorDiffuse": {
|
||||
"b": 0,
|
||||
"g": 0.36652,
|
||||
"r": 0.70588
|
||||
},
|
||||
"ContainedObjects_order": [
|
||||
"GenericDifficultySelector.8112ff",
|
||||
"TokenImageProvider.162580",
|
||||
"TokenList.297f5e",
|
||||
"GenericDifficultySelectorInstructions13.c32992"
|
||||
],
|
||||
"ContainedObjects_path": "WhimsicalsGenericDifficultySelector.05efb4",
|
||||
"Description": "",
|
||||
"DragSelectable": true,
|
||||
"GMNotes": "",
|
||||
"GUID": "05efb4",
|
||||
"Grid": true,
|
||||
"GridProjection": false,
|
||||
"Hands": false,
|
||||
"HideWhenFaceDown": false,
|
||||
"IgnoreFoW": false,
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": false,
|
||||
"LuaScript": "",
|
||||
"LuaScriptState": "",
|
||||
"MaterialIndex": -1,
|
||||
"MeasureMovement": false,
|
||||
"MeshIndex": -1,
|
||||
"Name": "Bag",
|
||||
"Nickname": "Whimsical's Generic Difficulty Selector",
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": 29.073,
|
||||
"posY": 3.901,
|
||||
"posZ": -21.285,
|
||||
"rotX": 0,
|
||||
"rotY": 0,
|
||||
"rotZ": 0,
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"scaleZ": 1
|
||||
},
|
||||
"Value": 0,
|
||||
"XmlUI": ""
|
||||
}
|
@ -1,169 +0,0 @@
|
||||
---
|
||||
--- Generated by EmmyLua(https://github.com/EmmyLua)
|
||||
--- Created by Whimsical.
|
||||
--- DateTime: 2021-08-05 6:14 p.m.
|
||||
---
|
||||
|
||||
|
||||
local tags = {
|
||||
bag = "chaosBag",
|
||||
provider = "token_list_provider",
|
||||
tokens = "token_image_provider"
|
||||
}
|
||||
|
||||
---@class ChaosToken
|
||||
---@field name string
|
||||
---@field image string
|
||||
local _ = {}
|
||||
|
||||
---@type table<string|number, ChaosToken>
|
||||
local sources
|
||||
|
||||
---@type table<string, any[]>
|
||||
local tokens
|
||||
|
||||
---@param source TTSObject
|
||||
local LoadSource = function (source)
|
||||
tokens = source:getTable("chaos_tokens")
|
||||
end
|
||||
|
||||
---@param token ChaosToken
|
||||
---@param position Vector
|
||||
---@param chaosBag TTSObject
|
||||
---@return number
|
||||
local SpawnToken = function(token, position, chaosBag)
|
||||
spawnObject {
|
||||
type = "Custom_Tile",
|
||||
position = position,
|
||||
scale = { 0.81, 1.0, 0.81 },
|
||||
rotation = { 0, 270, 0 },
|
||||
---@param object TTSObject
|
||||
callback_function = function(object, _, _)
|
||||
object:setName(token.name)
|
||||
chaosBag:putObject(object)
|
||||
end
|
||||
}:setCustomObject {
|
||||
image = token.image,
|
||||
type = 2,
|
||||
thickness = 0.1
|
||||
}
|
||||
end
|
||||
|
||||
---@param chaosBag TTSObject
|
||||
local emptyBag = function(chaosBag)
|
||||
local object = chaosBag:getObjects()
|
||||
local pos = self:getPosition()
|
||||
pos.y = pos.y+1
|
||||
|
||||
for _, object in ipairs(object) do
|
||||
chaosBag:takeObject {
|
||||
guid = object.guid,
|
||||
position = pos,
|
||||
---@param item TTSObject
|
||||
callback_function = function (item) item:destruct() end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
---@param difficulty string
|
||||
local clickFun= function (difficulty)
|
||||
local chaosBag = getObjectsWithTag(tags.bag)[1]
|
||||
|
||||
emptyBag(chaosBag)
|
||||
|
||||
local loading = tokens[difficulty]
|
||||
local pos = self:getPosition()
|
||||
|
||||
for _, token_id in ipairs(loading) do
|
||||
if type(token_id)=="string" then token_id = token_id:lower() end
|
||||
|
||||
local token = sources[token_id]
|
||||
|
||||
if (token==nil) then
|
||||
error("Could not find token \"" .. token_id .. "\".")
|
||||
return
|
||||
end
|
||||
|
||||
SpawnToken(token, pos, chaosBag)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---@param difficulty string
|
||||
local MakeClickFun = function(difficulty)
|
||||
return function ()
|
||||
clickFun(difficulty)
|
||||
end
|
||||
end
|
||||
|
||||
---@param label string
|
||||
---@param z_offset number|nil
|
||||
local makeButton = function(label , z_offset)
|
||||
z_offset = z_offset or -0.15
|
||||
|
||||
_G[label:lower() .. "Click"] = MakeClickFun(label)
|
||||
|
||||
self:createButton({
|
||||
label = label,
|
||||
function_owner = self,
|
||||
click_function = label:lower() .. "Click",
|
||||
position = {0, 0.1, z_offset},
|
||||
rotation = {0, 0, 0},
|
||||
scale = {0.47, 1, 0.47},
|
||||
height = 200,
|
||||
width = 1150,
|
||||
font_size = 100,
|
||||
color = {0.87, 0.8, 0.70},
|
||||
font_color = {0, 0, 0}
|
||||
})
|
||||
return z_offset + 0.20
|
||||
end
|
||||
|
||||
---@param source TTSObject
|
||||
local CreateButtons= function(source)
|
||||
self:clearButtons()
|
||||
|
||||
local z_offset
|
||||
for difficulty,_ in pairs(tokens) do
|
||||
z_offset = makeButton(difficulty, z_offset)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function LoadTokens()
|
||||
---@type TTSObject[]
|
||||
local image_sources = getObjectsWithTag(tags.tokens)
|
||||
|
||||
if (#image_sources<=0) then
|
||||
error("Cannot find images_sources")
|
||||
return
|
||||
end
|
||||
|
||||
sources = image_sources[1]:getTable("sources")
|
||||
|
||||
if (tokens~=nil) then CreateButtons() return end
|
||||
|
||||
local source = getObjectsWithTag(tags.provider)
|
||||
|
||||
if (#source<=0) then return end
|
||||
|
||||
LoadSource(source[1])
|
||||
|
||||
CreateButtons()
|
||||
end
|
||||
|
||||
function onload()
|
||||
Timer.create {
|
||||
identifier = self:getGUID(),
|
||||
function_name = "LoadTokens"
|
||||
}
|
||||
end
|
||||
|
||||
---@param provider TTSObject
|
||||
function onObjectSpawn(provider)
|
||||
if (not provider:hasTag(tags.provider)) then return end
|
||||
|
||||
LoadSource(provider)
|
||||
|
||||
CreateButtons()
|
||||
end
|
@ -1,137 +0,0 @@
|
||||
{
|
||||
"AltLookAngle": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"Autoraise": true,
|
||||
"ColorDiffuse": {
|
||||
"b": 1,
|
||||
"g": 1,
|
||||
"r": 1
|
||||
},
|
||||
"Description": "Tool for create custom chaos bag configurations.\n - The actual difficulty selector: click a difficulty to fill the chaos bag.\n- Token Image Provider: edit in scripting editor to add new token types. Cut and Paste to save.\n- Token List: edit in scripting editor to customize difficulties. Cut and Paste to save.\n\nReference of Token codes on following pages:",
|
||||
"DragSelectable": true,
|
||||
"GMNotes": "",
|
||||
"GUID": "c32992",
|
||||
"Grid": true,
|
||||
"GridProjection": false,
|
||||
"Hands": false,
|
||||
"HideWhenFaceDown": false,
|
||||
"IgnoreFoW": false,
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": false,
|
||||
"LuaScript": "",
|
||||
"LuaScriptState": "",
|
||||
"MeasureMovement": false,
|
||||
"Name": "Notecard",
|
||||
"Nickname": "Generic Difficulty Selector Instructions 1/3",
|
||||
"Snap": true,
|
||||
"States": {
|
||||
"2": {
|
||||
"AltLookAngle": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"Autoraise": true,
|
||||
"ColorDiffuse": {
|
||||
"b": 1,
|
||||
"g": 1,
|
||||
"r": 1
|
||||
},
|
||||
"Description": "1 — -8: Numeric tokens (Don't place quotes around these).\r\n\"S\": Skull.\r\n\"C\": Cultist.\r\n\"T\": Tablet.\r\n\"E\": Elder Thing.\r\n\"Fr\": Frost.",
|
||||
"DragSelectable": true,
|
||||
"GMNotes": "",
|
||||
"GUID": "eab766",
|
||||
"Grid": true,
|
||||
"GridProjection": false,
|
||||
"Hands": false,
|
||||
"HideWhenFaceDown": false,
|
||||
"IgnoreFoW": false,
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": false,
|
||||
"LuaScript": "",
|
||||
"LuaScriptState": "",
|
||||
"MeasureMovement": false,
|
||||
"Name": "Notecard",
|
||||
"Nickname": "Generic Difficulty Selector Instructions 2/3",
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": 3.29240441,
|
||||
"posY": 1.33262193,
|
||||
"posZ": 56.0586357,
|
||||
"rotX": 359.9792,
|
||||
"rotY": 89.99884,
|
||||
"rotZ": 359.983215,
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"scaleZ": 1
|
||||
},
|
||||
"Value": 0,
|
||||
"XmlUI": ""
|
||||
},
|
||||
"3": {
|
||||
"AltLookAngle": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"Autoraise": true,
|
||||
"ColorDiffuse": {
|
||||
"b": 1,
|
||||
"g": 1,
|
||||
"r": 1
|
||||
},
|
||||
"Description": "\"*\": Elder Sign.\r\n\"F\": Auto-fail.\r\n\"+\": Bless.\r\n\"-\": Curse.",
|
||||
"DragSelectable": true,
|
||||
"GMNotes": "",
|
||||
"GUID": "309295",
|
||||
"Grid": true,
|
||||
"GridProjection": false,
|
||||
"Hands": false,
|
||||
"HideWhenFaceDown": false,
|
||||
"IgnoreFoW": false,
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": false,
|
||||
"LuaScript": "",
|
||||
"LuaScriptState": "",
|
||||
"MeasureMovement": false,
|
||||
"Name": "Notecard",
|
||||
"Nickname": "Generic Difficulty Selector Instructions 3/3",
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": 3.29240441,
|
||||
"posY": 1.33262193,
|
||||
"posZ": 56.0586357,
|
||||
"rotX": 359.9792,
|
||||
"rotY": 89.9988556,
|
||||
"rotZ": 359.983215,
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"scaleZ": 1
|
||||
},
|
||||
"Value": 0,
|
||||
"XmlUI": ""
|
||||
}
|
||||
},
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": 13.505,
|
||||
"posY": 3.625,
|
||||
"posZ": 30.273,
|
||||
"rotX": 0,
|
||||
"rotY": 90,
|
||||
"rotZ": 0,
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"scaleZ": 1
|
||||
},
|
||||
"Value": 0,
|
||||
"XmlUI": ""
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
{
|
||||
"AltLookAngle": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"Autoraise": true,
|
||||
"ColorDiffuse": {
|
||||
"b": 1,
|
||||
"g": 1,
|
||||
"r": 1
|
||||
},
|
||||
"Description": "",
|
||||
"DragSelectable": true,
|
||||
"GMNotes": "",
|
||||
"GUID": "162580",
|
||||
"Grid": true,
|
||||
"GridProjection": false,
|
||||
"Hands": false,
|
||||
"HideWhenFaceDown": false,
|
||||
"IgnoreFoW": false,
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": false,
|
||||
"LuaScriptState": "",
|
||||
"LuaScript_path": "Fan-MadeAccessories.aa8b38/WhimsicalsGenericDifficultySelector.05efb4/TokenImageProvider.162580.ttslua",
|
||||
"MeasureMovement": false,
|
||||
"Name": "Checker_white",
|
||||
"Nickname": "Token Image Provider",
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tags": [
|
||||
"token_image_provider"
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": 13.194,
|
||||
"posY": 3.807,
|
||||
"posZ": 28.835,
|
||||
"rotX": 0,
|
||||
"rotY": 270,
|
||||
"rotZ": 180,
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"scaleZ": 1
|
||||
},
|
||||
"Value": 0,
|
||||
"XmlUI": ""
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
---
|
||||
--- Generated by EmmyLua(https://github.com/EmmyLua)
|
||||
--- Created by Whimsical.
|
||||
--- DateTime: 2021-08-05 6:51 p.m.
|
||||
---
|
||||
|
||||
---@param name string
|
||||
---@param image string
|
||||
---@return ChaosToken
|
||||
local MakeToken = function (name, image)
|
||||
return {
|
||||
name = name,
|
||||
image = image
|
||||
}
|
||||
end
|
||||
|
||||
sources = {
|
||||
[1] = MakeToken("+1", "https://i.imgur.com/uIx8jbY.png"),
|
||||
[0] = MakeToken("0", "https://i.imgur.com/btEtVfd.png"),
|
||||
[-1] = MakeToken("-1", "https://i.imgur.com/w3XbrCC.png"),
|
||||
[-2] = MakeToken("-2", "https://i.imgur.com/bfTg2hb.png"),
|
||||
[-3] = MakeToken("-3", "https://i.imgur.com/yfs8gHq.png"),
|
||||
[-4] = MakeToken("-4", "https://i.imgur.com/qrgGQRD.png"),
|
||||
[-5] = MakeToken("-5", "https://i.imgur.com/3Ym1IeG.png"),
|
||||
[-6] = MakeToken("-6", "https://i.imgur.com/c9qdSzS.png"),
|
||||
[-7] = MakeToken("-7", "https://i.imgur.com/4WRD42n.png"),
|
||||
[-8] = MakeToken("-8", "https://i.imgur.com/9t3rPTQ.png"),
|
||||
["s"] = MakeToken("Skull", "https://i.imgur.com/stbBxtx.png"),
|
||||
["c"] = MakeToken("Cultist", "https://i.imgur.com/VzhJJaH.png"),
|
||||
["t"] = MakeToken("Tablet", "https://i.imgur.com/1plY463.png"),
|
||||
["e"] = MakeToken("Elder Thing", "https://i.imgur.com/ttnspKt.png"),
|
||||
["*"] = MakeToken("Elder Sign", "https://i.imgur.com/nEmqjmj.png"),
|
||||
["f"] = MakeToken("Auto-fail", "https://i.imgur.com/lns4fhz.png"),
|
||||
["+"] = MakeToken("Bless", "http://cloud-3.steamusercontent.com/ugc/1655601092778627699/339FB716CB25CA6025C338F13AFDFD9AC6FA8356/"),
|
||||
["-"] = MakeToken("Curse", "http://cloud-3.steamusercontent.com/ugc/1655601092778636039/2A25BD38E8C44701D80DD96BF0121DA21843672E/"),
|
||||
["fr"] = MakeToken("Frost", "http://cloud-3.steamusercontent.com/ugc/1858293462583104677/195F93C063A8881B805CE2FD4767A9718B27B6AE/"),
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
{
|
||||
"AltLookAngle": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"Autoraise": true,
|
||||
"ColorDiffuse": {
|
||||
"b": 0,
|
||||
"g": 0,
|
||||
"r": 0
|
||||
},
|
||||
"Description": "",
|
||||
"DragSelectable": true,
|
||||
"GMNotes": "",
|
||||
"GUID": "297f5e",
|
||||
"Grid": true,
|
||||
"GridProjection": false,
|
||||
"Hands": false,
|
||||
"HideWhenFaceDown": false,
|
||||
"IgnoreFoW": false,
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": false,
|
||||
"LuaScriptState": "",
|
||||
"LuaScript_path": "Fan-MadeAccessories.aa8b38/WhimsicalsGenericDifficultySelector.05efb4/TokenList.297f5e.ttslua",
|
||||
"MeasureMovement": false,
|
||||
"Name": "Checker_black",
|
||||
"Nickname": "Token List",
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tags": [
|
||||
"mlc_memory_object",
|
||||
"token_list_provider"
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": 12.984,
|
||||
"posY": 4.045,
|
||||
"posZ": 29.828,
|
||||
"rotX": 0,
|
||||
"rotY": 270,
|
||||
"rotZ": 206,
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"scaleZ": 1
|
||||
},
|
||||
"Value": 0,
|
||||
"XmlUI": ""
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
---
|
||||
--- Generated by EmmyLua(https://github.com/EmmyLua)
|
||||
--- Created by Whimsical.
|
||||
--- DateTime: 2021-08-05 7:19 p.m.
|
||||
---
|
||||
|
||||
chaos_tokens = {
|
||||
Easy = {1, 1, 0, 0, -1, -1, -1, -2, -2, "S", "S", "C", "T", "F", "*"},
|
||||
Standard = {1, 0, 0, -1, -1, -1, -2, -2, -3, -4, "S", "S", "C", "T", "F", "*"},
|
||||
Hard = {0, 0, -1, -1, -2, -2, -3, -4, -4, -5, "Fr", "Fr", "S", "S", "C", "T", "F", "*"},
|
||||
Expert = {0, -1, -2, -2, -3, -4, -4, -5, -7, "Fr", "Fr", "Fr", "S", "S", "C", "T", "F", "*"}
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
-- specific setup (different for each playmat)
|
||||
---------------------------------------------------------
|
||||
|
||||
PLAYER_COLOR = "White"
|
||||
PLAY_ZONE_POSITION = { x = -54.5, y = 4, z = 19 }
|
||||
PLAY_ZONE_SCALE = { x = 32, y = 5, z = 12 }
|
||||
TRASHCAN_GUID = "147e80"
|
||||
|
@ -2,7 +2,6 @@
|
||||
-- specific setup (different for each playmat)
|
||||
---------------------------------------------------------
|
||||
|
||||
PLAYER_COLOR = "Orange"
|
||||
PLAY_ZONE_POSITION = { x = -54.5, y = 4, z = -19 }
|
||||
PLAY_ZONE_SCALE = { x = 32, y = 5, z = 12 }
|
||||
TRASHCAN_GUID = "f7b6c8"
|
||||
|
@ -2,7 +2,6 @@
|
||||
-- specific setup (different for each playmat)
|
||||
---------------------------------------------------------
|
||||
|
||||
PLAYER_COLOR = "Green"
|
||||
PLAY_ZONE_POSITION = { x = -26.5, y = 4, z = 26.5 }
|
||||
PLAY_ZONE_SCALE = { x = 32, y = 5, z = 12 }
|
||||
TRASHCAN_GUID = "5f896a"
|
||||
|
@ -2,7 +2,6 @@
|
||||
-- specific setup (different for each playmat)
|
||||
---------------------------------------------------------
|
||||
|
||||
PLAYER_COLOR = "Red"
|
||||
PLAY_ZONE_POSITION = { x = -26.5, y = 4, z = -26.5 }
|
||||
PLAY_ZONE_SCALE = { x = 32, y = 5, z = 12 }
|
||||
TRASHCAN_GUID = "4b8594"
|
||||
|
@ -1,30 +1,10 @@
|
||||
local TOKEN_URL = {
|
||||
ElderSign = "https://i.imgur.com/nEmqjmj.png",
|
||||
plusOne = "https://i.imgur.com/uIx8jbY.png",
|
||||
Zero = "https://i.imgur.com/btEtVfd.png",
|
||||
minusOne = "https://i.imgur.com/w3XbrCC.png",
|
||||
minusTwo = "https://i.imgur.com/bfTg2hb.png",
|
||||
minusThree = "https://i.imgur.com/yfs8gHq.png",
|
||||
minusFour = "https://i.imgur.com/qrgGQRD.png",
|
||||
minusFive = "https://i.imgur.com/3Ym1IeG.png",
|
||||
minusSix = "https://i.imgur.com/c9qdSzS.png",
|
||||
minusSeven = "https://i.imgur.com/4WRD42n.png",
|
||||
minusEight = "https://i.imgur.com/9t3rPTQ.png",
|
||||
Skull = "https://i.imgur.com/stbBxtx.png",
|
||||
Cultist = "https://i.imgur.com/VzhJJaH.png",
|
||||
Tablet = "https://i.imgur.com/1plY463.png",
|
||||
ElderThing = "https://i.imgur.com/ttnspKt.png",
|
||||
AutoFail = "https://i.imgur.com/lns4fhz.png",
|
||||
Frost = "http://cloud-3.steamusercontent.com/ugc/1858293462583104677/195F93C063A8881B805CE2FD4767A9718B27B6AE/"
|
||||
}
|
||||
|
||||
local TOKEN_NAMES = {
|
||||
local TOKEN_IDS = {
|
||||
-- first row
|
||||
"plusOne", "Zero", "minusOne", "minusTwo", "minusThree", "minusFour",
|
||||
"p1", "0", "m1", "m2", "m3", "m4",
|
||||
-- second row
|
||||
"minusFive", "minusSix", "minusSeven", "minusEight", "Frost",
|
||||
"m5", "m6", "m7", "m8", "frost",
|
||||
-- third row
|
||||
"ElderSign", "Skull", "Cultist", "Tablet", "ElderThing", "AutoFail"
|
||||
"blue", "skull", "cultist", "tablet", "elder", "red"
|
||||
}
|
||||
|
||||
local BUTTON_TOOLTIP = {
|
||||
@ -52,9 +32,6 @@ buttonParameters.color = { 0, 0, 0, 0 }
|
||||
buttonParameters.width = 300
|
||||
buttonParameters.height = 300
|
||||
|
||||
local UPDATING = false
|
||||
local tokenArranger
|
||||
|
||||
local name
|
||||
local tokens = {}
|
||||
|
||||
@ -76,108 +53,30 @@ function onLoad()
|
||||
|
||||
self.createButton(buttonParameters)
|
||||
end
|
||||
|
||||
self.addContextMenuItem("More Information", function()
|
||||
printToAll("------------------------------", "White")
|
||||
printToAll("Chaos Bag Manager by Chr1Z", "Orange")
|
||||
end)
|
||||
|
||||
tokenArranger = getObjectFromGUID("022907")
|
||||
end
|
||||
|
||||
-- get chaos bag from scripting zone and description
|
||||
function getChaosBag()
|
||||
local chaosbag = nil
|
||||
local chaosbag_zone = getObjectFromGUID("83ef06")
|
||||
|
||||
-- error handling: scripting zone not found
|
||||
if chaosbag_zone == nil then
|
||||
printToAll("Zone for chaos bag detection couldn't be found.", "Red")
|
||||
return nil
|
||||
end
|
||||
|
||||
for _, v in ipairs(chaosbag_zone.getObjects()) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- error handling: chaos bag not found
|
||||
if chaosbag == nil then
|
||||
printToAll("Chaos bag couldn't be found.", "Red")
|
||||
end
|
||||
return chaosbag
|
||||
end
|
||||
|
||||
-- click function for buttons
|
||||
function buttonClick(index, isRightClick)
|
||||
chaosbag = getChaosBag()
|
||||
local tokenId = TOKEN_IDS[index]
|
||||
|
||||
-- error handling: chaos bag not found
|
||||
if chaosbag == nil then return end
|
||||
|
||||
name = BUTTON_TOOLTIP[index]
|
||||
tokens = {}
|
||||
for _, v in ipairs(chaosbag.getObjects()) do
|
||||
if v.name == name then table.insert(tokens, v.guid) end
|
||||
end
|
||||
|
||||
token = TOKEN_NAMES[index]
|
||||
if isRightClick then
|
||||
-- error handling: no matching token found
|
||||
if #tokens == 0 then
|
||||
printToAll("No " .. name .. " tokens in the chaos bag.", "Yellow")
|
||||
return
|
||||
Global.call("removeChaosToken", tokenId)
|
||||
else
|
||||
local tokens = {}
|
||||
local name = BUTTON_TOOLTIP[index]
|
||||
local chaosbag = Global.call("findChaosBag")
|
||||
|
||||
for _, v in ipairs(chaosbag.getObjects()) do
|
||||
if v.name == name then table.insert(tokens, v.guid) end
|
||||
end
|
||||
|
||||
-- remove token
|
||||
chaosbag.takeObject({
|
||||
guid = tokens[1],
|
||||
position = self.getPosition(),
|
||||
smooth = false,
|
||||
callback_function = removeCallback
|
||||
})
|
||||
else
|
||||
-- spawn token (only 8 frost tokens allowed)
|
||||
if token == "Frost" and #tokens == 8 then
|
||||
if tokenId == "frost" and #tokens == 8 then
|
||||
printToAll("The maximum of 8 Frost tokens is already in the bag.", "Yellow")
|
||||
return
|
||||
end
|
||||
|
||||
local obj = spawnObject({
|
||||
type = 'Custom_Tile',
|
||||
position = chaosbag.getPosition() + Vector(0, 1, 0),
|
||||
rotation = { x = 0, y = 260, z = 0 },
|
||||
callback_function = spawnCallback
|
||||
})
|
||||
obj.setCustomObject({
|
||||
type = 2,
|
||||
image = TOKEN_URL[token],
|
||||
thickness = 0.1
|
||||
})
|
||||
end
|
||||
|
||||
updateTokenArranger()
|
||||
end
|
||||
|
||||
function removeCallback(obj)
|
||||
printToAll("Removing " .. name .. " token (in bag: " .. #tokens - 1 .. ")", "White")
|
||||
obj.destruct()
|
||||
end
|
||||
|
||||
function spawnCallback(obj)
|
||||
obj.scale { 0.81, 1, 0.81 }
|
||||
obj.setName(name)
|
||||
printToAll("Adding " .. name .. " token (in bag: " .. #tokens + 1 .. ")", "White")
|
||||
end
|
||||
|
||||
function updateTokenArranger()
|
||||
if tokenArranger and not UPDATING then
|
||||
UPDATING = true
|
||||
Wait.time(function()
|
||||
UPDATING = false
|
||||
tokenArranger.call("layout")
|
||||
end, 1.5)
|
||||
Global.call("spawnChaosToken", tokenId)
|
||||
printToAll("Adding " .. name .. " token (in bag: " .. #tokens + 1 .. ")", "White")
|
||||
end
|
||||
end
|
||||
|
@ -2,13 +2,10 @@
|
||||
Cleans up the table for the next scenario in a campaign:
|
||||
- sets counters to default values (resources and doom) or trauma values (health and sanity, if not disabled) from campaign log
|
||||
- puts everything on playmats and hands into respective trashcans
|
||||
- use the IGNORE_TAG to exclude objects from tidying (default: "CleanUpHelper_Ignore")
|
||||
--]]
|
||||
- use the IGNORE_TAG to exclude objects from tidying (default: "CleanUpHelper_Ignore")]]
|
||||
|
||||
local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi")
|
||||
|
||||
-- enable this for debugging
|
||||
local SHOW_RAYS = false
|
||||
local playmatApi = require("playermat/PlaymatApi")
|
||||
|
||||
-- these objects will be ignored
|
||||
local IGNORE_GUIDS = {
|
||||
@ -81,9 +78,7 @@ buttonParameters.function_owner = self
|
||||
---------------------------------------------------------
|
||||
|
||||
function onSave()
|
||||
return JSON.encode({
|
||||
options = options
|
||||
})
|
||||
return JSON.encode({ options = options })
|
||||
end
|
||||
|
||||
function onLoad(savedData)
|
||||
@ -213,7 +208,7 @@ function resetSkillTrackers()
|
||||
if obj ~= nil then
|
||||
obj.call("updateStats", { 1, 1, 1, 1 })
|
||||
else
|
||||
printToAll("Skill tracker number " .. i .. " could not be found.", "Yellow")
|
||||
printToAll("Skill tracker for " .. COLORS[i] .. " playmat could not be found.", "Yellow")
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -296,7 +291,7 @@ function discardHands()
|
||||
for i = 1, 4 do
|
||||
local trashcan = getObjectFromGUID(TRASHCAN_GUIDS[i])
|
||||
if trashcan == nil then return end
|
||||
local hand = Player[COLORS[i]].getHandObjects()
|
||||
local hand = Player[playmatApi.getPlayerColor(COLORS[i])].getHandObjects()
|
||||
for j = #hand, 1, -1 do
|
||||
trashcan.putObject(hand[j])
|
||||
end
|
||||
@ -339,7 +334,7 @@ function tidyPlayerMatCoroutine()
|
||||
local trashcan = getObjectFromGUID(TRASHCAN_GUIDS[i])
|
||||
if trashcan == nil then
|
||||
printToAll("Trashcan for " .. COLORS[i] .. " playmat could not be found!", "Red")
|
||||
return
|
||||
return 1
|
||||
end
|
||||
|
||||
for _, entry in ipairs(findObjects(i)) do
|
||||
@ -390,7 +385,7 @@ function findObjects(num)
|
||||
size = PHYSICS_SCALE[num],
|
||||
origin = PHYSICS_POSITION[num],
|
||||
orientation = { 0, PHYSICS_ROTATION[num], 0 },
|
||||
debug = SHOW_RAYS
|
||||
debug = false
|
||||
})
|
||||
end
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
local playmatAPI = require("playermat/PlaymatApi")
|
||||
local playmatApi = require("playermat/PlaymatApi")
|
||||
|
||||
-- forward declaration of variables that are used across functions
|
||||
local matColor, handColor, loopId, hovering
|
||||
|
||||
function onLoad()
|
||||
@ -62,8 +64,8 @@ end
|
||||
|
||||
-- updates the matcolor and handcolor variable
|
||||
function updateColors()
|
||||
matColor = playmatAPI.getMatColorByPosition(self.getPosition())
|
||||
handColor = playmatAPI.getHandColor(matColor)
|
||||
matColor = playmatApi.getMatColorByPosition(self.getPosition())
|
||||
handColor = playmatApi.getPlayerColor(matColor)
|
||||
self.setName(handColor .. " Hand Helper")
|
||||
end
|
||||
|
||||
@ -78,7 +80,7 @@ function updateValue(toggle)
|
||||
if Player[handColor].getHandCount() == 0 then return end
|
||||
|
||||
-- get state of "Dream-Enhancing Serum" from playermat and update button label
|
||||
local des = playmatAPI.isDES(matColor)
|
||||
local des = playmatApi.isDES(matColor)
|
||||
if toggle then des = not des end
|
||||
self.editButton({ index = 1, label = "DES: " .. (des and "✓" or "✗") })
|
||||
|
||||
@ -110,5 +112,5 @@ end
|
||||
|
||||
-- discards a random non-hidden card from hand
|
||||
function discardRandom()
|
||||
playmatAPI.doDiscardOne(matColor)
|
||||
playmatApi.doDiscardOne(matColor)
|
||||
end
|
||||
|
@ -1,10 +1,7 @@
|
||||
local playmatAPI = require("playermat/PlaymatApi")
|
||||
local playmatApi = require("playermat/PlaymatApi")
|
||||
|
||||
-- forward declaration of variables that are used across functions
|
||||
local matColor
|
||||
local setAsidePosition
|
||||
local setAsideRotation
|
||||
local drawDeckPosition
|
||||
local matColor, handColor, setAsidePosition, setAsideRotation, drawDeckPosition
|
||||
|
||||
local quickParameters = {}
|
||||
quickParameters.function_owner = self
|
||||
@ -102,10 +99,11 @@ end
|
||||
|
||||
-- start the search (change UI, set handCards aside, draw cards)
|
||||
function startSearch(messageColor, number)
|
||||
matColor = playmatAPI.getMatColorByPosition(self.getPosition())
|
||||
matColor = playmatApi.getMatColorByPosition(self.getPosition())
|
||||
handColor = playmatApi.getPlayerColor(matColor)
|
||||
|
||||
-- get draw deck
|
||||
local drawDeck = playmatAPI.getDrawDeck(matColor)
|
||||
local drawDeck = playmatApi.getDrawDeck(matColor)
|
||||
if drawDeck == nil then
|
||||
printToColor(matColor .. " draw deck could not be found!", messageColor, "Red")
|
||||
return
|
||||
@ -121,8 +119,8 @@ function startSearch(messageColor, number)
|
||||
end
|
||||
|
||||
-- get position and rotation for set aside cards
|
||||
local handData = Player[matColor].getHandTransform()
|
||||
local handCards = Player[matColor].getHandObjects()
|
||||
local handData = Player[handColor].getHandTransform()
|
||||
local handCards = Player[handColor].getHandObjects()
|
||||
setAsidePosition = handData.position + offset * handData.right
|
||||
setAsideRotation = { handData.rotation.x, handData.rotation.y + 180, 180 }
|
||||
|
||||
@ -136,18 +134,18 @@ function startSearch(messageColor, number)
|
||||
local object = v.hit_object
|
||||
if object.tag == "Card" and not object.is_face_down then
|
||||
object.flip()
|
||||
Wait.time(function() drawDeck = playmatAPI.getDrawDeck(matColor) end, 1)
|
||||
Wait.time(function() drawDeck = playmatApi.getDrawDeck(matColor) end, 1)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
Wait.time(function() drawDeck.deal(number, matColor) end, 1)
|
||||
Wait.time(function() drawDeck.deal(number, handColor) end, 1)
|
||||
searchView()
|
||||
end
|
||||
|
||||
-- place handCards back into deck and optionally shuffle
|
||||
function endSearch(_, _, isRightClick)
|
||||
local handCards = Player[matColor].getHandObjects()
|
||||
local handCards = Player[handColor].getHandObjects()
|
||||
|
||||
for i = #handCards, 1, -1 do
|
||||
handCards[i].setPosition(drawDeckPosition + Vector(0, 6 - i * 0.3, 0))
|
||||
@ -156,7 +154,7 @@ function endSearch(_, _, isRightClick)
|
||||
|
||||
if not isRightClick then
|
||||
Wait.time(function()
|
||||
local deck = playmatAPI.getDrawDeck(matColor)
|
||||
local deck = playmatApi.getDrawDeck(matColor)
|
||||
if deck ~= nil then
|
||||
deck.shuffle()
|
||||
end
|
||||
@ -168,11 +166,11 @@ function endSearch(_, _, isRightClick)
|
||||
local obj = v.hit_object
|
||||
if obj.tag == "Deck" then
|
||||
Wait.time(function()
|
||||
obj.deal(#obj.getObjects(), matColor)
|
||||
obj.deal(#obj.getObjects(), handColor)
|
||||
end, 1)
|
||||
break
|
||||
elseif obj.tag == "Card" then
|
||||
obj.setPosition(Player[matColor].getHandTransform().position)
|
||||
obj.setPosition(Player[handColor].getHandTransform().position)
|
||||
obj.flip()
|
||||
break
|
||||
end
|
||||
|
@ -4,7 +4,7 @@ local mythosAreaApi = require("core/MythosAreaApi")
|
||||
local buttonParameters = {}
|
||||
buttonParameters.function_owner = self
|
||||
buttonParameters.label = ""
|
||||
buttonParameters.tooltip = "Add / Remove"
|
||||
buttonParameters.tooltip = "Increase / Decrease"
|
||||
buttonParameters.color = { 0, 0, 0, 0 }
|
||||
buttonParameters.width = 325
|
||||
buttonParameters.height = 325
|
||||
@ -18,11 +18,14 @@ inputParameters.alignment = 3
|
||||
inputParameters.validation = 2
|
||||
inputParameters.tab = 2
|
||||
|
||||
local latestLoad = "XXX"
|
||||
local updating = false
|
||||
local percentage = false
|
||||
-- variables with save function
|
||||
local tokenPrecedence = {}
|
||||
local TOKEN_NAMES = {
|
||||
local latestLoad = "XXX"
|
||||
local percentage = false
|
||||
|
||||
-- variables without save function
|
||||
local updating = false
|
||||
local TOKEN_NAMES = {
|
||||
"Elder Sign",
|
||||
"Skull",
|
||||
"Cultist",
|
||||
@ -44,6 +47,7 @@ function onSave()
|
||||
})
|
||||
end
|
||||
|
||||
-- loading data, button creation and initial layouting
|
||||
function onLoad(saveState)
|
||||
if saveState ~= nil and saveState ~= "" then
|
||||
local loadedData = JSON.decode(saveState)
|
||||
@ -54,15 +58,18 @@ function onLoad(saveState)
|
||||
loadDefaultValues()
|
||||
end
|
||||
|
||||
createDefaultButtonsAndInputs(true)
|
||||
createButtonsAndInputs(true)
|
||||
layout()
|
||||
|
||||
-- reset context menu
|
||||
-- context menu items
|
||||
self.addContextMenuItem("Load default values", function()
|
||||
latestLoad = "XXX"
|
||||
loadDefaultValues()
|
||||
updateUI()
|
||||
layout()
|
||||
end)
|
||||
self.addContextMenuItem("Toggle Percentages", function()
|
||||
|
||||
self.addContextMenuItem("Toggle percentages", function()
|
||||
if percentage then
|
||||
percentage = false
|
||||
else
|
||||
@ -70,25 +77,26 @@ function onLoad(saveState)
|
||||
end
|
||||
layout()
|
||||
end)
|
||||
self.addContextMenuItem("Toggle Cumulative", function()
|
||||
if percentage == "basic" or not percentage then
|
||||
percentage = "cumulative"
|
||||
broadcastToAll("Cumulative percentages are unreliable when using tokens that draw other tokens (bless or curse for example)", Color.Yellow)
|
||||
else
|
||||
|
||||
self.addContextMenuItem("Toggle cumulative", function()
|
||||
if percentage == "cumulative" then
|
||||
percentage = "basic"
|
||||
else
|
||||
percentage = "cumulative"
|
||||
broadcastToAll("Cumulative percentages are unreliable when using tokens that draw other tokens (bless or curse for example).", Color.Yellow)
|
||||
end
|
||||
layout()
|
||||
end)
|
||||
layout()
|
||||
|
||||
-- grab token metadata from mythos area
|
||||
Wait.time(function() onTokenDataChanged(mythosAreaApi.returnTokenData()) end, 0.5)
|
||||
Wait.time(function() onTokenDataChanged(mythosAreaApi.returnTokenData()) end, 0.2)
|
||||
end
|
||||
|
||||
-- delete temporary tokens when destroyed
|
||||
function onDestroy() deleteCopiedTokens() end
|
||||
|
||||
-- layout tokens when dropped (after 2 seconds)
|
||||
function onDrop() Wait.time(layout, 2) end
|
||||
-- layout tokens when dropped (after 1.5 seconds)
|
||||
function onDrop() Wait.time(layout, 1.5) end
|
||||
|
||||
-- delete temporary tokens when picked up
|
||||
function onPickUp() deleteCopiedTokens() end
|
||||
@ -114,7 +122,10 @@ end
|
||||
function tokenClick(isRightClick, index)
|
||||
local change = tonumber(isRightClick and "-1" or "1")
|
||||
tokenPrecedence[TOKEN_NAMES[index]][1] = tokenPrecedence[TOKEN_NAMES[index]][1] + change
|
||||
self.editInput({ index = index - 1, value = tokenPrecedence[TOKEN_NAMES[index]][1] })
|
||||
self.editInput({
|
||||
index = index - 1,
|
||||
value = tokenPrecedence[TOKEN_NAMES[index]][1]
|
||||
})
|
||||
layout()
|
||||
end
|
||||
|
||||
@ -131,81 +142,73 @@ end
|
||||
|
||||
-- loads the default precedence table
|
||||
function loadDefaultValues()
|
||||
-- token modifiers for sorting (and order for same modifier)
|
||||
-- order starts at 2 because there is a "+1" token
|
||||
-- 1st value: token modifiers for sorting
|
||||
-- 2nd value: order for equivalent tokens (starts at 2 because of "+1" token)
|
||||
tokenPrecedence = {
|
||||
["Elder Sign"] = { 100, 2 },
|
||||
["Skull"] = { -1, 3 },
|
||||
["Cultist"] = { -2, 4 },
|
||||
["Tablet"] = { -3, 5 },
|
||||
["Elder Thing"] = { -4, 6 },
|
||||
["Auto-fail"] = { -100, 7 },
|
||||
["Bless"] = { 101, 8 },
|
||||
["Curse"] = { -101, 9 },
|
||||
["Frost"] = { -99, 10 },
|
||||
[""] = { 0, 11 }
|
||||
["Elder Sign"] = { 100, 2},
|
||||
["Skull"] = { -1, 3},
|
||||
["Cultist"] = { -2, 4},
|
||||
["Tablet"] = { -3, 5},
|
||||
["Elder Thing"] = { -4, 6},
|
||||
["Auto-fail"] = { -100, 7},
|
||||
["Bless"] = { 101, 8},
|
||||
["Curse"] = { -101, 9},
|
||||
["Frost"] = { -99, 10},
|
||||
[""] = { 0, 11}
|
||||
}
|
||||
end
|
||||
|
||||
-- creates all starting buttons and inputs
|
||||
function createDefaultButtonsAndInputs(loadInputs)
|
||||
loadInputs = loadInputs or false
|
||||
|
||||
buttonParameters.function_owner = self
|
||||
buttonParameters.label = ""
|
||||
buttonParameters.tooltip = "Increase / Decrease"
|
||||
buttonParameters.color = { 0, 0, 0, 0 }
|
||||
buttonParameters.width = 325
|
||||
buttonParameters.height = 325
|
||||
-- create UI
|
||||
-- creates buttons and inputs (if argument is true)
|
||||
function createButtonsAndInputs(loadInputs)
|
||||
local offset = 0.725
|
||||
local pos = { x = { -1.067, 0.377 }, z = -2.175 }
|
||||
local pos = { x = { -1.067, 0.377 }, z = -2.175 }
|
||||
|
||||
-- button and inputs index 0-9
|
||||
for i = 1, 10 do
|
||||
if i < 6 then
|
||||
buttonParameters.position = { pos.x[1], 0, pos.z + i * offset }
|
||||
if loadInputs then
|
||||
inputParameters.position = { pos.x[1] + offset, 0.1, pos.z + i * offset }
|
||||
end
|
||||
inputParameters.position = { pos.x[1] + offset, 0.1, pos.z + i * offset }
|
||||
else
|
||||
buttonParameters.position = { pos.x[2], 0, pos.z + (i - 5) * offset }
|
||||
if loadInputs then
|
||||
inputParameters.position = { pos.x[2] + offset, 0.1, pos.z + (i - 5) * offset }
|
||||
end
|
||||
inputParameters.position = { pos.x[2] + offset, 0.1, pos.z + (i - 5) * offset }
|
||||
end
|
||||
|
||||
buttonParameters.click_function = attachIndex("tokenClick", i)
|
||||
buttonParameters.click_function = attachIndex("tokenClick", i)
|
||||
self.createButton(buttonParameters)
|
||||
|
||||
-- only create inputs on initial load
|
||||
if loadInputs then
|
||||
inputParameters.input_function = attachIndex2("tokenInput", i)
|
||||
inputParameters.value = tokenPrecedence[TOKEN_NAMES[i]][1]
|
||||
inputParameters.input_function = attachIndex2("tokenInput", i)
|
||||
inputParameters.value = tokenPrecedence[TOKEN_NAMES[i]][1]
|
||||
self.createInput(inputParameters)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- index 10: "Update / Hide" button
|
||||
buttonParameters.label = "Update / Hide"
|
||||
buttonParameters.click_function = "layout"
|
||||
buttonParameters.tooltip = "Left-Click: Update!\nRight-Click: Hide Tokens!"
|
||||
buttonParameters.position = { 0.725, 0.1, 2.025 }
|
||||
buttonParameters.color = { 1, 1, 1 }
|
||||
buttonParameters.width = 675
|
||||
buttonParameters.height = 175
|
||||
self.createButton(buttonParameters)
|
||||
self.createButton({
|
||||
function_owner = self,
|
||||
label = "Update / Hide",
|
||||
click_function = "layout",
|
||||
tooltip = "Left-Click: Update!\nRight-Click: Hide Tokens!",
|
||||
position = { 0.725, 0.1, 2.025 },
|
||||
color = { 1, 1, 1 },
|
||||
width = 675,
|
||||
height = 175
|
||||
})
|
||||
end
|
||||
|
||||
-- update input fields
|
||||
function updateUI()
|
||||
for i = 1, 10 do
|
||||
self.editInput({ index = i - 1, value = tokenPrecedence[TOKEN_NAMES[i]][1] })
|
||||
self.editInput({
|
||||
index = i - 1,
|
||||
value = tokenPrecedence[TOKEN_NAMES[i]][1]
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- order function for data sorting
|
||||
function token_value_comparator(left, right)
|
||||
function tokenValueComparator(left, right)
|
||||
if left.value > right.value then
|
||||
return true
|
||||
elseif right.value > left.value then
|
||||
@ -219,46 +222,47 @@ function token_value_comparator(left, right)
|
||||
end
|
||||
end
|
||||
|
||||
-- checks scripting zone for chaos bag
|
||||
function findChaosBag()
|
||||
for _, item in ipairs(getObjectFromGUID("83ef06").getObjects()) do
|
||||
if item.getDescription() == "Chaos Bag" then
|
||||
return item
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- deletes previously placed tokens AND percentage buttons
|
||||
-- deletes previously placed tokens
|
||||
function deleteCopiedTokens()
|
||||
for _, token in ipairs(getObjectsWithTag("tempToken")) do
|
||||
token.destruct()
|
||||
end
|
||||
|
||||
-- this removes the percentage buttons
|
||||
self.clearButtons()
|
||||
createDefaultButtonsAndInputs()
|
||||
for _, token in ipairs(getObjectsWithTag("tempToken")) do token.destruct() end
|
||||
createButtonsAndInputs()
|
||||
end
|
||||
|
||||
-- creates percentage representation buttons
|
||||
function createPercentageButton(token_count, value_count, data, token_name, cumulative_percentage)
|
||||
local offset = -2.675
|
||||
local label_string = string.format("%s", string.format("%05.2f", math.floor((token_count / #data) * 10000) / 100) .. "%")
|
||||
local buttonScale = {2, 2, 2}
|
||||
local textColor = {1, 1, 1}
|
||||
function createPercentageButton(basePercentage, valueCount, tokenName, cumulativePercentage)
|
||||
local buttonScale, offset, textColor, labelString
|
||||
|
||||
if percentage == "cumulative" then
|
||||
|
||||
buttonScale = {1.5, 1.5, 1.5}
|
||||
offset = -2.85
|
||||
else
|
||||
buttonScale = {2, 2, 2}
|
||||
offset = -2.675
|
||||
end
|
||||
if cumulative_percentage then
|
||||
|
||||
-- if this is a cumulative button (bottom one of the two created buttons)
|
||||
if cumulativePercentage then
|
||||
offset = -2.45
|
||||
textColor = {1, 1, 1}
|
||||
label_string = string.format("%s", string.format("%05.2f", cumulative_percentage) .. "%")
|
||||
if cumulative_percentage == 100 then
|
||||
label_string = string.format("%s", string.format("%05.1f", cumulative_percentage) .. "%")
|
||||
|
||||
-- only display one digit for 100%
|
||||
if cumulativePercentage == 100 then
|
||||
labelString = string.format("%s", string.format("%05.1f", cumulativePercentage) .. "%")
|
||||
else
|
||||
labelString = string.format("%s", string.format("%05.2f", cumulativePercentage) .. "%")
|
||||
end
|
||||
else
|
||||
if token_name == "Elder Sign" then
|
||||
labelString = string.format("%s", string.format("%05.2f", basePercentage) .. "%")
|
||||
if tokenName == "Elder Sign" then
|
||||
textColor = {0.35, 0.71, 0.85}
|
||||
elseif token_name == "Auto-fail" then
|
||||
elseif tokenName == "Auto-fail" then
|
||||
textColor = {0.86, 0.1, 0.1}
|
||||
elseif token_name then
|
||||
elseif tokenName then
|
||||
textColor = {0.68, 0.53, 0.86}
|
||||
else
|
||||
textColor = {0.85, 0.67, 0.33}
|
||||
@ -266,13 +270,13 @@ function createPercentageButton(token_count, value_count, data, token_name, cumu
|
||||
end
|
||||
|
||||
self.createButton({
|
||||
label = label_string,
|
||||
click_function = "print",
|
||||
label = labelString,
|
||||
click_function = "none",
|
||||
width = 0,
|
||||
height = 0,
|
||||
scale = buttonScale,
|
||||
font_color = textColor,
|
||||
position = (Vector(2.2, -0.05, offset) + Vector(0.1, 0, 0.875 * value_count))
|
||||
position = Vector(2.3, -0.05, offset + 0.875 * valueCount)
|
||||
})
|
||||
end
|
||||
|
||||
@ -288,7 +292,7 @@ function layout(_, _, isRightClick)
|
||||
return
|
||||
end
|
||||
|
||||
local chaosBag = findChaosBag()
|
||||
local chaosBag = Global.call("findChaosBag")
|
||||
local data = {}
|
||||
|
||||
-- clone tokens from chaos bag (default position above trash can)
|
||||
@ -299,14 +303,15 @@ function layout(_, _, isRightClick)
|
||||
position = { 0.49, 3, 0 }
|
||||
})
|
||||
|
||||
local value = tonumber(obj["Nickname"])
|
||||
local precedence = tokenPrecedence[obj["Nickname"]]
|
||||
local value = tonumber(obj.Nickname)
|
||||
local precedence = tokenPrecedence[obj.Nickname]
|
||||
|
||||
data[i] = {
|
||||
token = spawnedObj,
|
||||
value = value or precedence[1]
|
||||
}
|
||||
|
||||
-- order for comparator function
|
||||
if precedence ~= nil then
|
||||
data[i].order = precedence[2]
|
||||
else
|
||||
@ -315,58 +320,60 @@ function layout(_, _, isRightClick)
|
||||
end
|
||||
|
||||
-- sort table by value (symbols last if same value)
|
||||
table.sort(data, token_value_comparator)
|
||||
|
||||
-- error handling for removal of token arranger
|
||||
if self == nil then
|
||||
for _, token in ipairs(getObjectsWithTag("tempToken")) do token.destruct() end
|
||||
return
|
||||
end
|
||||
table.sort(data, tokenValueComparator)
|
||||
|
||||
-- laying out the tokens
|
||||
local pos = self.getPosition() + Vector(3.55, -0.05, -3.95)
|
||||
if percentage then
|
||||
pos.z = self.getPosition().z - 7
|
||||
end
|
||||
local location = { x = pos.x, y = pos.y, z = pos.z }
|
||||
local current_value = data[1].value
|
||||
local token_count = 0
|
||||
local value_count = 1
|
||||
local cumulative_percentage = 0
|
||||
local current_token = false
|
||||
local pos = self.getPosition() + Vector(3.55, -0.05, -3.95)
|
||||
if percentage then pos.z = pos.z - 3.05 end
|
||||
|
||||
local location = { x = pos.x, y = pos.y, z = pos.z }
|
||||
local currentValue = data[1].value
|
||||
local tokenCount = 0
|
||||
local valueCount = 1
|
||||
local cumulativePercentage = 0
|
||||
local tokenName = false
|
||||
|
||||
for _, item in ipairs(data) do
|
||||
if item.value ~= current_value then
|
||||
if item.value ~= currentValue then
|
||||
if percentage then
|
||||
cumulative_percentage = cumulative_percentage + math.floor((token_count / #data) * 10000) / 100
|
||||
createPercentageButton(token_count, value_count, data, current_token)
|
||||
local basePercentage = math.floor((tokenCount / #data) * 10000) / 100
|
||||
createPercentageButton(basePercentage, valueCount, tokenName)
|
||||
if percentage == "cumulative" then
|
||||
createPercentageButton(token_count, value_count, data, current_token, cumulative_percentage)
|
||||
end
|
||||
end
|
||||
location.x = location.x - 1.75
|
||||
location.z = pos.z
|
||||
current_value = item.value
|
||||
value_count = value_count + 1
|
||||
token_count = 0
|
||||
current_token = false
|
||||
end
|
||||
if string.match(item.token.getName(), "%a") ~= nil then
|
||||
current_token = item.token.getName()
|
||||
cumulativePercentage = cumulativePercentage + basePercentage
|
||||
createPercentageButton(basePercentage, valueCount, tokenName, cumulativePercentage)
|
||||
end
|
||||
end
|
||||
|
||||
location.x = location.x - 1.75
|
||||
location.z = pos.z
|
||||
currentValue = item.value
|
||||
valueCount = valueCount + 1
|
||||
tokenCount = 0
|
||||
end
|
||||
|
||||
item.token.setPosition(location)
|
||||
item.token.setRotation(self.getRotation())
|
||||
location.z = location.z - 1.75
|
||||
token_count = token_count + 1
|
||||
end
|
||||
if percentage then
|
||||
cumulative_percentage = cumulative_percentage + math.floor((token_count / #data) * 10000) / 100
|
||||
createPercentageButton(token_count, value_count, data, current_token)
|
||||
if percentage == "cumulative" then
|
||||
createPercentageButton(token_count, value_count, data, current_token, cumulative_percentage)
|
||||
tokenCount = tokenCount + 1
|
||||
tokenName = item.token.getName()
|
||||
|
||||
-- set tokenName to false if it does not contain letters
|
||||
if string.match(tokenName, "%a") == nil then
|
||||
tokenName = false
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- this is repeated to create the button for the last token
|
||||
if percentage then
|
||||
local basePercentage = math.floor((tokenCount / #data) * 10000) / 100
|
||||
createPercentageButton(basePercentage, valueCount, tokenName)
|
||||
if percentage == "cumulative" then
|
||||
cumulativePercentage = cumulativePercentage + basePercentage
|
||||
createPercentageButton(basePercentage, valueCount, tokenName, cumulativePercentage)
|
||||
end
|
||||
end
|
||||
|
||||
-- introducing a small delay to limit update calls
|
||||
Wait.time(function() updating = false end, 0.1)
|
||||
end
|
||||
|
||||
@ -374,7 +381,7 @@ end
|
||||
function onTokenDataChanged(parameters)
|
||||
local tokenData = parameters.tokenData or {}
|
||||
local currentScenario = parameters.currentScenario or ""
|
||||
local useFrontData = parameters.useFrontData or true
|
||||
local useFrontData = parameters.useFrontData
|
||||
|
||||
-- only update if this data is new
|
||||
local info = currentScenario .. tostring(useFrontData)
|
||||
|
@ -24,7 +24,7 @@ do
|
||||
|
||||
-- updates the laid out tokens
|
||||
TokenArrangerApi.layout = function()
|
||||
callIfExistent("layout")
|
||||
Wait.time(function() callIfExistent("layout") end, 0.1)
|
||||
end
|
||||
|
||||
return TokenArrangerApi
|
||||
|
@ -77,7 +77,7 @@ do
|
||||
return false, "Deck not found!"
|
||||
end
|
||||
|
||||
return true, JSON.decode(status.text)
|
||||
return true, json
|
||||
end)
|
||||
|
||||
deck:with(internal.onDeckResult, playerColor, loadNewest, loadInvestigators, callback)
|
||||
@ -139,8 +139,9 @@ do
|
||||
-- investigator may have bonded cards or taboo entries, and should be present
|
||||
local slots = deck.slots
|
||||
internal.maybeDrawRandomWeakness(slots, playerColor)
|
||||
local loadAltInvestigator = "normal"
|
||||
if loadInvestigators then
|
||||
internal.addInvestigatorCards(deck, slots)
|
||||
loadAltInvestigator = internal.addInvestigatorCards(deck, slots)
|
||||
end
|
||||
internal.maybeAddCustomizeUpgradeSheets(slots)
|
||||
internal.maybeAddSummonedServitor(slots)
|
||||
@ -149,13 +150,12 @@ do
|
||||
internal.checkTaboos(deck.taboo_id, slots, playerColor)
|
||||
|
||||
-- get upgrades for customizable cards
|
||||
local meta = deck.meta
|
||||
local customizations = {}
|
||||
if meta then
|
||||
customizations = JSON.decode(meta)
|
||||
if deck.meta then
|
||||
customizations = JSON.decode(deck.meta)
|
||||
end
|
||||
|
||||
callback(slots, deck.investigator_code, bondList, customizations, playerColor)
|
||||
callback(slots, deck.investigator_code, bondList, customizations, playerColor, loadAltInvestigator)
|
||||
end
|
||||
|
||||
-- Checks to see if the slot list includes the random weakness ID. If it does,
|
||||
@ -186,25 +186,54 @@ do
|
||||
---@param deck Table The processed ArkhamDB deck response
|
||||
---@param slots Table The slot list for cards in this deck. Table key is the cardId, value is the
|
||||
--- number of those cards which will be spawned
|
||||
---@return string: Contains the name of the art that should be loaded ("normal", "promo" or "revised")
|
||||
internal.addInvestigatorCards = function(deck, slots)
|
||||
local investigatorId = deck.investigator_code
|
||||
slots[investigatorId .. "-m"] = 1
|
||||
local deckMeta = JSON.decode(deck.meta)
|
||||
local parallelFront = deckMeta ~= nil and deckMeta.alternate_front ~= nil and deckMeta.alternate_front ~= ""
|
||||
local parallelBack = deckMeta ~= nil and deckMeta.alternate_back ~= nil and deckMeta.alternate_back ~= ""
|
||||
if parallelFront and parallelBack then
|
||||
investigatorId = investigatorId .. "-p"
|
||||
elseif parallelFront then
|
||||
local alternateNum = tonumber(deckMeta.alternate_front)
|
||||
if alternateNum >= 01501 and alternateNum <= 01506 then
|
||||
investigatorId = investigatorId .. "-r"
|
||||
else
|
||||
investigatorId = investigatorId .. "-pf"
|
||||
-- handling alternative investigator art and parallel investigators
|
||||
local loadAltInvestigator = "normal"
|
||||
if deckMeta ~= nil then
|
||||
local altFrontId = tonumber(deckMeta.alternate_front) or 0
|
||||
local altBackId = tonumber(deckMeta.alternate_back) or 0
|
||||
local altArt = { front = "normal", back = "normal" }
|
||||
|
||||
-- translating front ID
|
||||
if altFrontId > 90000 and altFrontId < 90006 then
|
||||
altArt.front = "parallel"
|
||||
elseif altFrontId > 01500 and altFrontId < 01506 then
|
||||
altArt.front = "revised"
|
||||
elseif altFrontId > 98000 then
|
||||
altArt.front = "promo"
|
||||
end
|
||||
|
||||
-- translating back ID
|
||||
if altBackId > 90000 and altBackId < 90006 then
|
||||
altArt.back = "parallel"
|
||||
elseif altBackId > 01500 and altBackId < 01506 then
|
||||
altArt.back = "revised"
|
||||
elseif altBackId > 98000 then
|
||||
altArt.back = "promo"
|
||||
end
|
||||
|
||||
-- updating investigatorID based on alt investigator selection
|
||||
-- precedence: parallel > promo > revised
|
||||
if altArt.front == "parallel" then
|
||||
if altArt.back == "parallel" then
|
||||
investigatorId = investigatorId .. "-p"
|
||||
else
|
||||
investigatorId = investigatorId .. "-pf"
|
||||
end
|
||||
elseif altArt.back == "parallel" then
|
||||
investigatorId = investigatorId .. "-pb"
|
||||
elseif altArt.front == "promo" or altArt.back == "promo" then
|
||||
loadAltInvestigator = "promo"
|
||||
elseif altArt.front == "revised" or altArt.back == "revised" then
|
||||
loadAltInvestigator = "revised"
|
||||
end
|
||||
elseif parallelBack then
|
||||
investigatorId = investigatorId .. "-pb"
|
||||
end
|
||||
slots[investigatorId] = 1
|
||||
return loadAltInvestigator
|
||||
end
|
||||
|
||||
-- Process the card list looking for the customizable cards, and add their upgrade sheets if needed
|
||||
|
@ -1,6 +1,7 @@
|
||||
require("arkhamdb/DeckImporterUi")
|
||||
require("playercards/PlayerCardSpawner")
|
||||
|
||||
local playmatApi = require("playermat/PlaymatApi")
|
||||
local playAreaApi = require("core/PlayAreaApi")
|
||||
local arkhamDb = require("arkhamdb/ArkhamDb")
|
||||
local zones = require("playermat/Zones")
|
||||
@ -104,7 +105,8 @@ end
|
||||
-- from a parent bonded card.
|
||||
---@param customizations String ArkhamDB data for customizations on customizable cards
|
||||
---@param playerColor String Color name of the player mat to place this deck on (e.g. "Red")
|
||||
function loadCards(slots, investigatorId, bondedList, customizations, playerColor)
|
||||
---@param loadAltInvestigator String Contains the name of alternative art for the investigator ("normal", "revised" or "promo")
|
||||
function loadCards(slots, investigatorId, bondedList, customizations, playerColor, loadAltInvestigator)
|
||||
function coinside()
|
||||
local allCardsBag = getObjectFromGUID(ALL_CARDS_GUID)
|
||||
local yPos = {}
|
||||
@ -148,6 +150,8 @@ function loadCards(slots, investigatorId, bondedList, customizations, playerColo
|
||||
callback = function(deck) deck.spread(spreadDistance) end
|
||||
elseif zone == "Deck" then
|
||||
callback = function(deck) deckSpawned(deck, playerColor) end
|
||||
elseif zone == "Investigator" or zone == "Minicard" then
|
||||
callback = function(card) loadAltArt(card, loadAltInvestigator) end
|
||||
end
|
||||
Spawner.spawnCards(
|
||||
zoneCards,
|
||||
@ -181,7 +185,8 @@ end
|
||||
---@param deck Object Callback-provided spawned deck object
|
||||
---@param playerColor String Color of the player to draw the cards to
|
||||
function deckSpawned(deck, playerColor)
|
||||
local handPos = Player[playerColor].getHandTransform(1).position -- Only one hand zone per player
|
||||
local player = Player[playmatApi.getPlayerColor(playerColor)]
|
||||
local handPos = player.getHandTransform(1).position -- Only one hand zone per player
|
||||
local deckCards = deck.getData().ContainedObjects
|
||||
-- Process in reverse order so taking cards out doesn't upset the indexing
|
||||
for i = #deckCards, 1, -1 do
|
||||
@ -419,6 +424,51 @@ function handleCustomizableUpgrades(cardList, customizations)
|
||||
end
|
||||
end
|
||||
|
||||
-- Callback function for investigator cards and minicards to set the correct state for alt art
|
||||
---@param card Object Card which needs to be set the state for
|
||||
---@param loadAltInvestigator String Contains the name of alternative art for the investigator ("normal", "revised" or "promo")
|
||||
function loadAltArt(card, loadAltInvestigator)
|
||||
if loadAltInvestigator == "normal" then return end
|
||||
|
||||
-- lookup correct stateId for investigator and alt art state
|
||||
local baseId = string.gsub(JSON.decode(card.getGMNotes()).id, "-m", "")
|
||||
|
||||
local stateIdTable = {}
|
||||
-- Roland Banks
|
||||
stateIdTable["01001"] = {}
|
||||
stateIdTable["01001"]["revised"] = 2
|
||||
stateIdTable["01001"]["promo"] = 3
|
||||
-- Daisy Walker
|
||||
stateIdTable["01002"] = {}
|
||||
stateIdTable["01002"]["revised"] = 2
|
||||
-- "Skids" O'Toole
|
||||
stateIdTable["01003"] = {}
|
||||
stateIdTable["01003"]["revised"] = 2
|
||||
-- Agnes Baker
|
||||
stateIdTable["01004"] = {}
|
||||
stateIdTable["01004"]["revised"] = 2
|
||||
-- Wendy Adams
|
||||
stateIdTable["01005"] = {}
|
||||
stateIdTable["01005"]["revised"] = 2
|
||||
-- Jenny Barnes
|
||||
stateIdTable["02003"] = {}
|
||||
stateIdTable["02003"]["promo"] = 2
|
||||
-- Carolyn Fern
|
||||
stateIdTable["05001"] = {}
|
||||
stateIdTable["05001"]["promo"] = 2
|
||||
-- Dexter Drake
|
||||
stateIdTable["07004"] = {}
|
||||
stateIdTable["07004"]["promo"] = 2
|
||||
-- Silas Marsh
|
||||
stateIdTable["07005"] = {}
|
||||
stateIdTable["07005"]["promo"] = 2
|
||||
-- Norman Withers
|
||||
stateIdTable["08004"] = {}
|
||||
stateIdTable["08004"]["promo"] = 2
|
||||
|
||||
card.setState(stateIdTable[baseId][loadAltInvestigator])
|
||||
end
|
||||
|
||||
function log(message)
|
||||
if DEBUG then print(message) end
|
||||
end
|
||||
|
@ -1,9 +1,4 @@
|
||||
local tokenArrangerApi = require("accessories/TokenArrangerApi")
|
||||
|
||||
local IMAGE_URL = {
|
||||
Bless = "http://cloud-3.steamusercontent.com/ugc/1655601092778627699/339FB716CB25CA6025C338F13AFDFD9AC6FA8356/",
|
||||
Curse = "http://cloud-3.steamusercontent.com/ugc/1655601092778636039/2A25BD38E8C44701D80DD96BF0121DA21843672E/"
|
||||
}
|
||||
local tokenArrangerApi = require("accessories/TokenArrangerApi")
|
||||
|
||||
-- common button parameters
|
||||
local buttonParamaters = {}
|
||||
@ -12,11 +7,12 @@ buttonParamaters.color = { 0, 0, 0, 0 }
|
||||
buttonParamaters.width = 700
|
||||
buttonParamaters.height = 700
|
||||
|
||||
local altState = false
|
||||
local MODE = { [false] = "Add / Remove", [true] = "Take / Return" }
|
||||
local BUTTON_COLOR = { [false] = { 0.4, 0.4, 0.4 }, [true] = { 0.9, 0.9, 0.9 } }
|
||||
local FONT_COLOR = { [false] = { 1, 1, 1 }, [true] = { 0, 0, 0 } }
|
||||
local whitespace = " "
|
||||
local altState = false
|
||||
local MODE = { [false] = "Add / Remove",[true] = "Take / Return" }
|
||||
local BUTTON_COLOR = { [false] = { 0.4, 0.4, 0.4 },[true] = { 0.9, 0.9, 0.9 } }
|
||||
local FONT_COLOR = { [false] = { 1, 1, 1 },[true] = { 0, 0, 0 } }
|
||||
local whitespace = " "
|
||||
local updating
|
||||
|
||||
---------------------------------------------------------
|
||||
-- creating buttons and menus + initializing tables
|
||||
@ -71,8 +67,7 @@ end
|
||||
|
||||
function initializeState()
|
||||
-- count tokens in the bag
|
||||
local chaosbag = getChaosBag()
|
||||
if chaosbag == nil then return end
|
||||
local chaosbag = Global.call("findChaosBag")
|
||||
local tokens = {}
|
||||
for _, v in ipairs(chaosbag.getObjects()) do
|
||||
if v.name == "Bless" then
|
||||
@ -113,11 +108,7 @@ end
|
||||
|
||||
-- context menu function 1
|
||||
function doRemove(color)
|
||||
local chaosbag = getChaosBag()
|
||||
if chaosbag == nil then
|
||||
broadcastToAll("Chaos bag not found!", "Red")
|
||||
return
|
||||
end
|
||||
local chaosbag = Global.call("findChaosBag")
|
||||
|
||||
-- remove tokens from chaos bag
|
||||
local count = { Bless = 0, Curse = 0 }
|
||||
@ -132,22 +123,8 @@ function doRemove(color)
|
||||
end
|
||||
end
|
||||
|
||||
broadcastToColor("Removed " .. count["Bless"] .. " Bless and " ..
|
||||
count["Curse"] .. " Curse tokens from the chaos bag.", color, "White")
|
||||
|
||||
-- removing tokens that were 'taken'
|
||||
local function removeType(type)
|
||||
local count = 0
|
||||
for _, guid in ipairs(tokensTaken[type]) do
|
||||
local token = getObjectFromGUID(guid)
|
||||
if token ~= nil then
|
||||
token.destruct()
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
broadcastToColor("Removed " .. count.Bless .. " Bless and " ..
|
||||
count.Curse .. " Curse tokens from the chaos bag.", color, "White")
|
||||
broadcastToColor("Removed " .. removeType("Bless") .. " Bless and " ..
|
||||
removeType("Curse") .. " Curse tokens from play.", color, "White")
|
||||
|
||||
@ -156,9 +133,6 @@ end
|
||||
|
||||
-- context menu function 2
|
||||
function doReset(color)
|
||||
-- delete previously pulled out tokens by the token arranger
|
||||
tokenArrangerApi.deleteCopiedTokens()
|
||||
|
||||
playerColor = color
|
||||
numInPlay = { Bless = 0, Curse = 0 }
|
||||
tokensTaken = { Bless = {}, Curse = {} }
|
||||
@ -166,6 +140,19 @@ function doReset(color)
|
||||
tokenArrangerApi.layout()
|
||||
end
|
||||
|
||||
-- removing tokens that were 'taken'
|
||||
function removeType(type)
|
||||
local count = 0
|
||||
for _, guid in ipairs(tokensTaken[type]) do
|
||||
local token = getObjectFromGUID(guid)
|
||||
if token ~= nil then
|
||||
token.destruct()
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
-- click functions
|
||||
---------------------------------------------------------
|
||||
@ -248,27 +235,36 @@ function callFunctions(token, isRightClick)
|
||||
if success ~= 0 then tokenArrangerApi.layout() end
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local zone = getObjectFromGUID("83ef06")
|
||||
if zone == nil then printToAll("Zone for chaosbag not found!", "Red") return end
|
||||
|
||||
local items = zone.getObjects()
|
||||
local chaosbag = nil
|
||||
for _, v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToColor("No chaos bag found", playerColor) end
|
||||
return chaosbag
|
||||
end
|
||||
|
||||
function getTokenCount(type)
|
||||
if type == nil then type = mode end
|
||||
return "(" .. (numInPlay[type] - #tokensTaken[type]) .. "/" .. #tokensTaken[type] .. ")"
|
||||
end
|
||||
|
||||
-- called by cards that seal bless/curse tokens
|
||||
---@param param Table This contains the type and guid of the sealed token
|
||||
function sealedToken(param)
|
||||
table.insert(tokensTaken[param.type], param.guid)
|
||||
broadcastCount(param.type)
|
||||
end
|
||||
|
||||
-- called by cards that seal bless/curse tokens
|
||||
---@param param Table This contains the type and guid of the released token
|
||||
function releasedToken(param)
|
||||
for i, v in ipairs(tokensTaken[param.type]) do
|
||||
if v == param.guid then
|
||||
table.remove(tokensTaken[param.type], i)
|
||||
break
|
||||
end
|
||||
end
|
||||
if not updating then
|
||||
updating = true
|
||||
Wait.time(function()
|
||||
broadcastCount(param.type)
|
||||
updating = false
|
||||
end, 0.1)
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
-- main functions: add, take and return
|
||||
---------------------------------------------------------
|
||||
@ -278,39 +274,13 @@ function addToken(type)
|
||||
printToColor("10 tokens already in play, not adding any.", playerColor)
|
||||
return 0
|
||||
end
|
||||
return spawnToken(type)
|
||||
end
|
||||
|
||||
function spawnToken(type)
|
||||
local chaosbag = getChaosBag()
|
||||
if chaosbag == nil then
|
||||
return 0
|
||||
end
|
||||
local pos = chaosbag.getPosition()
|
||||
local obj = spawnObject({
|
||||
type = 'Custom_Tile',
|
||||
position = { pos.x, pos.y + 1, pos.z },
|
||||
callback_function = function(obj)
|
||||
obj.setName(type)
|
||||
chaosbag.putObject(obj)
|
||||
numInPlay[type] = numInPlay[type] + 1
|
||||
printToAll("Adding " .. type .. " token " .. getTokenCount(type))
|
||||
end
|
||||
})
|
||||
obj.setCustomObject({
|
||||
type = 2,
|
||||
image = IMAGE_URL[type],
|
||||
thickness = 0.1,
|
||||
})
|
||||
obj.scale { 0.81, 1, 0.81 }
|
||||
numInPlay[type] = numInPlay[type] + 1
|
||||
printToAll("Adding " .. type .. " token " .. getTokenCount(type))
|
||||
return Global.call("spawnChaosToken", type)
|
||||
end
|
||||
|
||||
function takeToken(type, remove)
|
||||
local chaosbag = getChaosBag()
|
||||
if chaosbag == nil then
|
||||
broadcastToAll("Chaos bag not found!", "Red")
|
||||
return 0
|
||||
end
|
||||
local chaosbag = Global.call("findChaosBag")
|
||||
if not remove and not SEAL_CARD_MESSAGE then
|
||||
broadcastToColor("For sealing tokens on cards try right-clicking on the card for seal options.", playerColor)
|
||||
SEAL_CARD_MESSAGE = true
|
||||
@ -355,7 +325,7 @@ function returnToken(type)
|
||||
printToColor("Couldn't find token " .. guid .. ", not returning to bag", playerColor)
|
||||
return 0
|
||||
end
|
||||
local chaosbag = getChaosBag()
|
||||
local chaosbag = Global.call("findChaosBag")
|
||||
if chaosbag == nil then
|
||||
return 0
|
||||
end
|
||||
@ -400,7 +370,7 @@ function addMenuOptions(playerColor, hoveredObject)
|
||||
end
|
||||
|
||||
function sealToken(type, playerColor, enemy)
|
||||
local chaosbag = getChaosBag()
|
||||
local chaosbag = Global.call("findChaosBag")
|
||||
if chaosbag == nil then return end
|
||||
local pos = enemy.getPosition()
|
||||
|
||||
@ -425,7 +395,7 @@ function sealToken(type, playerColor, enemy)
|
||||
end
|
||||
|
||||
function releaseToken(type, playerColor, enemy)
|
||||
local chaosbag = getChaosBag()
|
||||
local chaosbag = Global.call("findChaosBag")
|
||||
if chaosbag == nil then return end
|
||||
local tokens = sealedTokens[enemy.getGUID()]
|
||||
if tokens == nil or #tokens == 0 then return end
|
||||
|
24
src/chaosbag/BlessCurseManagerApi.ttslua
Normal file
24
src/chaosbag/BlessCurseManagerApi.ttslua
Normal file
@ -0,0 +1,24 @@
|
||||
do
|
||||
local BlessCurseManagerApi = {}
|
||||
local MANAGER_GUID = "5933fb"
|
||||
|
||||
-- removes all taken tokens and resets the counts
|
||||
BlessCurseManagerApi.removeTakenTokensAndReset = function()
|
||||
local BlessCurseManager = getObjectFromGUID(MANAGER_GUID)
|
||||
Wait.time(function() BlessCurseManager.call("removeType", "Bless") end, 0.05)
|
||||
Wait.time(function() BlessCurseManager.call("removeType", "Curse") end, 0.10)
|
||||
Wait.time(function() BlessCurseManager.call("doReset", "White") end, 0.15)
|
||||
end
|
||||
|
||||
-- updates the internal count (called by cards that seal bless/curse tokens)
|
||||
BlessCurseManagerApi.sealedToken = function(type, guid)
|
||||
getObjectFromGUID(MANAGER_GUID).call("sealedToken", { type = type, guid = guid })
|
||||
end
|
||||
|
||||
-- updates the internal count (called by cards that seal bless/curse tokens)
|
||||
BlessCurseManagerApi.releasedToken = function(type, guid)
|
||||
getObjectFromGUID(MANAGER_GUID).call("releasedToken", { type = type, guid = guid })
|
||||
end
|
||||
|
||||
return BlessCurseManagerApi
|
||||
end
|
@ -1,9 +0,0 @@
|
||||
-- automatically add correct names to tokens that enter the chaos bag
|
||||
function filterObjectEnter(obj)
|
||||
local props = obj.getCustomObject()
|
||||
if props ~= nil and props.image ~= nil then
|
||||
obj.setName(Global.call("getTokenName", { url = props.image }))
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
@ -34,6 +34,9 @@ local hideTitleSplashWaitFunctionId = nil
|
||||
local playmatApi = require("playermat/PlaymatApi")
|
||||
local tokenManager = require("core/token/TokenManager")
|
||||
local playAreaAPI = require("core/PlayAreaApi")
|
||||
local mythosAreaApi = require("core/MythosAreaApi")
|
||||
local tokenArrangerApi = require("accessories/TokenArrangerApi")
|
||||
local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi")
|
||||
|
||||
---------------------------------------------------------
|
||||
-- data for tokens
|
||||
@ -47,87 +50,46 @@ TOKEN_DATA = {
|
||||
clue = {image = "http://cloud-3.steamusercontent.com/ugc/1758068501357164917/1D06F1DC4D6888B6F57124BD2AFE20D0B0DA15A8/", scale = {0.15, 0.15, 0.15}}
|
||||
}
|
||||
|
||||
IMAGE_TOKEN_MAP = {
|
||||
["https://i.imgur.com/nEmqjmj.png"] = "Elder Sign",
|
||||
["https://i.imgur.com/uIx8jbY.png"] = "+1",
|
||||
["https://i.imgur.com/btEtVfd.png"] = "0",
|
||||
["https://i.imgur.com/w3XbrCC.png"] = "-1",
|
||||
["https://i.imgur.com/bfTg2hb.png"] = "-2",
|
||||
["https://i.imgur.com/yfs8gHq.png"] = "-3",
|
||||
["https://i.imgur.com/qrgGQRD.png"] = "-4",
|
||||
["https://i.imgur.com/3Ym1IeG.png"] = "-5",
|
||||
["https://i.imgur.com/c9qdSzS.png"] = "-6",
|
||||
["https://i.imgur.com/4WRD42n.png"] = "-7",
|
||||
["https://i.imgur.com/9t3rPTQ.png"] = "-8",
|
||||
["https://i.imgur.com/stbBxtx.png"] = "Skull",
|
||||
["https://i.imgur.com/VzhJJaH.png"] = "Cultist",
|
||||
["https://i.imgur.com/1plY463.png"] = "Tablet",
|
||||
["https://i.imgur.com/ttnspKt.png"] = "Elder Thing",
|
||||
["https://i.imgur.com/lns4fhz.png"] = "Auto-fail",
|
||||
["http://cloud-3.steamusercontent.com/ugc/1655601092778627699/339FB716CB25CA6025C338F13AFDFD9AC6FA8356/"] = "Bless",
|
||||
["http://cloud-3.steamusercontent.com/ugc/1655601092778636039/2A25BD38E8C44701D80DD96BF0121DA21843672E/"] = "Curse",
|
||||
["http://cloud-3.steamusercontent.com/ugc/1858293462583104677/195F93C063A8881B805CE2FD4767A9718B27B6AE/"] = "Frost"
|
||||
ID_URL_MAP = {
|
||||
['blue'] = {name = "Elder Sign", url = 'https://i.imgur.com/nEmqjmj.png'},
|
||||
['p1'] = {name = "+1", url = 'https://i.imgur.com/uIx8jbY.png'},
|
||||
['0'] = {name = "0", url = 'https://i.imgur.com/btEtVfd.png'},
|
||||
['m1'] = {name = "-1", url = 'https://i.imgur.com/w3XbrCC.png'},
|
||||
['m2'] = {name = "-2", url = 'https://i.imgur.com/bfTg2hb.png'},
|
||||
['m3'] = {name = "-3", url = 'https://i.imgur.com/yfs8gHq.png'},
|
||||
['m4'] = {name = "-4", url = 'https://i.imgur.com/qrgGQRD.png'},
|
||||
['m5'] = {name = "-5", url = 'https://i.imgur.com/3Ym1IeG.png'},
|
||||
['m6'] = {name = "-6", url = 'https://i.imgur.com/c9qdSzS.png'},
|
||||
['m7'] = {name = "-7", url = 'https://i.imgur.com/4WRD42n.png'},
|
||||
['m8'] = {name = "-8", url = 'https://i.imgur.com/9t3rPTQ.png'},
|
||||
['skull'] = {name = "Skull", url = 'https://i.imgur.com/stbBxtx.png'},
|
||||
['cultist'] = {name = "Cultist", url = 'https://i.imgur.com/VzhJJaH.png'},
|
||||
['tablet'] = {name = "Tablet", url = 'https://i.imgur.com/1plY463.png'},
|
||||
['elder'] = {name = "Elder Thing", url = 'https://i.imgur.com/ttnspKt.png'},
|
||||
['red'] = {name = "Auto-fail", url = 'https://i.imgur.com/lns4fhz.png'},
|
||||
['bless'] = {name = "Bless", url = 'http://cloud-3.steamusercontent.com/ugc/1655601092778627699/339FB716CB25CA6025C338F13AFDFD9AC6FA8356/'},
|
||||
['curse'] = {name = "Curse", url = 'http://cloud-3.steamusercontent.com/ugc/1655601092778636039/2A25BD38E8C44701D80DD96BF0121DA21843672E/'},
|
||||
['frost'] = {name = "Frost", url = 'http://cloud-3.steamusercontent.com/ugc/1858293462583104677/195F93C063A8881B805CE2FD4767A9718B27B6AE/'}
|
||||
}
|
||||
|
||||
---------------------------------------------------------
|
||||
-- data for chaos token stat tracker
|
||||
---------------------------------------------------------
|
||||
|
||||
local maxSquid = 0
|
||||
|
||||
MAT_GUID_TO_COLOUR = {
|
||||
["8b081b"] = "White",
|
||||
["bd0ff4"] = "Orange",
|
||||
["383d8b"] = "Green",
|
||||
["0840d5"] = "Red"
|
||||
local MAT_GUID_TO_COLOR = {
|
||||
["Overall"] = "Overall",
|
||||
["8b081b"] = "White",
|
||||
["bd0ff4"] = "Orange",
|
||||
["383d8b"] = "Green",
|
||||
["0840d5"] = "Red"
|
||||
}
|
||||
|
||||
local personalStats = {
|
||||
["8b081b"] = {},
|
||||
["bd0ff4"] = {},
|
||||
["383d8b"] = {},
|
||||
["0840d5"] = {}
|
||||
}
|
||||
|
||||
local overallStats = {
|
||||
-- cultist
|
||||
["https://i.imgur.com/VzhJJaH.png"] = 0,
|
||||
-- skull
|
||||
["https://i.imgur.com/stbBxtx.png"] = 0,
|
||||
-- tablet
|
||||
["https://i.imgur.com/1plY463.png"] = 0,
|
||||
-- curse
|
||||
["http://cloud-3.steamusercontent.com/ugc/1655601092778636039/2A25BD38E8C44701D80DD96BF0121DA21843672E/"] = 0,
|
||||
-- tentacle
|
||||
["https://i.imgur.com/lns4fhz.png"] = 0,
|
||||
-- minus eight
|
||||
["https://i.imgur.com/9t3rPTQ.png"] = 0,
|
||||
-- minus seven
|
||||
["https://i.imgur.com/4WRD42n.png"] = 0,
|
||||
-- minus six
|
||||
["https://i.imgur.com/c9qdSzS.png"] = 0,
|
||||
-- minus five
|
||||
["https://i.imgur.com/3Ym1IeG.png"] = 0,
|
||||
-- minus four
|
||||
["https://i.imgur.com/qrgGQRD.png"] = 0,
|
||||
-- minus three
|
||||
["https://i.imgur.com/yfs8gHq.png"] = 0,
|
||||
-- minus two
|
||||
["https://i.imgur.com/bfTg2hb.png"] = 0,
|
||||
-- minus one
|
||||
["https://i.imgur.com/w3XbrCC.png"] = 0,
|
||||
-- zero
|
||||
["https://i.imgur.com/btEtVfd.png"] = 0,
|
||||
-- plus one
|
||||
["https://i.imgur.com/uIx8jbY.png"] = 0,
|
||||
-- elder thing
|
||||
["https://i.imgur.com/ttnspKt.png"] = 0,
|
||||
-- bless
|
||||
["http://cloud-3.steamusercontent.com/ugc/1655601092778627699/339FB716CB25CA6025C338F13AFDFD9AC6FA8356/"] = 0,
|
||||
-- elder sign
|
||||
["https://i.imgur.com/nEmqjmj.png"] = 0,
|
||||
-- frost
|
||||
["http://cloud-3.steamusercontent.com/ugc/1858293462583104677/195F93C063A8881B805CE2FD4767A9718B27B6AE/"] = 0,
|
||||
local tokenDrawingStats = {
|
||||
["Overall"] = {},
|
||||
["8b081b"] = {},
|
||||
["bd0ff4"] = {},
|
||||
["383d8b"] = {},
|
||||
["0840d5"] = {}
|
||||
}
|
||||
|
||||
---------------------------------------------------------
|
||||
@ -270,13 +232,24 @@ end
|
||||
-- chaos token drawing
|
||||
---------------------------------------------------------
|
||||
|
||||
-- checks scripting zone for chaos bag
|
||||
-- checks scripting zone for chaos bag (also called by a lot of objects!)
|
||||
function findChaosBag()
|
||||
for _, item in ipairs(getObjectFromGUID("83ef06").getObjects()) do
|
||||
local chaosbag_zone = getObjectFromGUID("83ef06")
|
||||
|
||||
-- error handling: scripting zone not found
|
||||
if chaosbag_zone == nil then
|
||||
printToAll("Zone for chaos bag detection couldn't be found.", "Red")
|
||||
return
|
||||
end
|
||||
|
||||
for _, item in ipairs(chaosbag_zone.getObjects()) do
|
||||
if item.getDescription() == "Chaos Bag" then
|
||||
return item
|
||||
end
|
||||
end
|
||||
|
||||
-- error handling: chaos bag not found
|
||||
printToAll("Chaos bag couldn't be found.", "Red")
|
||||
end
|
||||
|
||||
function returnChaosTokens()
|
||||
@ -290,22 +263,20 @@ end
|
||||
-- are drawn or replaced a TTS bug can cause those tokens to vanish. Any functions which change the
|
||||
-- contents of the bag should check this method before doing so.
|
||||
-- This method will broadcast a message to all players if the bag is being searched.
|
||||
-- @return Boolean. True if the bag is manipulated, false if it should be blocked.
|
||||
---@return Boolean. True if the bag is manipulated, false if it should be blocked.
|
||||
function canTouchChaosTokens()
|
||||
for color, searching in pairs(bagSearchers) do
|
||||
if searching then
|
||||
broadcastToAll("Someone is searching the chaos bag, can't touch the tokens", "Red")
|
||||
broadcastToAll("Someone is searching the chaos bag, can't touch the tokens.", "Red")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function drawChaostoken(params)
|
||||
if not canTouchChaosTokens() then
|
||||
return
|
||||
end
|
||||
-- called by playermats (by the "Draw chaos token" button)
|
||||
function drawChaosToken(params)
|
||||
if not canTouchChaosTokens() then return end
|
||||
|
||||
local mat = params[1]
|
||||
local tokenOffset = params[2]
|
||||
@ -320,6 +291,7 @@ function drawChaostoken(params)
|
||||
end
|
||||
|
||||
chaosTokensLastMat = mat
|
||||
|
||||
-- if we have left clicked and have no tokens OR if we have right clicked
|
||||
if isRightClick or #chaosTokens == 0 then
|
||||
if #chaosbag.getObjects() == 0 then return end
|
||||
@ -328,11 +300,18 @@ function drawChaostoken(params)
|
||||
-- add the token to the list, compute new position based on list length
|
||||
tokenOffset[1] = tokenOffset[1] + (0.17 * #chaosTokens)
|
||||
local token = chaosbag.takeObject({
|
||||
index = 0,
|
||||
position = mat.positionToWorld(tokenOffset),
|
||||
rotation = mat.getRotation(),
|
||||
callback_function = function(obj) trackChaosToken(obj, mat.getGUID()) end
|
||||
rotation = mat.getRotation()
|
||||
})
|
||||
|
||||
-- get data for token description
|
||||
local name = token.getName()
|
||||
local tokenData = mythosAreaApi.returnTokenData().tokenData or {}
|
||||
local specificData = tokenData[name] or {}
|
||||
token.setDescription(specificData.description or "")
|
||||
|
||||
-- track the chaos token (for stat tracker and future returning)
|
||||
trackChaosToken(name, mat.getGUID())
|
||||
chaosTokens[#chaosTokens + 1] = token
|
||||
return
|
||||
else
|
||||
@ -355,64 +334,50 @@ end
|
||||
-- chaos token stat tracker
|
||||
---------------------------------------------------------
|
||||
|
||||
function trackChaosToken(token, matGUID)
|
||||
local image = token.getCustomObject().image
|
||||
overallStats[image] = (overallStats[image] or 0) + 1
|
||||
personalStats[matGUID][image] = (personalStats[matGUID][image] or 0) + 1
|
||||
function trackChaosToken(tokenName, matGUID)
|
||||
tokenDrawingStats["Overall"][tokenName] = (tokenDrawingStats["Overall"][tokenName] or 0) + 1
|
||||
tokenDrawingStats[matGUID][tokenName] = (tokenDrawingStats[matGUID][tokenName] or 0) + 1
|
||||
end
|
||||
|
||||
-- Left-click: print stats, Right-click: reset stats
|
||||
function handleStatTrackerClick(_, _, isRightClick)
|
||||
if isRightClick then
|
||||
resetChaosTokenStats()
|
||||
for key, _ in pairs(tokenDrawingStats) do
|
||||
tokenDrawingStats[key] = {}
|
||||
end
|
||||
else
|
||||
printChaosTokenStats()
|
||||
end
|
||||
end
|
||||
local squidKing = "Nobody"
|
||||
local maxSquid = 0
|
||||
local playerColor, playerName
|
||||
|
||||
for key, personalStats in pairs(tokenDrawingStats) do
|
||||
if personalStats ~= {} then
|
||||
if key == "Overall" then
|
||||
playerColor = "White"
|
||||
playerName = "Overall"
|
||||
else
|
||||
playerColor = playmatApi.getPlayerColor(MAT_GUID_TO_COLOR[key])
|
||||
playerName = Player[playerColor].steam_name or playerColor
|
||||
|
||||
function resetChaosTokenStats()
|
||||
for key, _ in pairs(overallStats) do
|
||||
overallStats[key] = 0
|
||||
end
|
||||
for playerKey, _ in pairs(personalStats) do
|
||||
for key, value in pairs(overallStats) do
|
||||
personalStats[playerKey][key] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function printChaosTokenStats()
|
||||
local squidKing = "Nobody"
|
||||
printToAll("")
|
||||
printToAll("Overall Stats")
|
||||
printToAll("------------------------------")
|
||||
printNonZeroTokenPairs(overallStats)
|
||||
printToAll("")
|
||||
printToAll("Individual Stats")
|
||||
printToAll("------------------------------")
|
||||
for matGUID, _ in pairs(personalStats) do
|
||||
local playerColour = MAT_GUID_TO_COLOUR[matGUID]
|
||||
local playerSquidCount = personalStats[matGUID]["https://i.imgur.com/lns4fhz.png"] or 0
|
||||
local playerName = playerColour
|
||||
if Player[playerColour].seated then
|
||||
playerName = Player[playerColour].steam_name
|
||||
end
|
||||
|
||||
printToAll(playerName .. " Stats", playerColour)
|
||||
printNonZeroTokenPairs(personalStats[matGUID])
|
||||
|
||||
if playerSquidCount > maxSquid then
|
||||
squidKing = playerName
|
||||
maxSquid = playerSquidCount
|
||||
end
|
||||
end
|
||||
printToAll(squidKing .. " is an auto-fail magnet.", {255, 0, 0})
|
||||
end
|
||||
|
||||
function printNonZeroTokenPairs(theTable)
|
||||
for key, value in pairs(theTable) do
|
||||
if value ~= 0 then
|
||||
printToAll(IMAGE_TOKEN_MAP[key] .. ': ' .. tostring(value))
|
||||
local playerSquidCount = personalStats["Auto-fail"] or 0
|
||||
if playerSquidCount > maxSquid then
|
||||
squidKing = playerName
|
||||
maxSquid = playerSquidCount
|
||||
end
|
||||
end
|
||||
|
||||
printToAll("------------------------------")
|
||||
printToAll(playerName .. " Stats", playerColor)
|
||||
|
||||
for tokenName, value in pairs(personalStats) do
|
||||
if value then
|
||||
printToAll(tokenName .. ': ' .. tostring(value))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
printToAll("------------------------------")
|
||||
printToAll(squidKing .. " is an auto-fail magnet.", {255, 0, 0})
|
||||
end
|
||||
end
|
||||
|
||||
@ -473,63 +438,44 @@ end
|
||||
-- called for adding chaos tokens
|
||||
---@param object object Usually "self"
|
||||
---@param key string Name of the scenario
|
||||
---@param mode string diffculty (e.g. "hard" or "expert")
|
||||
---@param mode string difficulty (e.g. "hard" or "expert")
|
||||
function fillContainer(args)
|
||||
chaosbag = findChaosBag()
|
||||
local data = getDataValue('modeData', args.key)
|
||||
if data == nil then return end
|
||||
|
||||
if chaosbag ~= nil then
|
||||
local data = getDataValue('modeData', args.key)
|
||||
if data == nil then return end
|
||||
local value = data[args.mode]
|
||||
if value == nil or value.token == nil then return end
|
||||
|
||||
local value = data[args.mode]
|
||||
if value == nil or value.token == nil then return end
|
||||
local tokenList = {}
|
||||
|
||||
local pos = chaosbag.getPosition()
|
||||
if args.object ~= nil then
|
||||
pos = args.object.getPosition()
|
||||
for _, tokenId in ipairs(value.token) do
|
||||
table.insert(tokenList, tokenId)
|
||||
end
|
||||
|
||||
if value.append ~= nil then
|
||||
for _, tokenId in ipairs(value.append) do
|
||||
table.insert(tokenList, tokenId)
|
||||
end
|
||||
end
|
||||
|
||||
-- empty the chaos bag
|
||||
for _, item in ipairs(chaosbag.getObjects()) do
|
||||
destroyObject(chaosbag.takeObject({}))
|
||||
end
|
||||
|
||||
for _, token in ipairs(value.token) do
|
||||
local obj = spawnChaosToken(token, pos)
|
||||
if obj ~= nil then
|
||||
chaosbag.putObject(obj)
|
||||
-- randomly choose tokens for specific Carcosa scenarios in standalone
|
||||
if value.random then
|
||||
local n = #value.random
|
||||
if n > 0 then
|
||||
for _, tokenId in ipairs(value.random[math.random(1, n)]) do
|
||||
table.insert(tokenList, tokenId)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if value.append ~= nil then
|
||||
for _, token in ipairs(value.append) do
|
||||
local obj = spawnChaosToken(token, pos)
|
||||
if obj ~= nil then
|
||||
chaosbag.putObject(obj)
|
||||
end
|
||||
end
|
||||
end
|
||||
setChaosBagState(tokenList)
|
||||
|
||||
-- randomly choose tokens for specific Carcosa scenarios in standalone
|
||||
if value.random then
|
||||
local n = #value.random
|
||||
if n > 0 then
|
||||
for _, token in ipairs(value.random[math.random(1, n)]) do
|
||||
local obj = spawnChaosToken(token, pos)
|
||||
if obj ~= nil then
|
||||
chaosbag.putObject(obj)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if value.message then
|
||||
broadcastToAll(value.message)
|
||||
end
|
||||
|
||||
if value.message then
|
||||
broadcastToAll(value.message)
|
||||
end
|
||||
|
||||
if value.warning then
|
||||
broadcastToAll(value.warning, { 1, 0.5, 0.5 })
|
||||
end
|
||||
if value.warning then
|
||||
broadcastToAll(value.warning, { 1, 0.5, 0.5 })
|
||||
end
|
||||
end
|
||||
|
||||
@ -554,52 +500,112 @@ function getDataValue(storage, key)
|
||||
end
|
||||
end
|
||||
|
||||
function spawnChaosToken(id, pos)
|
||||
local url = getChaosTokenImageURL(id)
|
||||
if url ~= '' then
|
||||
local obj = spawnObject({
|
||||
-- respawns the chaos bag with a new state of tokens
|
||||
---@param tokenList Table List of chaos token ids
|
||||
function setChaosBagState(tokenList)
|
||||
if not canTouchChaosTokens() then return end
|
||||
|
||||
local chaosbag = findChaosBag()
|
||||
local chaosbagData = chaosbag.getData()
|
||||
local reserveData = getObjectFromGUID("106418").getData()
|
||||
local tokenCache = {}
|
||||
local containedObjects = {}
|
||||
|
||||
-- create a temporary copy of the data for each chaos token
|
||||
for _, objData in ipairs(reserveData.ContainedObjects) do
|
||||
tokenCache[objData.Nickname] = objData
|
||||
end
|
||||
|
||||
-- iterate over tokenlist and insert specified tokens into new table
|
||||
for _, tokenId in ipairs(tokenList) do
|
||||
local tokenName = ID_URL_MAP[tokenId].name
|
||||
table.insert(containedObjects, tokenCache[tokenName])
|
||||
end
|
||||
|
||||
-- overwrite chaos bag content and respawn it
|
||||
chaosbagData.ContainedObjects = containedObjects
|
||||
chaosbag.destruct()
|
||||
spawnObjectData({data = chaosbagData})
|
||||
|
||||
-- remove tokens that are still in play
|
||||
for _, token in pairs(chaosTokens) do
|
||||
if token ~= nil then token.destruct() end
|
||||
end
|
||||
chaosTokens = {}
|
||||
chaosTokensLastMat = nil
|
||||
|
||||
-- reset bless / curse manager
|
||||
blessCurseManagerApi.removeTakenTokensAndReset()
|
||||
|
||||
printToAll("Chaos bag set to chosen difficulty.", "Green")
|
||||
end
|
||||
|
||||
-- spawns the specified chaos token and puts it into the chaos bag
|
||||
---@param id String ID of the chaos token
|
||||
function spawnChaosToken(id)
|
||||
if not canTouchChaosTokens() then return end
|
||||
|
||||
id = id:lower()
|
||||
local chaosbag = findChaosBag()
|
||||
local url = ID_URL_MAP[id].url or ""
|
||||
|
||||
if url ~= "" then
|
||||
return spawnObject({
|
||||
type = 'Custom_Tile',
|
||||
position = {pos.x, pos.y + 3, pos.z},
|
||||
rotation = {0, 260, 0}
|
||||
})
|
||||
obj.setCustomObject({
|
||||
position = { 0.49, 3, 0 },
|
||||
scale = { 0.81, 1.0, 0.81 },
|
||||
rotation = {0, 270, 0},
|
||||
callback_function = function(obj)
|
||||
obj.setName(ID_URL_MAP[id].name)
|
||||
chaosbag.putObject(obj)
|
||||
tokenArrangerApi.layout()
|
||||
end
|
||||
}).setCustomObject({
|
||||
type = 2,
|
||||
image = url,
|
||||
thickness = 0.1
|
||||
})
|
||||
obj.scale {0.81, 1, 0.81}
|
||||
obj.setName(getTokenName({ url=url }))
|
||||
return obj
|
||||
end
|
||||
end
|
||||
|
||||
-- chaos bag needs this for renaming chaos tokens
|
||||
function getTokenName(params)
|
||||
local name = IMAGE_TOKEN_MAP[params.url]
|
||||
if name == nil then name = "" end
|
||||
return name
|
||||
-- removes the specified chaos token from the chaos bag
|
||||
---@param id String ID of the chaos token
|
||||
function removeChaosToken(id)
|
||||
if not canTouchChaosTokens() then return end
|
||||
|
||||
local tokens = {}
|
||||
local chaosbag = findChaosBag()
|
||||
local name = ID_URL_MAP[id].name
|
||||
|
||||
for _, v in ipairs(chaosbag.getObjects()) do
|
||||
if v.name == name then table.insert(tokens, v.guid) end
|
||||
end
|
||||
|
||||
-- error handling: no matching token found
|
||||
if #tokens == 0 then
|
||||
printToAll("No " .. name .. " tokens in the chaos bag.", "Yellow")
|
||||
return
|
||||
end
|
||||
|
||||
chaosbag.takeObject({
|
||||
guid = tokens[1],
|
||||
smooth = false,
|
||||
callback_function = function(obj)
|
||||
obj.destruct()
|
||||
tokenArrangerApi.layout()
|
||||
end
|
||||
})
|
||||
printToAll("Removing " .. name .. " token (in bag: " .. #tokens - 1 .. ")", "White")
|
||||
end
|
||||
|
||||
-- returns the image url for a chaos token (identified by the "id")
|
||||
function getChaosTokenImageURL(id)
|
||||
if id == 'p1' then return 'https://i.imgur.com/uIx8jbY.png' end
|
||||
if id == '0' then return 'https://i.imgur.com/btEtVfd.png' end
|
||||
if id == 'm1' then return 'https://i.imgur.com/w3XbrCC.png' end
|
||||
if id == 'm2' then return 'https://i.imgur.com/bfTg2hb.png' end
|
||||
if id == 'm3' then return 'https://i.imgur.com/yfs8gHq.png' end
|
||||
if id == 'm4' then return 'https://i.imgur.com/qrgGQRD.png' end
|
||||
if id == 'm5' then return 'https://i.imgur.com/3Ym1IeG.png' end
|
||||
if id == 'm6' then return 'https://i.imgur.com/c9qdSzS.png' end
|
||||
if id == 'm7' then return 'https://i.imgur.com/4WRD42n.png' end
|
||||
if id == 'm8' then return 'https://i.imgur.com/9t3rPTQ.png' end
|
||||
if id == 'skull' then return 'https://i.imgur.com/stbBxtx.png' end
|
||||
if id == 'cultist' then return 'https://i.imgur.com/VzhJJaH.png' end
|
||||
if id == 'tablet' then return 'https://i.imgur.com/1plY463.png' end
|
||||
if id == 'elder' then return 'https://i.imgur.com/ttnspKt.png' end
|
||||
if id == 'red' then return 'https://i.imgur.com/lns4fhz.png' end
|
||||
if id == 'blue' then return 'https://i.imgur.com/nEmqjmj.png' end
|
||||
if id == 'frost' then return 'http://cloud-3.steamusercontent.com/ugc/1858293462583104677/195F93C063A8881B805CE2FD4767A9718B27B6AE/' end
|
||||
return ''
|
||||
-- empty the chaos bag
|
||||
function emptyChaosBag()
|
||||
if not canTouchChaosTokens() then return end
|
||||
|
||||
local chaosbag = findChaosBag()
|
||||
for _, object in ipairs(chaosbag.getObjects()) do
|
||||
chaosbag.takeObject({callback_function = function(item) item.destruct() end})
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
|
@ -62,7 +62,10 @@ function onCollisionEnter(collisionInfo)
|
||||
-- trigger update if a change was detected and push new data
|
||||
if updateNeeded then
|
||||
local metadata = JSON.decode(object.getGMNotes()) or {}
|
||||
if not metadata["tokens"] then return end
|
||||
if not metadata["tokens"] then
|
||||
tokenData = {}
|
||||
return
|
||||
end
|
||||
tokenData = metadata["tokens"][(useFrontData and "front" or "back")]
|
||||
fireTokenDataChangedEvent()
|
||||
end
|
||||
|
154
src/playercards/CardsThatSealTokens.ttslua
Normal file
154
src/playercards/CardsThatSealTokens.ttslua
Normal file
@ -0,0 +1,154 @@
|
||||
--[[ Library for cards that seal tokens
|
||||
This file is used to add sealing option to cards' context menu.
|
||||
Valid options (set before requiring this file):
|
||||
SHOW_READ_BAG -- boolean
|
||||
SHOW_SINGLE_RELEASE -- boolean
|
||||
SHOW_MULTI_RELEASE -- number (amount of tokens to release at once)
|
||||
VALID_TOKENS -- table ([tokenName] = true)
|
||||
INVALID_TOKENS -- table ([tokenName] = true)]]
|
||||
|
||||
local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi")
|
||||
local tokenArrangerApi = require("accessories/TokenArrangerApi")
|
||||
|
||||
function onSave() return JSON.encode(sealedTokens) end
|
||||
|
||||
function onLoad(savedData)
|
||||
sealedTokens = JSON.decode(savedData) or {}
|
||||
ID_URL_MAP = Global.getTable("ID_URL_MAP")
|
||||
generateContextMenu()
|
||||
end
|
||||
|
||||
-- builds the context menu
|
||||
function generateContextMenu()
|
||||
self.clearContextMenu()
|
||||
|
||||
-- only show this for cards that need a dynamic list of tokens (for example 'Unrelenting')
|
||||
if SHOW_READ_BAG then
|
||||
self.addContextMenuItem("Update list", generateContextMenu)
|
||||
readBag()
|
||||
end
|
||||
|
||||
-- conditional single or multi release options
|
||||
if SHOW_SINGLE_RELEASE then
|
||||
self.addContextMenuItem("Release token", releaseOneToken)
|
||||
elseif SHOW_MULTI_RELEASE then
|
||||
self.addContextMenuItem("Release " .. SHOW_MULTI_RELEASE .. " token(s)", function(playerColor)
|
||||
if SHOW_MULTI_RELEASE >= #sealedTokens then
|
||||
for i = 1, SHOW_MULTI_RELEASE do
|
||||
releaseOneToken(playerColor)
|
||||
end
|
||||
else
|
||||
printToColor("Not enough " .. name .. " tokens sealed.", playerColor)
|
||||
end
|
||||
end)
|
||||
else
|
||||
self.addContextMenuItem("Release token(s)", releaseTokens)
|
||||
end
|
||||
|
||||
-- main context menu options to seal tokens
|
||||
for _, map in pairs(ID_URL_MAP) do
|
||||
if (VALID_TOKENS[map.name] ~= nil) or (SHOW_READ_BAG and tokensInBag[map.name] and not INVALID_TOKENS[map.name]) then
|
||||
if not SHOW_MULTI_SEAL then
|
||||
self.addContextMenuItem("Seal " .. map.name, function(playerColor)
|
||||
sealToken(map.name, playerColor)
|
||||
end)
|
||||
else
|
||||
self.addContextMenuItem("Seal " .. SHOW_MULTI_SEAL .. " " .. map.name, function(playerColor)
|
||||
readBag()
|
||||
local allowed = true
|
||||
local notFound
|
||||
|
||||
for name, _ in pairs(VALID_TOKENS) do
|
||||
if (tokensInBag[name] or 0) < SHOW_MULTI_SEAL then
|
||||
allowed = false
|
||||
notFound = name
|
||||
end
|
||||
end
|
||||
|
||||
if allowed then
|
||||
for i = 1, SHOW_MULTI_SEAL do
|
||||
sealToken(map.name, playerColor)
|
||||
end
|
||||
else
|
||||
printToColor("Not enough " .. notFound .. " tokens in the chaos bag.", playerColor)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- generates a list of chaos tokens that is in the chaos bag
|
||||
function readBag()
|
||||
local chaosbag = Global.call("findChaosBag")
|
||||
tokensInBag = {}
|
||||
|
||||
for _, token in ipairs(chaosbag.getObjects()) do
|
||||
tokensInBag[token.name] = (tokensInBag[token.name] or 0) + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- seals the named token on this card
|
||||
function sealToken(name, playerColor)
|
||||
if not Global.call("canTouchChaosTokens") then return end
|
||||
local chaosbag = Global.call("findChaosBag")
|
||||
for i, obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position = self.getPosition() + Vector(0, 0.5 + 0.1 * #sealedTokens, 0),
|
||||
rotation = self.getRotation(),
|
||||
index = i - 1,
|
||||
smooth = false,
|
||||
callback_function = function(token)
|
||||
local guid = token.getGUID()
|
||||
table.insert(sealedTokens, guid)
|
||||
tokenArrangerApi.layout()
|
||||
if name == "Bless" or name == "Curse" then
|
||||
blessCurseManagerApi.sealedToken(name, guid)
|
||||
end
|
||||
end
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in chaos bag", playerColor)
|
||||
end
|
||||
|
||||
-- release the last sealed token
|
||||
function releaseOneToken(playerColor)
|
||||
if not Global.call("canTouchChaosTokens") then return end
|
||||
if sealedTokens == {} or #sealedTokens == 0 then
|
||||
printToColor("No sealed token(s) found", playerColor)
|
||||
else
|
||||
printToColor("Releasing token", playerColor)
|
||||
putTokenAway(table.remove(sealedTokens))
|
||||
end
|
||||
end
|
||||
|
||||
-- releases all sealed tokens
|
||||
function releaseTokens(playerColor)
|
||||
if not Global.call("canTouchChaosTokens") then return end
|
||||
if #sealedTokens == 0 then
|
||||
printToColor("No sealed token(s) found", playerColor)
|
||||
else
|
||||
printToColor("Releasing token(s)", playerColor)
|
||||
for _, guid in ipairs(sealedTokens) do
|
||||
putTokenAway(guid)
|
||||
end
|
||||
sealedTokens = {}
|
||||
end
|
||||
end
|
||||
|
||||
-- returns the token (referenced by GUID) to the chaos bag
|
||||
function putTokenAway(guid)
|
||||
local token = getObjectFromGUID(guid)
|
||||
if not token then return end
|
||||
|
||||
local name = token.getName()
|
||||
local chaosbag = Global.call("findChaosBag")
|
||||
chaosbag.putObject(token)
|
||||
tokenArrangerApi.layout()
|
||||
if name == "Bless" or name == "Curse" then
|
||||
blessCurseManagerApi.releasedToken(name, guid)
|
||||
end
|
||||
end
|
@ -1,65 +1,6 @@
|
||||
VALID_TOKENS = {
|
||||
["+1"]=true,
|
||||
["Elder Sign"]=true
|
||||
["+1"] = true,
|
||||
["Elder Sign"] = true
|
||||
}
|
||||
|
||||
function onload()
|
||||
chaosbag = getChaosBag()
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if VALID_TOKENS[name] ~= nil then
|
||||
self.addContextMenuItem("Seal " .. name, function(playerColor) sealToken(url, playerColor) end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
printToColor("Releasing token", playerColor)
|
||||
for i,obj in ipairs(sealedTokens) do
|
||||
chaosbag.putObject(obj)
|
||||
end
|
||||
sealedTokens = { }
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,81 +1,5 @@
|
||||
function onload()
|
||||
mode = "Curse"
|
||||
chaosbag = getChaosBag()
|
||||
manager = getObjectFromGUID("5933fb")
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {
|
||||
["Curse"] = true
|
||||
}
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens, true)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if name == mode then
|
||||
self.addContextMenuItem("Seal " .. mode, function(playerColor) sealToken(url, playerColor) end, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
local guid = obj.getGUID()
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
table.insert(tokensTaken[mode], guid)
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Sealing " .. mode .. " token " .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
if #sealedTokens == 0 then return end
|
||||
local token = sealedTokens[#sealedTokens]
|
||||
if token ~= nil then
|
||||
local guid = token.getGUID()
|
||||
chaosbag.putObject(token)
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
for i,v in ipairs(tokensTaken[mode]) do
|
||||
if v == guid then
|
||||
table.remove(tokensTaken[mode], i)
|
||||
break
|
||||
end
|
||||
end
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Releasing " .. mode .. " token" .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
table.remove(sealedTokens)
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,60 +1,5 @@
|
||||
function onload()
|
||||
chaosbag = getChaosBag()
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {
|
||||
["Elder Sign"] = true
|
||||
}
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if name == "Elder Sign" then
|
||||
self.addContextMenuItem("Seal Elder Sign", function(playerColor) sealToken(url, playerColor) end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
printToColor("Releasing token", playerColor)
|
||||
for i,obj in ipairs(sealedTokens) do
|
||||
chaosbag.putObject(obj)
|
||||
end
|
||||
sealedTokens = { }
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,81 +1,7 @@
|
||||
function onload()
|
||||
mode = "Curse"
|
||||
chaosbag = getChaosBag()
|
||||
manager = getObjectFromGUID("5933fb")
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {
|
||||
["Curse"] = true
|
||||
}
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens, true)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if name == mode then
|
||||
self.addContextMenuItem("Seal " .. mode, function(playerColor) sealToken(url, playerColor) end, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
SHOW_SINGLE_RELEASE = true
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
local guid = obj.getGUID()
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
table.insert(tokensTaken[mode], guid)
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Sealing " .. mode .. " token " .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
if #sealedTokens == 0 then return end
|
||||
local token = sealedTokens[#sealedTokens]
|
||||
if token ~= nil then
|
||||
local guid = token.getGUID()
|
||||
chaosbag.putObject(token)
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
for i,v in ipairs(tokensTaken[mode]) do
|
||||
if v == guid then
|
||||
table.remove(tokensTaken[mode], i)
|
||||
break
|
||||
end
|
||||
end
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Releasing " .. mode .. " token" .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
table.remove(sealedTokens)
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,81 +1,7 @@
|
||||
function onload()
|
||||
mode = "Bless"
|
||||
chaosbag = getChaosBag()
|
||||
manager = getObjectFromGUID("5933fb")
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {
|
||||
["Bless"] = true
|
||||
}
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens, true)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if name == mode then
|
||||
self.addContextMenuItem("Seal " .. mode, function(playerColor) sealToken(url, playerColor) end, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
SHOW_SINGLE_RELEASE = true
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
local guid = obj.getGUID()
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
table.insert(tokensTaken[mode], guid)
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Sealing " .. mode .. " token " .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
if #sealedTokens == 0 then return end
|
||||
local token = sealedTokens[#sealedTokens]
|
||||
if token ~= nil then
|
||||
local guid = token.getGUID()
|
||||
chaosbag.putObject(token)
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
for i,v in ipairs(tokensTaken[mode]) do
|
||||
if v == guid then
|
||||
table.remove(tokensTaken[mode], i)
|
||||
break
|
||||
end
|
||||
end
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Releasing " .. mode .. " token" .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
table.remove(sealedTokens)
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,81 +1,7 @@
|
||||
function onload()
|
||||
mode = "Curse"
|
||||
chaosbag = getChaosBag()
|
||||
manager = getObjectFromGUID("5933fb")
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {
|
||||
["Curse"] = true
|
||||
}
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens, true)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if name == mode then
|
||||
self.addContextMenuItem("Seal " .. mode, function(playerColor) sealToken(url, playerColor) end, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
SHOW_SINGLE_RELEASE = true
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
local guid = obj.getGUID()
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
table.insert(tokensTaken[mode], guid)
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Sealing " .. mode .. " token " .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
if #sealedTokens == 0 then return end
|
||||
local token = sealedTokens[#sealedTokens]
|
||||
if token ~= nil then
|
||||
local guid = token.getGUID()
|
||||
chaosbag.putObject(token)
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
for i,v in ipairs(tokensTaken[mode]) do
|
||||
if v == guid then
|
||||
table.remove(tokensTaken[mode], i)
|
||||
break
|
||||
end
|
||||
end
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Releasing " .. mode .. " token" .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
table.remove(sealedTokens)
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,93 +1,8 @@
|
||||
function onload()
|
||||
mode = "Bless"
|
||||
chaosbag = getChaosBag()
|
||||
manager = getObjectFromGUID("5933fb")
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {
|
||||
["Bless"] = true
|
||||
}
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens, true)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if name == mode then
|
||||
self.addContextMenuItem("Seal 2 " .. mode, function(playerColor) sealToken(url, playerColor) end, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
SHOW_SINGLE_RELEASE = true
|
||||
SHOW_MULTI_SEAL = 2
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
local indexes = {}
|
||||
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
table.insert(indexes, obj.index)
|
||||
end
|
||||
end
|
||||
if #indexes < 2 then
|
||||
printToColor("Fewer than 2 " .. name .. " tokens in bag", playerColor)
|
||||
return
|
||||
end
|
||||
table.sort(indexes)
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=indexes[#indexes],
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 2, pos.z },
|
||||
index=indexes[#indexes-1],
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
local guid = obj.getGUID()
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
table.insert(tokensTaken[mode], guid)
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Sealing " .. mode .. " token " .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
if #sealedTokens == 0 then return end
|
||||
local token = sealedTokens[#sealedTokens]
|
||||
if token ~= nil then
|
||||
local guid = token.getGUID()
|
||||
chaosbag.putObject(token)
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
for i,v in ipairs(tokensTaken[mode]) do
|
||||
if v == guid then
|
||||
table.remove(tokensTaken[mode], i)
|
||||
break
|
||||
end
|
||||
end
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Releasing " .. mode .. " token" .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
table.remove(sealedTokens)
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,81 +1,7 @@
|
||||
function onload()
|
||||
mode = "Bless"
|
||||
chaosbag = getChaosBag()
|
||||
manager = getObjectFromGUID("5933fb")
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {
|
||||
["Bless"] = true
|
||||
}
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens, true)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if name == mode then
|
||||
self.addContextMenuItem("Seal " .. mode, function(playerColor) sealToken(url, playerColor) end, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
SHOW_MULTI_RELEASE = 3
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
local guid = obj.getGUID()
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
table.insert(tokensTaken[mode], guid)
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Sealing " .. mode .. " token " .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
if #sealedTokens == 0 then return end
|
||||
local token = sealedTokens[#sealedTokens]
|
||||
if token ~= nil then
|
||||
local guid = token.getGUID()
|
||||
chaosbag.putObject(token)
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
for i,v in ipairs(tokensTaken[mode]) do
|
||||
if v == guid then
|
||||
table.remove(tokensTaken[mode], i)
|
||||
break
|
||||
end
|
||||
end
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Releasing " .. mode .. " token" .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
table.remove(sealedTokens)
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,75 +1,9 @@
|
||||
function onload()
|
||||
chaosbag = getChaosBag()
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
readBag()
|
||||
end
|
||||
VALID_TOKENS = {}
|
||||
|
||||
function readBag(playerColor)
|
||||
if playerColor ~= nil then
|
||||
printToColor("Reading chaos bag", playerColor)
|
||||
end
|
||||
INVALID_TOKENS = {
|
||||
["Auto-fail"] = true
|
||||
}
|
||||
|
||||
local tokensInBag = { }
|
||||
for i,token in ipairs(chaosbag.getObjects()) do
|
||||
if token.name ~= nil and token.name ~= "" then
|
||||
tokensInBag[token.name] = true
|
||||
end
|
||||
end
|
||||
SHOW_READ_BAG = true
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if tokensInBag[name] and name ~= "Auto-fail" then
|
||||
self.addContextMenuItem("Seal " .. name, function(playerColor) sealToken(url, playerColor) end)
|
||||
end
|
||||
end
|
||||
self.addContextMenuItem("Read Chaos Bag", readBag)
|
||||
end
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
printToColor("Releasing token", playerColor)
|
||||
for i,obj in ipairs(sealedTokens) do
|
||||
chaosbag.putObject(obj)
|
||||
end
|
||||
sealedTokens = { }
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,81 +1,5 @@
|
||||
function onload()
|
||||
mode = "Bless"
|
||||
chaosbag = getChaosBag()
|
||||
manager = getObjectFromGUID("5933fb")
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {
|
||||
["Bless"] = true
|
||||
}
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens, true)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if name == mode then
|
||||
self.addContextMenuItem("Seal " .. mode, function(playerColor) sealToken(url, playerColor) end, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
local guid = obj.getGUID()
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
table.insert(tokensTaken[mode], guid)
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Sealing " .. mode .. " token " .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
if #sealedTokens == 0 then return end
|
||||
local token = sealedTokens[#sealedTokens]
|
||||
if token ~= nil then
|
||||
local guid = token.getGUID()
|
||||
chaosbag.putObject(token)
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
for i,v in ipairs(tokensTaken[mode]) do
|
||||
if v == guid then
|
||||
table.remove(tokensTaken[mode], i)
|
||||
break
|
||||
end
|
||||
end
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Releasing " .. mode .. " token" .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
table.remove(sealedTokens)
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,81 +1,7 @@
|
||||
function onload()
|
||||
mode = "Bless"
|
||||
chaosbag = getChaosBag()
|
||||
manager = getObjectFromGUID("5933fb")
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {
|
||||
["Bless"] = true
|
||||
}
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens, true)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if name == mode then
|
||||
self.addContextMenuItem("Seal " .. mode, function(playerColor) sealToken(url, playerColor) end, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
SHOW_SINGLE_RELEASE = true
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
local guid = obj.getGUID()
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
table.insert(tokensTaken[mode], guid)
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Sealing " .. mode .. " token " .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
if #sealedTokens == 0 then return end
|
||||
local token = sealedTokens[#sealedTokens]
|
||||
if token ~= nil then
|
||||
local guid = token.getGUID()
|
||||
chaosbag.putObject(token)
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
for i,v in ipairs(tokensTaken[mode]) do
|
||||
if v == guid then
|
||||
table.remove(tokensTaken[mode], i)
|
||||
break
|
||||
end
|
||||
end
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Releasing " .. mode .. " token" .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
table.remove(sealedTokens)
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,60 +1,5 @@
|
||||
function onload()
|
||||
chaosbag = getChaosBag()
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {
|
||||
["Auto-fail"] = true
|
||||
}
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if name == "Auto-fail" then
|
||||
self.addContextMenuItem("Seal Auto-fail", function(playerColor) sealToken(url, playerColor) end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
printToColor("Releasing token", playerColor)
|
||||
for i,obj in ipairs(sealedTokens) do
|
||||
chaosbag.putObject(obj)
|
||||
end
|
||||
sealedTokens = { }
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,60 +1,5 @@
|
||||
function onload()
|
||||
chaosbag = getChaosBag()
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {
|
||||
["Elder Sign"] = true
|
||||
}
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if name == "Elder Sign" then
|
||||
self.addContextMenuItem("Seal Elder Sign", function(playerColor) sealToken(url, playerColor) end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
printToColor("Releasing token", playerColor)
|
||||
for i,obj in ipairs(sealedTokens) do
|
||||
chaosbag.putObject(obj)
|
||||
end
|
||||
sealedTokens = { }
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,45 +1,7 @@
|
||||
function onload()
|
||||
chaosbag = getChaosBag()
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {
|
||||
["0"] = true
|
||||
}
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if name == "0" then
|
||||
self.addContextMenuItem("Seal 0", function(playerColor) sealToken(url, playerColor) end)
|
||||
end
|
||||
end
|
||||
end
|
||||
SHOW_SINGLE_RELEASE = true
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,81 +1,7 @@
|
||||
function onload()
|
||||
mode = "Bless"
|
||||
chaosbag = getChaosBag()
|
||||
manager = getObjectFromGUID("5933fb")
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {
|
||||
["Bless"] = true
|
||||
}
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens, true)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if name == mode then
|
||||
self.addContextMenuItem("Seal " .. mode, function(playerColor) sealToken(url, playerColor) end, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
SHOW_SINGLE_RELEASE = true
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
local guid = obj.getGUID()
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
table.insert(tokensTaken[mode], guid)
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Sealing " .. mode .. " token " .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
if #sealedTokens == 0 then return end
|
||||
local token = sealedTokens[#sealedTokens]
|
||||
if token ~= nil then
|
||||
local guid = token.getGUID()
|
||||
chaosbag.putObject(token)
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
for i,v in ipairs(tokensTaken[mode]) do
|
||||
if v == guid then
|
||||
table.remove(tokensTaken[mode], i)
|
||||
break
|
||||
end
|
||||
end
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", mode)
|
||||
printToAll("Releasing " .. mode .. " token" .. manager.call("getTokenCount"))
|
||||
end
|
||||
|
||||
table.remove(sealedTokens)
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,67 +1,8 @@
|
||||
VALID_TOKENS = {
|
||||
Skull=true,
|
||||
Cultist=true,
|
||||
Tablet=true,
|
||||
["Elder Thing"]=true
|
||||
["Skull"] = true,
|
||||
["Cultist"] = true,
|
||||
["Tablet"] = true,
|
||||
["Elder Thing"] = true,
|
||||
}
|
||||
|
||||
function onload()
|
||||
chaosbag = getChaosBag()
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if VALID_TOKENS[name] ~= nil then
|
||||
self.addContextMenuItem("Seal " .. name, function(playerColor) sealToken(url, playerColor) end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
printToColor("Releasing token", playerColor)
|
||||
for i,obj in ipairs(sealedTokens) do
|
||||
chaosbag.putObject(obj)
|
||||
end
|
||||
sealedTokens = { }
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,67 +1,8 @@
|
||||
VALID_TOKENS = {
|
||||
Skull=true,
|
||||
Cultist=true,
|
||||
Tablet=true,
|
||||
["Elder Thing"]=true
|
||||
["Skull"] = true,
|
||||
["Cultist"] = true,
|
||||
["Tablet"] = true,
|
||||
["Elder Thing"] = true,
|
||||
}
|
||||
|
||||
function onload()
|
||||
chaosbag = getChaosBag()
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if VALID_TOKENS[name] ~= nil then
|
||||
self.addContextMenuItem("Seal " .. name, function(playerColor) sealToken(url, playerColor) end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
printToColor("Releasing token", playerColor)
|
||||
for i,obj in ipairs(sealedTokens) do
|
||||
chaosbag.putObject(obj)
|
||||
end
|
||||
sealedTokens = { }
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,60 +1,5 @@
|
||||
function onload()
|
||||
chaosbag = getChaosBag()
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {
|
||||
["Elder Sign"] = true
|
||||
}
|
||||
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Token", releaseTokens)
|
||||
for url,name in pairs(IMAGE_TOKEN_MAP) do
|
||||
if name == "Elder Sign" then
|
||||
self.addContextMenuItem("Seal Elder Sign", function(playerColor) sealToken(url, playerColor) end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
printToColor("Releasing token", playerColor)
|
||||
for i,obj in ipairs(sealedTokens) do
|
||||
chaosbag.putObject(obj)
|
||||
end
|
||||
sealedTokens = { }
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -1,97 +1,6 @@
|
||||
function onload()
|
||||
chaosbag = getChaosBag()
|
||||
manager = getObjectFromGUID("5933fb")
|
||||
sealedTokens = { }
|
||||
IMAGE_TOKEN_MAP = { }
|
||||
for i,v in pairs(Global.getVar("IMAGE_TOKEN_MAP")) do
|
||||
IMAGE_TOKEN_MAP[i] = v
|
||||
end
|
||||
VALID_TOKENS = {}
|
||||
INVALID_TOKENS = {}
|
||||
|
||||
readBag()
|
||||
end
|
||||
SHOW_READ_BAG = true
|
||||
|
||||
function sealToken(url, playerColor)
|
||||
local pos = self.getPosition()
|
||||
|
||||
local name = IMAGE_TOKEN_MAP[url]
|
||||
for i,obj in ipairs(chaosbag.getObjects()) do
|
||||
if obj.name == name then
|
||||
chaosbag.takeObject({
|
||||
position={ pos.x, pos.y + 1, pos.z },
|
||||
index=i-1,
|
||||
smooth=false,
|
||||
callback_function=_sealToken
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
printToColor(name .. " token not found in bag", playerColor)
|
||||
end
|
||||
|
||||
function _sealToken(obj)
|
||||
table.insert(sealedTokens, obj)
|
||||
local guid = obj.getGUID()
|
||||
local name = obj.getName()
|
||||
if name == "Bless" or name == "Curse" then
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
table.insert(tokensTaken[name], guid)
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", name)
|
||||
printToAll("Sealing " .. name .. " token " .. manager.call("getTokenCount"))
|
||||
end
|
||||
end
|
||||
|
||||
function releaseTokens(playerColor)
|
||||
if #sealedTokens == 0 then return end
|
||||
for i,token in ipairs(sealedTokens) do
|
||||
local guid = token.getGUID()
|
||||
local name = token.getName()
|
||||
chaosbag.putObject(token)
|
||||
if name == "Bless" or name == "Curse" then
|
||||
local tokensTaken = manager.getVar("tokensTaken")
|
||||
for i,v in ipairs(tokensTaken[name]) do
|
||||
if v == guid then
|
||||
table.remove(tokensTaken[name], i)
|
||||
break
|
||||
end
|
||||
end
|
||||
manager.setVar("tokensTaken", tokensTaken)
|
||||
manager.setVar("mode", name)
|
||||
printToAll("Releasing " .. name .. " token" .. manager.call("getTokenCount"))
|
||||
end
|
||||
end
|
||||
|
||||
sealedTokens = { }
|
||||
end
|
||||
|
||||
function getChaosBag()
|
||||
local items = getObjectFromGUID("83ef06").getObjects()
|
||||
local chaosbag = nil
|
||||
for i,v in ipairs(items) do
|
||||
if v.getDescription() == "Chaos Bag" then
|
||||
chaosbag = getObjectFromGUID(v.getGUID())
|
||||
break
|
||||
end
|
||||
end
|
||||
if chaosbag == nil then printToAll("No chaos bag found") end
|
||||
return chaosbag
|
||||
end
|
||||
|
||||
function readBag()
|
||||
-- add menu items
|
||||
self.clearContextMenu()
|
||||
self.addContextMenuItem("Release Tokens", releaseTokens)
|
||||
|
||||
local bagTokens = { }
|
||||
local tokens = chaosbag.getObjects()
|
||||
for i,token in ipairs(tokens) do
|
||||
bagTokens[token.name] = true
|
||||
end
|
||||
|
||||
for url,token in pairs(IMAGE_TOKEN_MAP) do
|
||||
if bagTokens[token] then
|
||||
self.addContextMenuItem("Seal " .. token, function(playerColor) sealToken(url, playerColor) end, true)
|
||||
end
|
||||
end
|
||||
self.addContextMenuItem("Refresh Seal Options", readBag)
|
||||
end
|
||||
require("playercards/CardsThatSealTokens")
|
||||
|
@ -67,7 +67,7 @@ isDES = false
|
||||
function onSave()
|
||||
return JSON.encode({
|
||||
zoneID = zoneID,
|
||||
playerColor = PLAYER_COLOR,
|
||||
playerColor = playerColor,
|
||||
activeInvestigatorId = activeInvestigatorId,
|
||||
isDrawButtonVisible = isDrawButtonVisible
|
||||
})
|
||||
@ -80,6 +80,7 @@ function onLoad(save_state)
|
||||
STAT_TRACKER = getObjectFromGUID(STAT_TRACKER_GUID)
|
||||
RESOURCE_COUNTER = getObjectFromGUID(RESOURCE_COUNTER_GUID)
|
||||
|
||||
-- button creation
|
||||
for i = 1, 6 do
|
||||
makeDiscardButton(DISCARD_BUTTON_OFFSETS[i], {-3.85, 3, 10.38}, i)
|
||||
end
|
||||
@ -94,7 +95,7 @@ function onLoad(save_state)
|
||||
})
|
||||
|
||||
self.createButton({
|
||||
click_function = "drawChaostokenButton",
|
||||
click_function = "drawChaosTokenButton",
|
||||
function_owner = self,
|
||||
position = {1.85, 0, -0.74},
|
||||
rotation = {0, -45, 0},
|
||||
@ -113,10 +114,11 @@ function onLoad(save_state)
|
||||
font_size = 180
|
||||
})
|
||||
|
||||
-- save state loading
|
||||
local state = JSON.decode(save_state)
|
||||
if state ~= nil then
|
||||
zoneID = state.zoneID
|
||||
PLAYER_COLOR = state.playerColor
|
||||
playerColor = state.playerColor
|
||||
activeInvestigatorId = state.activeInvestigatorId
|
||||
isDrawButtonVisible = state.isDrawButtonVisible
|
||||
end
|
||||
@ -133,15 +135,6 @@ end
|
||||
-- utility functions
|
||||
---------------------------------------------------------
|
||||
|
||||
function log(message)
|
||||
if DEBUG then print(message) end
|
||||
end
|
||||
|
||||
-- send messages to player who clicked button if no seated player found
|
||||
function setMessageColor(color)
|
||||
messageColor = Player[PLAYER_COLOR].seated and PLAYER_COLOR or color
|
||||
end
|
||||
|
||||
function spawnDeckZone()
|
||||
spawnObject({
|
||||
position = self.positionToWorld({-1.4, 0, 0.3 }),
|
||||
@ -165,7 +158,9 @@ function searchArea(origin, size)
|
||||
})
|
||||
end
|
||||
|
||||
function doNotReady(card) return card.getVar("do_not_ready") or false end
|
||||
function doNotReady(card)
|
||||
return card.getVar("do_not_ready") or false
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
-- Discard buttons
|
||||
@ -231,19 +226,18 @@ end
|
||||
-- Upkeep button
|
||||
---------------------------------------------------------
|
||||
|
||||
function doUpkeep(_, color, alt_click)
|
||||
setMessageColor(color)
|
||||
|
||||
-- right-click binds to new player color
|
||||
if alt_click then
|
||||
PLAYER_COLOR = color
|
||||
printToColor("Upkeep button bound to " .. color, color)
|
||||
function doUpkeep(_, clickedByColor, isRightClick)
|
||||
-- right-click allow color changing
|
||||
if isRightClick then
|
||||
changeColor(clickedByColor)
|
||||
return
|
||||
end
|
||||
|
||||
local forcedLearning = false
|
||||
-- send messages to player who clicked button if no seated player found
|
||||
messageColor = Player[playerColor].seated and playerColor or clickedByColor
|
||||
|
||||
-- unexhaust cards in play zone, flip action tokens and find forcedLearning
|
||||
local forcedLearning = false
|
||||
for _, v in ipairs(searchArea(PLAY_ZONE_POSITION, PLAY_ZONE_SCALE)) do
|
||||
local obj = v.hit_object
|
||||
if obj.getDescription() == "Action Token" and obj.is_face_down then
|
||||
@ -304,7 +298,7 @@ function doUpkeep(_, color, alt_click)
|
||||
if forcedLearning then
|
||||
printToColor("Wow, did you really take 'Versatile' to play Patrice with 'Forced Learning'? Choose which draw replacement effect takes priority and draw cards accordingly.", messageColor)
|
||||
else
|
||||
local handSize = #Player[PLAYER_COLOR].getHandObjects()
|
||||
local handSize = #Player[playerColor].getHandObjects()
|
||||
if handSize < 5 then
|
||||
local cardsToDraw = 5 - handSize
|
||||
printToColor("Drawing " .. cardsToDraw .. " cards (Patrice)", messageColor)
|
||||
@ -328,7 +322,8 @@ end
|
||||
|
||||
-- function for "draw 1 button" (that can be added via option panel)
|
||||
function doDrawOne(_, color)
|
||||
setMessageColor(color)
|
||||
-- send messages to player who clicked button if no seated player found
|
||||
messageColor = Player[playerColor].seated and playerColor or color
|
||||
drawCardsWithReshuffle(1)
|
||||
end
|
||||
|
||||
@ -351,7 +346,7 @@ function drawCardsWithReshuffle(numCards)
|
||||
end
|
||||
|
||||
if topCard ~= nil then
|
||||
topCard.deal(numCards, PLAYER_COLOR)
|
||||
topCard.deal(numCards, playerColor)
|
||||
numCards = numCards - 1
|
||||
if numCards == 0 then return end
|
||||
end
|
||||
@ -402,7 +397,7 @@ end
|
||||
|
||||
function drawCards(numCards)
|
||||
if drawDeck == nil then return end
|
||||
drawDeck.deal(numCards, PLAYER_COLOR)
|
||||
drawDeck.deal(numCards, playerColor)
|
||||
end
|
||||
|
||||
function shuffleDiscardIntoDeck()
|
||||
@ -415,8 +410,7 @@ end
|
||||
|
||||
-- discard a random non-hidden card from hand
|
||||
function doDiscardOne()
|
||||
local handColor = getHandColor()
|
||||
local hand = Player[handColor].getHandObjects()
|
||||
local hand = Player[playerColor].getHandObjects()
|
||||
if #hand == 0 then
|
||||
broadcastToAll("Cannot discard from empty hand!", "Red")
|
||||
else
|
||||
@ -444,18 +438,72 @@ function doDiscardOne()
|
||||
end
|
||||
end
|
||||
|
||||
-- gets the hand color of the closest seated player (by roughly cutting the table into quarters)
|
||||
function getHandColor()
|
||||
for _, handColor in ipairs(Player.getAvailableColors()) do
|
||||
local handPosition = Player[handColor].getHandTransform().position
|
||||
---------------------------------------------------------
|
||||
-- color related functions
|
||||
---------------------------------------------------------
|
||||
|
||||
if (PLAYER_COLOR == "White" and handPosition.x < -42 and handPosition.z > 0)
|
||||
or (PLAYER_COLOR == "Orange" and handPosition.x < -42 and handPosition.z < 0)
|
||||
or (PLAYER_COLOR == "Green" and handPosition.x > -42 and handPosition.z > 0)
|
||||
or (PLAYER_COLOR == "Red" and handPosition.x > -42 and handPosition.z < 0) then
|
||||
return handColor
|
||||
-- changes the player color
|
||||
function changeColor(clickedByColor)
|
||||
local colorList = {
|
||||
"White",
|
||||
"Brown",
|
||||
"Red",
|
||||
"Orange",
|
||||
"Yellow",
|
||||
"Green",
|
||||
"Teal",
|
||||
"Blue",
|
||||
"Purple",
|
||||
"Pink"
|
||||
}
|
||||
|
||||
-- remove existing colors from the list of choices
|
||||
for _, existingColor in ipairs(Player.getAvailableColors()) do
|
||||
for i, newColor in ipairs(colorList) do
|
||||
if existingColor == newColor then
|
||||
table.remove(colorList, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- show the option dialog for color selection to the player that triggered this
|
||||
Player[clickedByColor].showOptionsDialog("Select a new color:", colorList, _, function(color)
|
||||
local HAND_ZONE_GUIDS = {
|
||||
"a70eee", -- White
|
||||
"5fe087", -- Orange
|
||||
"0285cc", -- Green
|
||||
"be2f17" -- Red
|
||||
}
|
||||
local index
|
||||
local startPos = self.getPosition()
|
||||
|
||||
-- get respective hand zone by position
|
||||
if startPos.x < -42 then
|
||||
if startPos.z > 0 then
|
||||
index = 1
|
||||
else
|
||||
index = 2
|
||||
end
|
||||
else
|
||||
if startPos.z > 0 then
|
||||
index = 3
|
||||
else
|
||||
index = 4
|
||||
end
|
||||
end
|
||||
|
||||
-- update the color of the hand zone
|
||||
local handZone = getObjectFromGUID(HAND_ZONE_GUIDS[index])
|
||||
handZone.setValue(color)
|
||||
|
||||
-- if the seated player clicked this, reseat him to the new color
|
||||
if clickedByColor == playerColor then
|
||||
Player[playerColor].changeColor(color)
|
||||
end
|
||||
|
||||
-- update the internal variable
|
||||
playerColor = color
|
||||
end)
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
@ -696,8 +744,8 @@ end
|
||||
-- calls to 'Global' / functions for calls from outside
|
||||
---------------------------------------------------------
|
||||
|
||||
function drawChaostokenButton(_, _, isRightClick)
|
||||
Global.call("drawChaostoken", {self, DRAWN_CHAOS_TOKEN_OFFSET, isRightClick})
|
||||
function drawChaosTokenButton(_, _, isRightClick)
|
||||
Global.call("drawChaosToken", {self, DRAWN_CHAOS_TOKEN_OFFSET, isRightClick})
|
||||
end
|
||||
|
||||
function drawEncountercard(_, _, isRightClick)
|
||||
|
@ -43,9 +43,9 @@ do
|
||||
|
||||
-- Returns the color of the player's hand that is seated next to the playermat
|
||||
---@param matColor String Color of the playermat
|
||||
PlaymatApi.getHandColor = function(matColor)
|
||||
PlaymatApi.getPlayerColor = function(matColor)
|
||||
local mat = getObjectFromGUID(MAT_IDS[matColor])
|
||||
return mat.call("getHandColor")
|
||||
return mat.getVar("playerColor")
|
||||
end
|
||||
|
||||
-- Returns if there is the card "Dream-Enhancing Serum" on the requested playermat
|
||||
|
Loading…
Reference in New Issue
Block a user